Android踩坑日记:点击变暗效果的ImageView实现原理
Posted tuke_tuke
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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) );
以上是关于Android踩坑日记:点击变暗效果的ImageView实现原理的主要内容,如果未能解决你的问题,请参考以下文章
Android 踩坑日记 - RecyclerView 布局问题
Android 自定义Button 圆角大小可设置+点击变暗效果