Android 实现工具栏菜单项单击涟漪效果

Android 实现工具栏菜单项单击涟漪效果,android,android-layout,android-view,android-drawable,rippledrawable,Android,Android Layout,Android View,Android Drawable,Rippledrawable,我尝试使用填充来增加按钮的触摸区域。我用 <ImageButton android:paddingRight="32dp" android:paddingEnd="32dp" android:id="@+id/confirm_image_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignPar

我尝试使用
填充
来增加按钮的触摸区域。我用

<ImageButton
    android:paddingRight="32dp"
    android:paddingEnd="32dp"
    android:id="@+id/confirm_image_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentEnd="true"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:background="?selectableItemBackgroundBorderless"
    android:src="?attr/confirmIcon" />

现在,

  • 单击的区域被放大
  • selectableitemsbackgroundless
    圆圈效果是一个完美的圆圈
  • 然而,它似乎有一些奇怪的行为。当我点击
    ImageButton
    的实际区域时,不会显示圆圈按压效果

    我可以知道为什么会这样吗?我怎样才能克服它?我使用API 26进行了测试。

    注意,我尽量避免使用
    TouchDelegate
    技术,除非我被迫这样做,因为这会使我们的代码更加复杂


    补充资料 以下是
    工具栏
    按钮显示的正确行为

    单击区域位于按钮外部时会显示涟漪效应

    单击区域位于按钮内时会显示涟漪效应

    然而,我不知道他们是如何实施这种行为的

    Android 5.0上的涟漪从每个视图的中心开始。相符合的 根据材料设计规则,涟漪应该从触摸的地方开始 事件发生时,它们似乎从手指向外流动这是 在Android 5.1中解决,但在Android 5.0中是一个bug

    要解决此问题,您需要使用添加到 可在API级别21中绘制
    setHotspot()
    为可绘制的 “热点”,而
    RippleDrawable
    显然将其用作涟漪效应的发射点<代码>设置热点()获取一对 浮点值,大概是为了使用
    sethospot()
    在一个
    OnTouchListener
    中,当
    MotionEvent
    报告
    X/Y
    具有浮动值的触摸事件的位置

    感谢忙碌的编码员的指南书

    您可以使用以下代码更正ripples错误:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           btn.setOnTouchListener(new View.OnTouchListener() {
              @TargetApi(Build.VERSION_CODES.LOLLIPOP)
              @Override
              public boolean onTouch(View v, MotionEvent event) {
                  v.getBackground()
                    .setHotspot(event.getX(), event.getY());
                  return(false);
              }
         });
    }
    
    其他解决方案:


    另一个解决方案:

    第一次尝试时:

    我试着用填充物来增加按钮的触摸面积

    您可以使用此代码将波纹中心置于
    图像按钮的中心。

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
               btn.setOnTouchListener(new View.OnTouchListener() {
                  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
                  @Override
                  public boolean onTouch(View v, MotionEvent event) {
                      v.getBackground()
                        .setHotspot(v.getWidth()/2f, v.getHeight()/2f);//setting hot spot at center of ImageButton
                      return(false);
                  }
             });
        }
    

    FrameLayout
    包装
    ImageButton
    时,可能还有另一种解决方案:

    正如你所说:

    然而,它似乎有一些奇怪的行为。当我点击 ImageButton的实际区域,圆圈按压效果未显示

    解决此问题的方法可能是在
    ImageButton的
    onClick()方法中添加
    frameLayout.performClick()

    或者,当单击
    ImageButton
    时,您可以模拟触摸
    frameLayout
    ,如下所示:

    // Obtain MotionEvent object
    long downTime = SystemClock.uptimeMillis();
    long eventTime = SystemClock.uptimeMillis() + 100;
    float x = 0.0f;// or x = frameLayout.getWidth()/2f
    float y = 0.0f;// or y = frameLayout.getHeight()/2f
    // List of meta states found here: developer.android.com/reference/android/view/KeyEvent.html#getMetaState()
    int metaState = 0;
    MotionEvent motionEvent = MotionEvent.obtain(
        downTime, 
        eventTime, 
        MotionEvent.ACTION_UP, 
        x, 
        y, 
        metaState
    );
    
    // Dispatch touch event to view
    frameLayout.dispatchTouchEvent(motionEvent);
    

    我怀疑您的问题在于您有一个
    ImageButton
    ,而不仅仅是
    ImageView
    ImageButton
    的默认样式为:

    <style name="Widget.ImageButton">
        <item name="android:focusable">true</item>
        <item name="android:clickable">true</item>
        <item name="android:scaleType">center</item>
        <item name="android:background">@android:drawable/btn_default</item>
    </style>
    
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="?selectableItemBackgroundBorderless"
        android:duplicateParentState="true"
        android:src="@drawable/ic_check_black_24dp"
        />
    
    另一个是相同的,除了
    FrameLayout
    内的视图是:

    <style name="Widget.ImageButton">
        <item name="android:focusable">true</item>
        <item name="android:clickable">true</item>
        <item name="android:scaleType">center</item>
        <item name="android:background">@android:drawable/btn_default</item>
    </style>
    
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="?selectableItemBackgroundBorderless"
        android:duplicateParentState="true"
        android:src="@drawable/ic_check_black_24dp"
        />
    
    
    
    以下是视觉证明:


    这是在运行Android 5.0.2的模拟器上捕获的。我在我的8.0手机上试用过,效果也不错。

    如果你使用
    android:duplicateParentState=“true”
    ,只需将
    安卓:clickable=“false”
    设置为你的
    图像按钮
    将使你的
    按钮及其父按钮在点击时高亮显示

    <ImageButton
           ...
           android:duplicateParentState="true"
           android:clickable="false"
      />
    

    当使用
    setOnClickListener
    时,它也将
    setClickable(true)
    ,因此在这种情况下,您只需为其父布局设置
    setOnClickListener
    ,花了一些时间后,我终于发现了“工具栏之谜”是如何工作的。工具栏上显示的是
    ActionMenuItemView
    。您可以看到,它内部应用了
    style=“?attr/actionButtonStyle”
    <代码>?attr/actionButtonStyle
    对应于此样式,在该样式中我们可以看到
    ?attr/actionBarItemBackground

    如果您想对您的
    ImageButton
    应用相同的效果,那么您所要做的就是对其应用
    android:background=“?attr/actionBarItemBackground”
    。因此,具有以下xml布局:

    <ImageButton
        android:id="@+id/confirm_image_button"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="?attr/actionBarItemBackground"
        android:src="@drawable/ic_check_black_24dp" />
    

    因此,您可以创建您的drawable并将其作为
    ImageButton

    的背景应用。我可以知道没有此解决方法它无法工作的原因吗?您是否有关于此错误的参考源?我使用API 26进行测试。我可以确认你提出的解决方案不起作用
    OnTouchListener
    被触发,但圆圈按下效果没有显示。我已经阅读了这些答案,但它没有回答我的疑问。我知道如何实现连锁反应。(正如您所看到的,我的涟漪效应是通过使用中的技术实现的)但我的问题不同,这在我的问题中已经清楚地说明了。@CheokYanCheng在您第一次尝试时,它只有带填充的ImageButton,您可以使用
    v.getBackground().setHotspot(v.getWidth()/2f,v.getHeight()/2f)将波纹中心定位在图像按钮的中心。请参阅我编辑的答案我建议您编写动画并单击行为。我认为这是最快的解决方案。我尝试将
    ImageButton
    替换为
    ImageView
    。它仍然表现出与我在
    ImageButton
    中描述的相同的问题行为。如果按下的区域在
    图像视图上
    ,则不会显示圆形按下效果。@CheokYanCheng手动将可聚焦和可点击设置为
    ?另外,您是否在图像或容器上设置了
    onClickListener
    ?是和是。我尝试了,并尝试在容器和/或按钮上单击侦听器。(各种组合)。它不起作用。你试过站在你这边吗?“这对你有用吗?”彻盐城说得很好。我已经用实际代码更新了我的答案。也许有什么不对劲
    <ImageButton
        android:id="@+id/confirm_image_button"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="?attr/actionBarItemBackground"
        android:src="@drawable/ic_check_black_24dp" />
    
    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?attr/colorControlHighlight"
        android:radius="20dp" />