在 Android Touch 事件中看不到点击涟漪效应

Posted

技术标签:

【中文标题】在 Android Touch 事件中看不到点击涟漪效应【英文标题】:Can't see click ripple effect in Android Touch events 【发布时间】:2020-07-26 04:25:44 【问题描述】:

我在这里看到了一些解决方案,但没有一个适合我。我正在使用View.OnTouchListener 类来检测我的应用程序代码中的单击和拖动事件。但是这种美丽的涟漪效应现在已经消失了(可能是因为我在到达View.OnClickListener 之前使用了MotionEvent 手势。注意MotionEvent.ACTION_DOWN 块中的return true)。

我无法使用View.OnClickListener 来检测点击事件,因为我的应用使用了多种复合手势(点击、点击按住、点击按住拖动等)。任何人都可以分享一些关于如何使用 android 触摸手势创建涟漪效果的建议吗?

这是我在BaseAdapter 类中实现View.OnTouchListener 的代码sn-p:

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_
    android:layout_
    android:orientation="vertical"
    android:background="?android:attr/selectableItemBackground"
    android:focusable="true"
    android:clickable="true"
    android:padding="5sp">

    <ImageView
        android:id="@+id/appicondrawable"
        android:layout_
        android:layout_
        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_
        android:layout_
        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>

【问题讨论】:

请分享您的布局代码。 请参阅上面的更新 2。我在根视图中添加了 android:background="?android:attr/selectableItemBackground" android:focusable="true" android:clickable="true"。 【参考方案1】:

我找到了解决这个问题的方法。虽然涟漪效应不可定制,但修复非常漂亮。我在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);
                            
                        

【讨论】:

值得注意的是还有MotionEvent.ACTION_CANCEL,它可能会出现INSTEAD ACTION_UP,所以在这种情况下setPressed(false)也应该被调用【参考方案2】:

您需要为布局自定义背景或前景。

创建一个名为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>

然后,将其用作background

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/applayout"
    android:layout_
    android:layout_
    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_
    android:layout_
    android:orientation="vertical"
    android:foreground="@drawable/ripple_selector"
    android:focusable="true"
    android:clickable="true"
    android:padding="5sp">

    ...

</LinearLayout>

【讨论】:

谢谢你的回答,不过我之前也试过这个,也没用。背景和前景都试过了。有没有办法直接在 onTouch 方法里面创建? 我不知道。你可以试试。 @VinitShandilya【参考方案3】:

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

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

【讨论】:

我试过这个,但它对我不起作用。我相信这些属性只适用于 onclicklistener。 您是否尝试将视图包装为子视图并将父视图的背景设置为 selectableItemBackground ?查看其他参考资料:***.com/a/30964407/8109202、***.com/a/35268525/8109202 是的,也试过了。关键是,手势调用没有到达 onclick 事件,它实际上显示了涟漪效应。 如果你使用 onClickListener 是对的,但如果你使用手势检测器就不行

以上是关于在 Android Touch 事件中看不到点击涟漪效应的主要内容,如果未能解决你的问题,请参考以下文章

Sencha Touch:点击面具事件

Android Touch事件分发处理机制详解

Android Touch事件分发(源码分析)

Android Touch事件分发(源码分析)

Android 进阶——Framework 核心之Touch事件分发机制详细攻略

Android 进阶——Framework 核心之Touch事件分发机制详细攻略