用View来进行动态绘图,要解决的一个很重要的问题就是如何重绘屏幕。Android的View类中提供了一个postInvalidate()方法,会自动调用View中onDraw方法来重新绘制屏幕。
下面一段代码实现了任意线拖动红线的位置。并能自动自动更新线的位置.
/*
* 用线程来更新View, 画一条线
*/
public class ThreadUpdateView extends View
{
Paint paint = null;
int y = 0;
public ThreadUpdateView(Context context)
{
super(context);
paint = new Paint();
MyThread myThread = new MyThread();
myThread.start(); //启动线程后红线会自动下移.
this.setFocusable(true);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
canvas.drawLine(0, y, 444, y, paint);//画线
}
class MyThread extends Thread
{
@Override
public void run()
{
//一直让他的值加, 小于400
while (y < 400)
{
y++;
try
{
Thread.sleep(100); //慢点更新
} catch (InterruptedException e)
{
e.printStackTrace();
}
postInvalidate();//View里面的方法, 让重画, 及重新调用onDraw方法. 因为y已经更新.
}
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event)
{
System.out.println("View onKeyUp " + event.getAction());
return super.onKeyUp(keyCode, event);
}
/*
* 做一个功能, 想把线拖动到哪里就拖动到哪里.
*/
@Override
public boolean onTouchEvent(MotionEvent event)
{
System.out.println("View "+event.getAction() + " " + event.getX() + " "
+ event.getY());
//return super.onTouchEvent(event);
y = (int) event.getY(); //将当前点击拖动的位置赋值给y
postInvalidate(); //重新调用onDraw()方法, 来进行重绘.
return true;
}
}
![](https://img-my.csdn.net/uploads/201210/11/1349930337_5732.png)
在此会出现两个关于屏幕事件的问题:
一、如何让View来捕获按键及触屏事件, 而不是Activity?
我们知道,当你点击屏幕的时候,系统是先响应Activity中的onTouchEvent方法(onKeyUp等方法也是)的,而不是响应我们自己设定显示的View。这就会造成我们在View中写的onTouchEvent失效。
有2中解决办法:
方法1. 使用代理。即在Activity中的onTouchEvent方法中直接调用ThreadUpdateView实例中的onTouchEvent方法。
方法2. 使View强行获得焦点。在View的构造方法中设置
this.setFocusable(true);
二、如何让触摸事件不传递给Activity?
我们知道,在Android中触摸事件是能进行传递的。如View执行完后, 按下事件就传递给Activity。
那么如何让他不传递呢?
解决方法:
将onTouchEvent的返回值写成
return true; (这样写之后一些传递事件就失效了, 如回退键等)
而不是return super.onTouchEvent(event);
注意:一般
主线程负责绘制UI,所以主线程中
不能出现长循环,否则会让界面卡死(点击无响应)。出现长循环时,即使调用重绘方法postInvalidate(),也不会响应。所以绘制动画时一定使用子线程。