先看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); } } }
NewLayOut 类 继承 LinearLayout,因为需要在LinearLayout里面画图
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(); } }
编写的过程中发现一点问题:
第一:画图与循环同步的问题
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(),把下一次移动的数据准备好了。所以侦数就稍有上升了。
转自:http://www.pin5i.com/showtopic-android-qq-top-bar-oval-transparent-background-moving-effect.html
时间: 2024-12-07 03:25:43