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();
}
}
编写的过程中发现一点问题:
第一:画图与循环同步的问题
-
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