Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom View: Redraw view canvas on Press

I'm working on custom view, which have to draw custom canvas when pressed and other if not. I have basically overriden only methods onMeasure and onDraw. In Constructor I have set: setFocusable(true) and setDrawingCacheEnabled(true)

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

I want this effect: view looks like pressed after onDown and like non-pressed after onUp/onCancel motion event. Normally I was using <selector> but now i have to do a little bit of work with canvas. (one draws circle around view, other some background effects)

How can I set canvas for different press states?

like image 970
VizGhar Avatar asked Feb 23 '26 13:02

VizGhar


1 Answers

Thanks to pskink I was able to create complete solutions so here is it.

If you want to create custom view in which have to be your custom drawings for different touch states (pressed, selected, focused etc.) and you didn't know whether this view will be placed inside other View that can intercept touch events or the view structure is even more difficult. You should implement the behavior as follows

  1. Create custom Drawable
  2. in overriden method isStateful() return true value (needed to hold different states)
  3. override onStateChange method and call invalidateSelf() if state was changed.
  4. override draw method to implement custom drawing based on drawableState (see getState method)
  5. in custom view override method that should draw drawable (for example setImageDrawable, setBackground... depends on your needs)
  6. in the method call supermethod with your custom Drawable class

Example:

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);
        }
    }
}
like image 98
VizGhar Avatar answered Feb 26 '26 02:02

VizGhar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!