【问题标题】:Android, setting background color of button loses ripple effectAndroid,设置按钮的背景颜色会失去涟漪效果
【发布时间】:2016-11-14 14:17:47
【问题描述】:

在为 android 按钮添加颜色后,它会失去涟漪效果,让用户感觉就像是响应式点击。我该如何解决?我已经搜索了许多解决方案,但我找不到一个明确的不模棱两可的解决方案。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".ClockInOutFragment">


    <AnalogClock
        android:id="@+id/clock"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/date_and_time"/>


    <RelativeLayout
        android:id="@+id/date_and_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp">

        <TextView
            android:id="@+id/time_digits"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="12:10"
            android:textSize="45sp"/>

        <TextView
            android:id="@+id/am_pm"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/time_digits"
            android:layout_toRightOf="@+id/time_digits"
            android:paddingLeft="3dp"
            android:text="PM"
            android:textSize="20sp"/>

        <TextView
            android:id="@+id/date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/time_digits"
            android:text="Mon, July 11"
            android:textSize="22sp"/>
    </RelativeLayout>

    <!--Clock in and out buttons-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal">

        <Button
            android:id="@+id/textView3"
            android:layout_width="0dp"
            android:layout_height="56dp"
            android:layout_weight="1"
            android:background="#4CAF50"
            android:gravity="center"
            android:text="Clock In"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="#FFFFFF"/>

        <!--Divider between the clock in and out button-->
        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="#B6B6B6"/>

        <Button
            android:id="@+id/textView4"
            android:layout_width="0dp"
            android:layout_height="56dp"
            android:layout_weight="1"
            android:background="#FF5252"
            android:gravity="center"
            android:text="Clock Out"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="#FFFFFF"/>
    </LinearLayout>


</RelativeLayout>

【问题讨论】:

    标签: android button click effect ripple


    【解决方案1】:

    您可以使用附加的波纹可绘制来添加波纹效果和背景颜色:

    你的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <Button
            android:id="@+id/button_connect"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dip"
            android:fontFamily="sans-serif"
            android:text="Connect"
            android:background="@drawable/ripple"
            android:textColor="#FFFFFF"
            android:textSize="18sp" />
    
    </LinearLayout>
    

    ripple.xml(除了波纹效果之外,您还可以在此处添加背景颜色):

    <?xml version="1.0" encoding="utf-8"?>
    <!-- in drawable folder-->
    <ripple
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?android:colorControlHighlight">
    
        <item android:id="@android:id/mask">
            <shape android:shape="rectangle">
                <solid android:color="?android:colorAccent" />
            </shape>
        </item>
    
        <item>
            <shape android:shape="rectangle">
                <!-- put your background color here-->
                <solid android:color="@color/default_color" />
            </shape>
        </item>
    
    </ripple>
    

    【讨论】:

    • android如何区分哪一种是蒙版,哪一种是默认颜色?
    • 按 ID。例如 - android:id="@android:id/mask"
    • 这适用于更改菜单背景并保留涟漪效果
    【解决方案2】:

    执行此操作的一种非常简单直接的方法是将按钮的?attr/selectableItemBackground 设置为android:foreground 属性。以下 xml 完全有效且有效

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:foreground="?attr/selectableItemBackground"/>
    

    【讨论】:

    • 不错。但是,23 版不支持向后兼容。
    • 如何改变效果的颜色?
    • 这不适用于使用 style="@style/Widget.AppCompat.Button.Colored" 的弯曲按钮 结果是阴影有尖角,而不是弯曲的角。
    • 适用于Widget.AppCompat.Button.Borderless
    【解决方案3】:

    不要改变 Button 的背景。换个主题。

    <style name="ButtonGray">
        <item name="colorButtonNormal">@color/gray</item>
    </style>
    

    在你的xml文件中

    <Button
         android:id="@+id/accept_button"
         android:layout_height="wrap_content"
         android:layout_width="0dp"
         android:layout_weight="1"
         android:text="@string/button_accept_group"
         android:theme="@style/ButtonGray"/>
    

    或者您可以将其添加到您的主应用主题中

    <style name="AppTheme"
               parent="Theme.AppCompat.Light.NoActionBar">
            <item name="colorButtonNormal">@color/primary_color</item>
    </style>
    

    并且不需要更改按钮背景。

    如果你想要完全自定义的背景,你需要创建你的选择器。你可以在那里设置涟漪效应。

    【讨论】:

      【解决方案4】:

      只需使用:

      android:backgroundTint="#4CAF50"
      

      代替:

      android:background="#4CAF50"
      

      别忘了把你的Button改成android.support.v7.widget.AppCompatButton

      【讨论】:

      • 这不适用于androidx.appcompat.widget.AppCompatButton
      【解决方案5】:

      MaterialButton没有答案,所以我把它放在这里。

      对于 MaterialButton (com.google.android.material.button.MaterialButton),使用“backgroundTint”和“rippleColor”。

      <com.google.android.material.button.MaterialButton
          android:id="@+id/button_sign_in"
          android:layout_width="0dp"
          android:layout_height="55dp"
          app:backgroundTint="@android:color/white"
          app:rippleColor="?attr/colorControlHighlight"
      

      ?attr/colorControlHighlight是默认的波纹颜色,你可以改变这个值。

      【讨论】:

        【解决方案6】:

        实际上,您可以使用drawables的&lt;layer-list&gt;将涟漪效果与任何其他drawable结合起来。这也是 pre-lolipop 的通用解决方案:我已经在许多配置中对其进行了测试。

        唯一的问题是当?selectableItemBackground 出现在&lt;layer-list&gt; 中时pre-lolipop 会崩溃,所以我们必须以编程方式创建LayerDrawable。

        一个非常快速的简单解决方案如下所示:

        为您的视图指定

        android:background="?selectableItemBackground"
        

        然后在代码中的任何地方创建 mySpecialDrawable 并执行此操作:

        Drawable[] layers = {mySpecialDrawable, getBackground()};
        setBackgroundDrawable(new LayerDrawable(layers).mutate()); 
        

        请注意,LayeredDrawable 的 .mutate() 在这里是必不可少的!

        当您已经拥有自定义 View 并且更喜欢扩展其功能和兼容性而不是添加额外的空 FrameLayout 作为父级时,更复杂的解决方案可能会很有用。

        在attrs.xml里面放:

        <resources>
            <declare-styleable name="MyView">
                <attr name="selectableBackground" format="reference"/>
                <attr name="backgroundDrawable" format="reference"/>
            </declare-styleable>
        </resources>
        

        然后在你的 View-descendant 类中:

        private Drawable selectableBackground;
        private Drawable backgroundDrawable;
        
        public MyView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        
            try {
                TypedArray attributeArray;
                attributeArray = context.obtainStyledAttributes(attrs, R.styleable.MyView);
        
                int id = attributeArray.getResourceId(R.styleable.MyView_selectableBackground, -1);
                if (id != -1) {
                    selectableBackground = ResourcesCompat.getDrawable(getResources(), id, context.getTheme());
                }
                id = attributeArray.getResourceId(R.styleable.MyView_backgroundDrawable, -1);
                if (id != -1) {
                    backgroundDrawable = ResourcesCompat.getDrawable(getResources(), id, context.getTheme());
                }
        
                constructBackground();
                attributeArray.recycle();
            } catch (Exception e) {
                Log.e(this.toString(), "Attributes initialization error", e);
                throw e;
            }
        }
        
        void setSelectableBackground(Drawable drawable) {
            selectableBackground = drawable;
            constructBackground();
        }
        
        void setDrawable(Drawable drawable) {
            backgroundDrawable = drawable;
            constructBackground();
        }
        
        private void constructBackground() {
            if (selectableBackground != null) {
                if (backgroundDrawable != null) {
                    Drawable[] layers = {backgroundDrawable, selectableBackground};
                    setBackgroundDrawable(new LayerDrawable(layers).mutate());      // Both, using layers
                } else setBackgroundDrawable(selectableBackground);                 // Selectable only
            } else setBackgroundDrawable(backgroundDrawable);                       // Background only or null
        }
        

        我更喜欢这种方法,因为它没有像 android:foreground 属性这样的问题,它是 23+ 或在 FrameLayout 中包含可点击视图的额外开销。

        【讨论】:

          【解决方案7】:

          你应该使用样式

          <style parent="Theme.AppCompat.Light" name="RaisedButtonGreen">
              <item name="colorButtonNormal">@color/green</item>
              <item name="colorControlHighlight">@color/greenLight</item>
              <item name="android:textColor">@android:color/white</item>
          </style>
          

          这是最优解

          <Button
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:text="Button with ripple for style"
              android:theme="@style/RaisedButtonGreen"/>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-11-11
            • 1970-01-01
            • 2015-01-10
            • 2019-07-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多