QQ顶栏椭圆透明背景移动的实现!

先看ANDROID QQ截图:
[img]http://dl.iteye.com/upload/attachment/300124/ba1e6613-cd88-3a02-90fe-dc29425571a4.png[/img]
再看DEMO截图:
[img]http://dl.iteye.com/upload/attachment/300126/18763953-75f0-34fd-92b8-d68a6a255d85.png[/img]
[img]http://dl.iteye.com/upload/attachment/300128/38a88b09-fd6c-3f50-aa82-7ae10b7c83d8.png[/img]

直接看代码:

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);
}

}
}


[color=red]NewLayOut 类 继承 LinearLayout[/color],因为需要在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);
}
}
}


如果把 [color=red]if(this.mSyn)[/color] 这段去掉 看图:

[img]http://dl.iteye.com/upload/attachment/300114/bc7af164-ed32-3d3c-9926-3db6328f1c83.png[/img]

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

看看把 [color=red]if(this.mSyn)[/color] 加上去后的打印数据 看图:

[img]http://dl.iteye.com/upload/attachment/300116/069f4aa3-e207-33f9-a42c-0c3140f1d386.png[/img]

第二:把移动的运算部份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(),把下一次移动的数据准备好了。所以侦数就稍有上升了。

最后附上DEMO的源码: [url=http://dl.iteye.com/topics/download/66bd15b9-8bda-30ed-a1f8-c07079d39970]test3.rar[/url]

如上描述,有不正确的地方,请指教。谢谢。。

完毕。

有关ANDROID QQ的一些实现方法,请听下回分解。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值