在Android触摸事件中看不到点击水波纹效果

7
我在这里看到了一些解决方案,但它们都无法满足我的需求。我正在使用View.OnTouchListener类在我的应用程序代码中检测点击和拖动事件,但那美丽的波纹效果现在已经消失了(可能是因为我在MotionEvent手势到达View.OnClickListener之前就消耗掉了它。请注意,在MotionEvent.ACTION_DOWN块中出现的return true)。
我不能使用View.OnClickListener来检测点击事件,因为我的应用程序使用了多个复合手势(点击、点击-保持、点击-保持-拖动等)。请问是否有人能够分享一些关于如何使用Android触摸手势创建涟漪效果的指导?
以下是我的BaseAdapter类中View.OnTouchListener实现的代码片段:
v.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent ev) {
                switch (ev.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        if(mAppActionDownListener != null) {
                            mAppActionDownListener.onAppActionDown(appObjectList.get(position), v);
                        }
                        Log.d("COOK", "ACTION_DOWN: " + ev.getX() + ", " + ev.getY());
                        t1 = System.currentTimeMillis();
                        return true;

                    case MotionEvent.ACTION_UP:
                        Log.d("COOK", "ACTION_UP: " + ev.getX() + ", " + ev.getY());
                        t2 = System.currentTimeMillis();
                        if(Math.abs(t2-t1) <=300) {
                            //Toast.makeText(context, "Click event", Toast.LENGTH_SHORT).show();
                            if(mAppClickListener!=null) {
                                mAppClickListener.onAppClicked(appObjectList.get(position), v);
                            }
                        }

                        return false;

                    case MotionEvent.ACTION_MOVE:
                        Log.d("COOK", "ACTION_MOVE: " + ev.getX() + ", " + ev.getY());

                        ClipData.Item item = new ClipData.Item(appObjectList.get(position).getAppname()+"~"+appObjectList.get(position).getPackagename()+"~"+appObjectList.get(position).getAppicon());
                        ClipData dragData = new ClipData(
                                (CharSequence) v.getTag(),
                                new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN},
                                item);
                        v.findViewById(R.id.appicondrawable).startDrag(dragData,  // the data to be dragged
                                new View.DragShadowBuilder(v.findViewById(R.id.appicondrawable)),  // the drag shadow builder
                                null,      // no need to use local data
                                0          // flags (not currently used, set to 0)
                        );

                        if(mAppDragListener!=null) {
                            mAppDragListener.onAppDragged(appObjectList.get(position), v);
                        }

                        return true;

                    default:
                        return false;

                }
            }
        });

非常感谢您的帮助!

更新1:

为了澄清,在父自定义布局中设置背景/前景/可点击属性没有效果,原因如上所述。我已经尝试了这些解决方案。

更新2:

添加适配器项布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/applayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="?android:attr/selectableItemBackground"
    android:focusable="true"
    android:clickable="true"
    android:padding="5sp">

    <ImageView
        android:id="@+id/appicondrawable"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:adjustViewBounds="true"
        android:maxWidth="40dp"
        android:maxHeight="40dp"
        android:scaleType="fitCenter"
        android:layout_marginStart="3dp"
        android:src="@drawable/ic_launcher_background" />

    <TextView
        android:id="@+id/appname"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif-light"
        android:gravity="center"
        android:maxLines="1"
        android:text="app name"
        android:textAlignment="center"
        android:textSize="10sp"
        android:textColor="#000000" />

</LinearLayout>

请分享您的布局代码。 - Anggrayudi H
请查看上面的更新2。我在根视图中添加了android:background="?android:attr/selectableItemBackground"、android:focusable="true"和android:clickable="true"。 - Vinit Shandilya
3个回答

18

我找到了一个解决方法。虽然涟漪效果不能定制,但修复方法非常巧妙。我手动在 ACTION_DOWNACTION_UP 事件中调用了 View 上的 setPressed() 方法,现在我可以看到默认的 Android 涟漪效果。

case MotionEvent.ACTION_DOWN:
                        //icon.setColorFilter(Color.argb(80, 0, 0, 0));
                        v.setPressed(true);
                        if(mAppActionDownListener != null) {
                            mAppActionDownListener.onAppActionDown(appObjectList.get(position), v);
                        }
                        Log.d("COOK", "ACTION_DOWN: " + ev.getX() + ", " + ev.getY());
                        t1 = System.currentTimeMillis();
                        return true;

                    case MotionEvent.ACTION_UP:
                        v.setPressed(false);
                        Log.d("COOK", "ACTION_UP: " + ev.getX() + ", " + ev.getY());
                        t2 = System.currentTimeMillis();
                        if(Math.abs(t2-t1) <=300) {
                            //Toast.makeText(context, "Click event", Toast.LENGTH_SHORT).show();
                            if(mAppClickListener!=null) {
                                mAppClickListener.onAppClicked(appObjectList.get(position), v);
                            }
                        }

2
值得注意的是,还有MotionEvent.ACTION_CANCEL,它可能会代替ACTION_UP发生,因此在这种情况下,也应该调用setPressed(false) - snachmsm

1
你需要为布局添加自定义背景或前景。
创建一个名为res/drawable/ripple_selector.xml的文件:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
    <item android:id="@android:id/mask"><color android:color="#dcffffff"/></item>
</ripple>

然后,将其用作背景:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/applayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/ripple_selector"
    android:focusable="true"
    android:clickable="true"
    android:padding="5sp">

    ...

</LinearLayout>

如果不起作用,请尝试将其作为foreground使用:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/applayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:foreground="@drawable/ripple_selector"
    android:focusable="true"
    android:clickable="true"
    android:padding="5sp">

    ...

</LinearLayout>

谢谢你的回答,但是我之前也尝试过这个方法,但是也没有起作用。我尝试了后台和前台两种方式。有没有一种方法可以直接在onTouch方法中创建它? - Vinit Shandilya
我不知道。你可以试试看。@VinitShandilya - Anggrayudi H

0

如果要为您的视图添加涟漪效果,可以将?attr/selectableItemBackground添加为视图的背景。

<ImageView
     android:height="100dp"
     android:width="100dp"
     android:src="@drawable/crush"
     android:background="?attr/selectableItemBackground"
     android:clickable="true"
     android:focusable="true" />

我已经尝试过这个,但对我没有用。我相信这些属性只适用于onclicklistener。 - Vinit Shandilya
你尝试过将你的视图包装为子视图,并将父视图的背景设置为selectableItemBackground吗?参考其他内容:https://stackoverflow.com/a/30964407/8109202,https://stackoverflow.com/a/35268525/8109202 - Ezra Lazuardy
是的,我也尝试过了。关键是,手势调用没有到达onclick事件,而这个事件实际上显示了涟漪效果。 - Vinit Shandilya
如果您使用onClickListener,则是正确的,但如果您使用手势检测器,则无法正常工作。 - Manuel Mato

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接