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

很多时候我们使用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) );
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值