Android踩坑日记:点击变暗效果的ImageView实现原理

来源:互联网 发布:中国电信网络传真 编辑:程序博客网 时间:2024/06/08 09:04

很多时候我们使用ImagView显示图片,无论是Gilde,Fresco等图片显示框架,比如设置中心更换头像,网格相册点击预览,选择等情况,会遇到点击变暗的交互需求。

  • 源码分析
        我们想的办法是自定义一个ImageView,当点击图片时,是不是有回调方法来同时改变图片的滤镜或者蒙版等。
        特意去看了View.java的源码(ImageView继承View),想看看View被点击之后是是否有回调函数可用。
View的onTouchEvent()方法case MotionEvent.ACTION_DOWN:              mHasPerformedLongPress = false;             if (performButtonActionOnTouchDown(event)) {                          break;                }            // Walk up the hierarchy to determine if we're inside a scrolling container.            boolean isInScrollingContainer = isInScrollingContainer();            // For views inside a scrolling container, delay the pressed feedback for            // a short period in case this is a scroll.             if (isInScrollingContainer) {                   mPrivateFlags |= PFLAG_PREPRESSED;                   if (mPendingCheckForTap == null) {                              mPendingCheckForTap = new CheckForTap();                     }                       postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());                     } else {                          // Not inside a scrolling container, so show the feedback right away                          setPressed(true);                          checkForLongClick(0);                      }                      break;  

意思就是case: MotionEvent.ACTION_DOWN,按下去的时候事件发生时,检测View是否被点击了,如果点击了就setPressed(true);把状态标记为已点击
对应的case: MotionEvent.ACTION_UP,松开手的时候会检测是否是unpressed,如果是就setPressed(false);把状态标记为未点击。

setPress(boolean pressed)这个方法,定义如下

  /**     * Sets the pressed state for this view.     *     * @see #isClickable()     * @see #setClickable(boolean)     *     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts     *        the View's internal state from a previously set "pressed" state.     */    public void setPressed(boolean pressed) {        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);        if (pressed) {            mPrivateFlags |= PFLAG_PRESSED;        } else {            mPrivateFlags &= ~PFLAG_PRESSED;        }        if (needsRefresh) {            refreshDrawableState();        }        dispatchSetPressed(pressed);    }

就是说View按下时会调用这个方法改变view的状态,那么我们就可以在这个方法中做文章,重写这个方法。当参数是true时,使用颜色矩阵ColorMetrix来改变drawable的滤镜,当参数是false时,还原图像

/*点击变暗效果的ImageView*/public class MaskImageView extends ImageView {    private boolean touchEffect = true;    public final float[] BG_PRESSED = new float[] { 1, 0, 0, 0, -50, 0, 1, 0, 0, -50, 0, 0, 1, 0, -50, 0, 0, 0, 1, 0 };    public final float[] BG_NOT_PRESSED = new float[] { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 };    public MaskImageView(Context context) {        super(context);    }    public MaskImageView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MaskImageView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public MaskImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);    }    @Override    public void setPressed(boolean pressed) {        updateView(pressed);        super.setPressed(pressed);    }    /**     * 根据是否按下去来刷新bg和src     *     * @param pressed     */    private void updateView(boolean pressed){        //如果没有点击效果        if( !touchEffect ){            return;        }        if( pressed ){            /**             * 通过设置滤镜来改变图片亮度             */            this.setDrawingCacheEnabled(true);            this.setColorFilter( new ColorMatrixColorFilter(BG_PRESSED) ) ;            //此为src,背景用getBackground()            this.getDrawable().setColorFilter( new ColorMatrixColorFilter(BG_PRESSED) );        }else{            this.setColorFilter( new ColorMatrixColorFilter(BG_NOT_PRESSED) ) ;            this.getDrawable().setColorFilter( new ColorMatrixColorFilter(BG_NOT_PRESSED) );        }    }}
原创粉丝点击