Ripple effect for ImageView in RecyclerView / 点击 RecyclerView ImageView时的水纹效果

Implement ripple effect on ImageView in RecyclerView. 首先要明确这个效果只在 API level >= 21 的机器上有效。 需要做的事情:

  1. 使用 appcompat library theme 并继承 AppCompatActivity;
  2. 继承 ImageView,在 attrs.xml 中添加一个新的属性 foreground attribute, 源码 ForegroundImageView:

     <?xml version="1.0" encoding="utf-8"?>
     <resources>
       <declare-styleable name="ForegroundImageView">
         <attr name="android:foreground"/>
       </declare-styleable>
     </resources>
    
  3. 然后在布局文件中使用这个 ImageView子类,并添加android:foreground:

     <?xml version="1.0" encoding="utf-8"?>
     <me.li2.android.photogallery.ForegroundImageView
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:contentDescription="@string/app_name"
         android:id="@+id/gallery_item_imageView"
         android:layout_width="match_parent"
         android:layout_height="120dp"
         android:foreground="?android:attr/selectableItemBackground"
         android:scaleType="centerCrop" >
     </me.li2.android.photogallery.ForegroundImageView>
    

Refer to:

解决 ripple 不从触点开始的问题

Make sure that the ripple starts from the correct point. Bug: With Android 5.0 the ripple drawable will animate in the foreground, but the ripple will always begin at the center of the view. A solution can be:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onTouchEvent(MotionEvent e) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (e.getActionMasked() == MotionEvent.ACTION_DOWN) {
            if (mForeground != null)
                mForeground.setHotspot(e.getX(), e.getY());
        }
    }
    return super.onTouchEvent(e);
}

Refer to:

尝试过的其它方法,但是无效:

android:focusable="true"
android:clickable="true"
android:background="?android:attr/selectableItemBackground"

还尝试把 ImageView 嵌套在 FrameLayout 中,设置 FrameLayout 的 foreground 属性,依然无效。如果直接设置 ImageView 的 android:foreground 也无效,必须继承 ImageView。原因不知。

Refer to: