【问题标题】:CardView background color states not being respectedCardView 背景颜色状态不被尊重
【发布时间】:2014-08-17 19:36:57
【问题描述】:

简而言之:

我们如何定义 CardView 的 cardBackgroundColor 属性的颜色状态(在这种情况下,在 ListView 布局中)?

(我正在使用 Android L 开发者预览版的 RC1,在安装了 4.4 的手机上,以及 build.gradle 中的“com.android.support:cardview-v7:21.0.0-rc1”)

更长:

在 CardView 布局中,我们通过 cardCornerRadius 和 cardBackgroundColor 设置 CardView 的圆角半径和背景颜色。

但是,背景颜色不反映选定的状态,例如,如果列表项被按下。

如果您在 CardView 的内部视图中设置了背景颜色和相关的状态,它们会受到尊重,但是,它将显示在您在 CardView 中定义的角上。

那么,我们如何确保 CardView 的 cardBackgroundColor 中的状态得到尊重?

这是用于 cardBackgroundColor 的颜色 colour_with_states.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:color="@android:color/holo_green_dark" />
    <item android:state_focused="true"  android:state_enabled="false"                              android:color="@android:color/holo_green_dark" />
    <item android:state_focused="true"                                android:state_pressed="true" android:color="@android:color/holo_green_dark" />
    <item android:state_focused="false"                               android:state_pressed="true" android:color="@android:color/holo_green_dark" />
    <item android:state_focused="true"                                                             android:color="@android:color/holo_green_dark" />
    <!-- Only this below is seen in the cardview dispaly -->
    <item android:color="@android:color/holo_blue_bright" />
</selector>

以及使用 CardView 的布局:

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:cardview="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    cardview:cardCornerRadius="10dp"
    cardview:cardBackgroundColor="@color/colour_with_states"
    >

<!-- If we set a background color below, it will overwrite our radius defined above -->
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:text="Lorem ipsum"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceListItem"
    android:background="@null"
    android:gravity="center_vertical"
    android:paddingTop="8dip"
    android:paddingBottom="8dip"
    android:paddingStart="8dip"
    android:paddingEnd="8dip"
    />

</android.support.v7.widget.CardView>

【问题讨论】:

  • 在常规FrameLayout 中使用相同的背景颜色是否尊重所选状态?我认为您在您的CardView 上拨打setOnClickListener
  • 我认为答案就在您的问题中:If, in the inner view of the CardView, you set a background colour, and associated states, which are respected, however, it will display over the corners you defined in the CardView.。父 ViewGroup(卡片)正在将焦点和事件路由到子视图。此外,ListView 有自己的 selector 用于突出显示所选项目。
  • @S.D. “路由”不是它的工作方式。你应该测试 android:duplicateParentState。通过这种方式,父级和任何感兴趣的子级都可以使用 XML 选择器隐式响应感兴趣的事件。 CardView 打破了这种模式,无法“听到”父选择状态的变化,可能是因为有问题的属性是特殊的 cardview:cardBackgroundColor,而不是通用的 android:background。
  • 希望 [this][1] 可以帮助 [1]:stackoverflow.com/questions/24518376/…

标签: android android-cardview


【解决方案1】:

虽然这并不理想,但由于边缘不是圆角的,您可以像这样向CardView 添加触摸反馈:

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="4dp"
    android:clickable="true"
    android:foreground="?android:attr/selectableItemBackground">

    //Nested View ...

</android.support.v7.widget.CardView>

android:foregroundandroid:clickable 属性添加到CardView

这还有一个负面影响,因为 android:clickable 属性会覆盖任何 clickListener,因此不会触发这些 clickListener。

更新

我有一些 CardView 实现的例子

循环 (https://github.com/lawloretienne/Loop) - https://github.com/lawloretienne/Loop/blob/master/app/src/main/res/layout/category_card.xml

快速返回 (https://github.com/lawloretienne/QuickReturn) - https://github.com/lawloretienne/QuickReturn/blob/master/sample/src/main/res/layout/activity_quick_return.xml

更新 2

经过更多研究后,我为所有 API 版本(包括 Lollipop 之前的版本)上的 CardViews 提出了一个很好的解决方案。

https://medium.com/@etiennelawlor/layout-tips-for-pre-and-post-lollipop-bcb2e4cdd6b2#.9h0v1gmaw

【讨论】:

  • 你应该可以使用 android:onClick="someMethod" 代替上面的 android:clickable="true" 来达到同样的效果。
  • 不适用的解决方案。丑陋。
  • 实际上这在 Kit Kat 或 Lollipop 中都有效。刚刚测试并确认工作!除此之外,这是一个完美的简单解决方案。
  • 要更改波纹的颜色,您可以将 @color/your_color 添加到您的主题中。
  • 完美答案。非常感谢。像魅力一样工作。
【解决方案2】:

有时,您可能希望CardView 具有视觉触摸反馈。 android:foreground="?android:attr/selectableItemBackground" 解决方案非常适合。

但是,您可以考虑将drawSelectorOnTop(true) 与您的 ListView 一起使用。这根本不需要更改您的CardView

如果需要进一步说明,请告诉我。

【讨论】:

    【解决方案3】:

    这是我解决问题的方法。

    首先,创建一个名为 CustomCardView 的自定义类 extends CardView

    然后重写drawableStateChanged()方法,在卡片按压状态发生变化时调用setCardBackgroundColor()方法改变卡片背景颜色。

    最后,在你的布局文件中用这个 CustomCardView 替换 CardView。

    此方案唯一的一个缺点是cardview在Android 5.0及以上版本无法显示波纹按压效果。

    这是我的代码:

    public class CustomCardView extends CardView {
    
    public CustomCardView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    
    public CustomCardView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }
    
    public CustomCardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    }
    
    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (isPressed()) {
            this.setCardBackgroundColor(getContext().getResources().getColor(R.color.card_view_pressed));
        } else {
            this.setCardBackgroundColor(getContext().getResources().getColor(R.color.card_view_normal));
        }
    }
    

    }

    【讨论】:

      【解决方案4】:

      我使用的一种解决方法是通过在我的自定义 ViewHolder 中覆盖 View.OnTouchListener OnTouch() 事件处理程序以编程方式更改 UI。

      @Override
      public boolean onTouch (View v, MotionEvent event) 
      {
          int action = event.getActionMasked();
          if (action == MotionEvent.ACTION_DOWN) 
          {
              mCardView.setCardBackgroundColor(STATE_PRESSED_COLOR);
          } 
          else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) 
          {
              mCardView.setCardBackgroundColor(DEFAULT_COLOR);
          }
          return false;
      }
      

      【讨论】:

        【解决方案5】:

        **只需在卡片视图中添加行**

            android:clickable="true"
            android:focusableInTouchMode="true"
            android:foreground="?android:attr/selectableItemBackground"
        

        【讨论】:

          【解决方案6】:

          您可以在代码中使用颜色状态,它可以完美运行。

          cardView.setCardBackgroundColor(context.getColorStateList(R.color.card_view_selectable))
          

          颜色> card_view_selectable.xml

          <selector xmlns:android="http://schemas.android.com/apk/res/android">
              <item android:color="#4fc3f7" android:state_activated="true" />
              <item android:color="#fff" />
          </selector>
          

          然后使用 isActivated 导致背景颜色更改为 state_activated 或默认。

          cardView.isActivated = true    // or false
          

          【讨论】:

            【解决方案7】:

            我使用了与卡片视图具有相同角半径的矩形形状。然后使用xml drawable作为cardview内部视图的背景。 背景不显示在 cardview 角落,虽然我仍然在卡片和它的内部视图之间得到一个小填充。

            【讨论】:

              【解决方案8】:

              如果你看一下carBackgroundColor属性的定义,至少在android支持库中是:

              <resources>
                  <declare-styleable name="CardView">
                      <!-- Background color for CardView. -->
                      <attr name="cardBackgroundColor" format="color" />
                  </declare-styleable>
              </resource>
              

              这里说 cardBackgroundValue 只需要颜色。我想这意味着选择器不被尊重,但会下降到默认值,即。选择器底部的颜色。

              【讨论】:

                【解决方案9】:

                在您的&lt;CardView/&gt; 中使用android:foreground 而不是android:background。下面是 CardView 的示例代码。

                 <android.support.v7.widget.CardView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:clickable="true"
                        android:foreground="?android:attr/selectableItemBackground"
                        app:cardCornerRadius="2dp"
                        app:cardElevation="2dp">
                
                // others view component 
                
                </android.support.v7.widget.CardView>
                

                【讨论】:

                  猜你喜欢
                  • 2020-10-04
                  • 1970-01-01
                  • 2018-08-19
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-11-02
                  • 1970-01-01
                  相关资源
                  最近更新 更多