android仿QQ topbar按钮被选择时背景图片移动效果

ANDROID QQ截图:



DEMO截图:


 

public class test3 extends Activity {
        
        private NewLayOut layout;
        
        private myThread mThread;
        
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
            layout = (NewLayOut) inflater.inflate(R.layout.move, null);
            
            ImageView button = (ImageView)layout.findViewById(R.id.ImageView01);
            button.setOnClickListener(mClickListener);
            ImageView button2 = (ImageView)layout.findViewById(R.id.ImageView02);
            button2.setOnClickListener(mClickListener);
            ImageView button3 = (ImageView)layout.findViewById(R.id.ImageView03);
            button3.setOnClickListener(mClickListener);
            
            this.setContentView(layout);
    }
    
    private View.OnClickListener mClickListener = new View.OnClickListener() {
                
                public void onClick(View v) {
                        startMove(v);
                }
        };
        
        private void startMove(View v)
    {
            stopThread();//停止之前的线程
                mThread = new myThread(v);
                mThread.start();
    }
        
        private void stopThread()
    {
            if (mThread != null)
                {
                    try
                        {
                            layout.mIsStop = true;
                                mThread.join();
                        }
                        catch(Exception e)
                        {
                                e.printStackTrace();
                        }
                }
    }
        
        class myThread extends Thread
    {
            private View mView;
            
            public myThread(View v){ this.mView = v; }
            
                public void run() {
                        layout.doWork(this.mView);
                }
            
    }
}

 

package test3.program;

import android.content.Context;

import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

public class NewLayOut extends LinearLayout {

        private static final short SPEED = 15;
        
        private Context mContext;
        private Rect mNowRect;//当前的区域
        private Rect mEndRect;//结束的区域
        private BitmapDrawable mSelecter;//移动的半透明背景bitmaip
        private boolean mSyn = false;//循环和onDraw同步
        public boolean mIsStop = false;//是否到达指定区域
        
        public NewLayOut(Context context) {
                super(context);
                init(context);
        }
        
        public NewLayOut(Context context, AttributeSet attrs) {
                super(context, attrs);
                init(context);
        }
        
        private void init(Context context)
        {
                mContext = context;
                mSelecter = new BitmapDrawable(
                                BitmapFactory.decodeResource(mContext.getResources(), 
                                                R.drawable.topbar_select));
                mNowRect = new Rect();
                mEndRect = new Rect();
        }
        
        protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2, int paramInt3, int paramInt4)
        {
                super.onLayout(paramBoolean, paramInt1, paramInt2, paramInt3, paramInt4);
                this.getChildAt(0).getHitRect(mNowRect);//取得第一个控制区域作为起始区域
        }
        
        /**
        * 
        * @param v 目标控件
        */
        public void doWork(View v)
        {
                v.getHitRect(this.mEndRect);
                
                if (this.mNowRect.right < this.mEndRect.right)
                {
                        work(new RunForword()
                        {
                                public void run()
                                {
                                        mNowRect.left += SPEED;//每次左边移动15格
                                        mNowRect.right += SPEED;//每次右边移动15格
                                        
                                        System.out.println("is run run run");
                                        
                                        if (mNowRect.right >= mEndRect.right)//如果移动超出或等于目标区域
                                                ReachRect();
                                }
                        });
                }
                else if(this.mNowRect.right > this.mEndRect.right)
                {
                        work(new RunForword()
                        {
                                public void run()
                                {
                                        mNowRect.left -= SPEED;//每次左边移动15格
                                        mNowRect.right -= SPEED;//每次右边移动15格
                                        
                                        if (mNowRect.right <= mEndRect.right)//如果移动超出或等于目标区域
                                                ReachRect();
                                }
                        });
                }
        }
        
        private void work(RunForword run)
        {
                this.mIsStop = false;
                while(!this.mIsStop)
                {
                        if(this.mSyn)//画图与循环同步
                        {
                                run.run();
                                System.out.println("is running!");
                                this.mSyn = false;
                                this.postInvalidate();
                                //Thread.sleep(35);
                        }
                }
        }
        
        /**
        * 到达目的地
        */
        private void ReachRect()
        {
                mNowRect.left = mEndRect.left;
                mNowRect.right = mEndRect.right;
                mIsStop = true;
        }
        
        protected void onDraw(Canvas canvas)
        {
                super.onDraw(canvas);
                
                mSelecter.setBounds(mNowRect);
                mSelecter.draw(canvas);
                this.mSyn = true;

                System.out.println("is ondraw");
        }
        
        public interface RunForword
        {
                void run();
        }
}

 

编写的过程中发现一点问题:

第一:画图与循环同步的问题

  1.  
    private void work(RunForword run)
            {
                    this.mIsStop = false;
                    while(!this.mIsStop)
                    {
                            if(this.mSyn)//画图与循环同步
                            {
                                    run.run();
                                    System.out.println("is running!");
                                    this.mSyn = false;
                                    this.postInvalidate();
                                    //Thread.sleep(35);
                            }
                    }
            }

如果把 if(this.mSyn) 这段去掉 看图:



 

就是while循环好多次之后,onDraw才执行一次。猜想onDraw在上一次未执行完之前是不会被执行第二次的(onDraw好像开了一个新线程画图,但看SDK源码实现没看出个端儿。),所以需要做一个这样的同步。这里是继承LinearLayout的,不知道直接继承View会不会出现这种情况。上面的程序,onDraw执行完的时间大概在Thread.sleep(35)这么多时间。

看看把 if(this.mSyn) 加上去后的打印数据 看图:



第二:把移动的运算部份run.run();的方法直接放到onDraw里面运算

private void work(RunForword run)
        {
                this.mIsStop = false;
                while(!this.mIsStop)
                {
                        if(this.mSyn)//画图与循环同步
                        {

                                System.out.println("is running!");
                                this.mSyn = false;
                                this.postInvalidate();
                                //Thread.sleep(35);
                        }
                }
        }
protected void onDraw(Canvas canvas)
        {
                super.onDraw(canvas);
                run.run();//大概时这个意思。。当实这样实写是不行的。
                mSelecter.setBounds(mNowRect);
                mSelecter.draw(canvas);
                this.mSyn = true;

                System.out.println("is ondraw");
        }

 

 这样做的话,发觉移动的侦数比较底下,分析了一下原因。首先上面讲的,因为onDraw在上一次未画完图之前,第二次是不会运行的。而while 循环又无视onDraw方法未执行完毕。所以在onDraw未执行完毕的过程中。运行run.run(),把下一次移动的数据准备好了。所以侦数就稍有上升了。(文/djking

reference: http://www.pin5i.com/showtopic-android-qq-top-bar-oval-transparent-background-moving-effect.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值