自定义视图:按下时重绘视图画布

时间:2014-06-11 07:06:43

标签: android canvas motionevent

我正在处理自定义视图,必须在按下时绘制自定义画布,否则必须绘制其他画布。我基本上只覆盖方法onMeasureonDraw。在构造函数中,我设置了setFocusable(true)setDrawingCacheEnabled(true)

public class CircularImageView extends ImageView{
    //...
    @Override
    protected void onDraw(Canvas canvas) {
        // ...
        if (isPressed() || isSelected() || isFocused()){
            // code when pressed
        }
        else{
            // otherwise
        }
    }
}

我想要这样的效果:视图看起来像onDown之后的按下,就像onUp / onCancel动作事件之后的未按下一样。通常我使用<selector>,但现在我必须使用canvas进行一些工作。 (一个围绕视图绘制圆圈,其他一些背景效果)

如何为不同的按下状态设置画布?

2 个答案:

答案 0 :(得分:3)

感谢pskink我能够创建完整的解决方案,所以就在这里。

如果您想创建自定义视图,其中必须是针对不同触摸状态(按下,选择,聚焦等)的自定义绘图,并且您不知道此视图是否将放置在可以拦截触摸的其他视图中事件或视图结构更加困难。您应该按如下方式实现行为

  1. 创建自定义Drawable
  2. in overriden method isStateful()返回true值(需要保持不同的状态)
  3. 覆盖onStateChange方法,如果状态已更改,请致电invalidateSelf()
  4. 覆盖draw方法以基于drawableState实现自定义绘图(请参阅getState方法)
  5. 在自定义视图覆盖方法中应该绘制drawable(例如setImageDrawablesetBackground ...取决于您的需求)
  6. 在方法中使用您的自定义Drawable类调用supermethod
  7. 示例:

    public class CircularImageView extends ImageView{
    
        @Override
        public void setImageDrawable(Drawable drawable) {
            super.setImageDrawable(new CustomDrawable(
                ((BitmapDrawable)drawable).getBitmap()));
        }
    
        protected class CustomDrawable extends Drawable {
            // 
            private Bitmap bitmap;
    
            public CustomDrawable(Bitmap bitmap){
                this.bitmap = bitmap;
            }
    
            @Override
            public boolean isStateful() {
                // always return true
                return true;
            }
    
            @Override
            public int getOpacity() {
                // see documentation on android developers site
                return PixelFormat.OPAQUE;
            }
    
            @Override
            public void setColorFilter(ColorFilter colorFilter) {
            }
    
            @Override
            public void setAlpha(int i) {
            }
    
            boolean pressed = false;
    
            @Override
            protected boolean onStateChange(int[] states) {
                // simplified but working
                for (int state : getState()){
                    if (state == android.R.attr.state_pressed ||
                        state == android.R.attr.state_focused)
                            pressed = true;
                    else pressed = false;
                }
                invalidateSelf();
                return true;
            }
    
            @Override
            public void draw(Canvas canvas) {
                // very simplified example
                canvas.drawBitmap(bitmap,0,0,paint);
                circlePaint.setColor(pressed ? colorActive : colorPassive);
                canvas.drawCircle(0, 0, 100, 100);
            }
        }
    }
    

答案 1 :(得分:1)

创建一个布尔值来控制何时按下视图并覆盖onTouchEvent以将其设置为true或false:

private boolean pressed;

@Override
protected void onDraw(Canvas canvas) {
    // ...
    if (pressed){
        // code when pressed
    }
    else{
        // otherwise
    }
}

@Override
public boolean onTouchEvent(MotionEvent event){
    switch(event.getAction()){
        case MotionEvent.ACTION_DOWN:
            pressed = true;
            this.invalidate();
            break;
        case MotionEvent.ACTION_UP:
            pressed = false;
            this.invalidate();
            break;
     }
}