onTouch 调用使 onDraw 无效 - 不流畅
onTouch calling invalidate onDraw - not smooth
我的自定义视图中有一个代码,如果我触摸,就会绘制一个圆圈。当我移动圆圈时,请跟随。代码如下
// override onDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (circleBounds != null) {
canvas.drawArc(circleBounds, 360, 360, false, mPaint);
}
}
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
circleBounds.set(mX - mRadius, mY - mRadius, mX + mRadius, mY + mRadius);
invalidate();
}
//override the onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startTouch(x, y);
break;
case MotionEvent.ACTION_MOVE:
startTouch(x, y);
break;
}
return true;
}
当我慢慢移动的时候,动作很流畅。但是当我快速移动时,可以感觉到闪烁。我猜 invalidate() 发生了很多次,导致闪烁。有没有办法让它更平滑(减少绘制圆上的闪烁)?
public class MyView extend FrameLayout implement OnTouchListener{
public MyView(params){
init();
}
private void init(){
ImageView imageView = new ImageView();
imageView.setImageResource(R.mipmap.logo);
addView(imageview)
imageView.setOnTouchListener(this);
}
private boolean onTouch(params){
//some logic to control
//use imageView.setLayoutParams() instead of invalidate();
}
}
无效不是你的问题,系统有双缓冲,你不应该看到闪烁。
从您的代码中,我可以想到两种改进方法:
- 在 onStartTouch 中调用 mPath.moveTo()。目前还不清楚为什么需要 mPath,但这条路径会不断增长,会需要更多的内存
- canvas.drawArc 由 CPU 渲染(它创建一个位图并在每次调用 onDraw 时将圆弧绘制到其中)。将圆圈渲染成位图并在 onDraw 中绘制该位图会更快。如果你继续使用相同的位图,它会加载一次到 GPU 并且绘图会更快
我知道这个问题很老,但如果其他人有同样的问题,解决方案是使用 postInvalidate()
而不是 onTouchEvent
方法中的 invalidate()
,这将让它更流畅。
由于我们在 onTouchEvent
中收到许多事件,将无效调用放入事件队列以供将来处理比立即执行更有效。
我的自定义视图中有一个代码,如果我触摸,就会绘制一个圆圈。当我移动圆圈时,请跟随。代码如下
// override onDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (circleBounds != null) {
canvas.drawArc(circleBounds, 360, 360, false, mPaint);
}
}
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
circleBounds.set(mX - mRadius, mY - mRadius, mX + mRadius, mY + mRadius);
invalidate();
}
//override the onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startTouch(x, y);
break;
case MotionEvent.ACTION_MOVE:
startTouch(x, y);
break;
}
return true;
}
当我慢慢移动的时候,动作很流畅。但是当我快速移动时,可以感觉到闪烁。我猜 invalidate() 发生了很多次,导致闪烁。有没有办法让它更平滑(减少绘制圆上的闪烁)?
public class MyView extend FrameLayout implement OnTouchListener{
public MyView(params){
init();
}
private void init(){
ImageView imageView = new ImageView();
imageView.setImageResource(R.mipmap.logo);
addView(imageview)
imageView.setOnTouchListener(this);
}
private boolean onTouch(params){
//some logic to control
//use imageView.setLayoutParams() instead of invalidate();
}
}
无效不是你的问题,系统有双缓冲,你不应该看到闪烁。 从您的代码中,我可以想到两种改进方法:
- 在 onStartTouch 中调用 mPath.moveTo()。目前还不清楚为什么需要 mPath,但这条路径会不断增长,会需要更多的内存
- canvas.drawArc 由 CPU 渲染(它创建一个位图并在每次调用 onDraw 时将圆弧绘制到其中)。将圆圈渲染成位图并在 onDraw 中绘制该位图会更快。如果你继续使用相同的位图,它会加载一次到 GPU 并且绘图会更快
我知道这个问题很老,但如果其他人有同样的问题,解决方案是使用 postInvalidate()
而不是 onTouchEvent
方法中的 invalidate()
,这将让它更流畅。
由于我们在 onTouchEvent
中收到许多事件,将无效调用放入事件队列以供将来处理比立即执行更有效。