将自定义CardView样式附加到主题

在我的应用程序中,我有两个主题(浅色和黑色),我希望所有CardView都根据所选主题更改背景颜色。

想要的是:

 <android.support.v7.widget.CardView style="@style/CardView.MyBlue" android:layout_width="200dp" android:layout_height="100dp" android:layout_gravity="center_horizontal"> 

上面的代码不是dynamic的。 我需要我的两种风格自动应用,取决于是否select了光线或黑暗的主题。


我现在所拥有的不起作用:

 <style name="AppTheme.Light" parent="Theme.AppCompat.Light"> ... <item name="cardViewStyle">@style/CardViewStyle.Light</item> </style> <style name="AppTheme.Dark" parent="Theme.AppCompat"> ... <item name="cardViewStyle">@style/CardViewStyle.Dark</item> </style> <style name="CardViewStyle.Light" parent="CardView"> <item name="cardBackgroundColor">@color/cardview_dark_background</item> </style> <style name="CardViewStyle.Dark" parent="CardView"> <item name="cardBackgroundColor">@color/cardview_light_background</item> </style> 

我读了一个地方,你可以在/res/values/定义一个styleable.xml文件来键入cardViewStyle这个单词,所以我这样做了:

styleable.xml:

 <resources> <declare-styleable name="AppTheme"> <attr name="cardViewStyle" format="reference" /> </declare-styleable> </resources> 

更新

类似的问题也没有答案。

Solutions Collecting From Web of "将自定义CardView样式附加到主题"

在styles.xml中

 <resources> <attr format="reference" name="cardStyle"/> <style name="Light" parent="Theme.AppCompat.NoActionBar"> <item name="cardStyle">@style/CardView.Light</item> ... </style> <style name="Dark" parent="Theme.AppCompat.NoActionBar"> <item name="cardStyle">@style/CardView.Dark</item> ... </style> </resources> 

然后在你的其他XML中使用新的属性,你会像这样使用它

 style="?attr/cardStyle" 

要详细了解如何实施David Park的解决scheme

把这个放在attrs.xml中:

 <declare-styleable name = "cardStyle"> <attr name="cardStyle" format="reference" /> </declare-styleable> <style name="Light" parent="Theme.AppCompat.NoActionBar"> <item name="cardStyle">@style/CardView.Light</item> </style> <style name="Dark" parent="Theme.AppCompat.NoActionBar"> <item name="cardStyle">@style/CardView.Dark</item> </style> 

然后,在styles.xml中将cardStyle添加到您的主题中:

 <style name="AppThemeLight" parent="AppTheme.Base"/> <style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar"> <item name="cardStyle">@style/CardView.Light</item> </style> <style name="AppThemeDark" parent="AppTheme.Base.Dark"/> <style name="AppTheme.Base.Dark" parent="Theme.AppCompat.NoActionBar"> <item name="cardStyle">@style/CardView.Dark</item> </style> 

然后在有CardView的地方使用attr:

 <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/header_card" android:layout_width="match_parent" android:layout_height="wrap_content" card_view:cardCornerRadius="2dp" card_view:cardElevation="2dp" style="?attr/cardStyle"> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:id="@+id/header_title" </android.support.v7.widget.CardView> 

如果您不想在布局中的每个CardView中添加style="?cardViewStyle" ,则可以CardView并在构造函数中设置style属性(太糟糕了,他们在支持库中没有这样做)。 然后在XML中使用该子类,而不是CardView

 package com.example.widget; import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.CardView; import android.util.AttributeSet; import com.example.R; /** * {@link CardView} subclass that allows theme'ing through * the {@link R.attr#cardViewStyle} attribute. * <p> * The attribute needs to be defined, for example in <code>attrs.xml</code> as: * <pre> * &lt;attr format="reference" name="cardViewStyle"/&gt; * </pre> * <p> * You'll need to set that attribute in your theme, as usual: * <pre> * &lt;item name="cardViewStyle"&gt;@style/CardView.MyStyle&lt;/item&gt; * </pre> * And define the style itself, for example: * <pre> * &lt;style name="CardView.MyStyle" parent="CardView.Light"&gt; * &lt;item name="cardCornerRadius"&gt;0dp&lt;/item&gt; * &lt;/style&gt; * </pre> */ public class StylishCardView extends CardView { public StylishCardView(@NonNull Context context) { this(context, null); } public StylishCardView(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, R.attr.cardViewStyle); } public StylishCardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } } 

需要定义属性cardViewStyle ,例如在attrs.xml定义为:

 <attr format="reference" name="cardViewStyle"/> 

像往常一样,您需要在主题中设置该属性:

 <item name="cardViewStyle">@style/CardView.MyStyle</item> 

并定义风格本身,例如:

 <style name="CardView.MyStyle" parent="CardView.Light"> <item name="cardCornerRadius">0dp</item> </style> 

我已经能够想出的唯一的解决办法是手动持有一个常数variables的卡颜色应该是在每一个主题的变化。 然后,我得到我的应用程序中的一个卡的每个实例,并将其颜色设置为该常量variables。

所以,我有一个BaseActivity,我所有的活动都是从这里开始的。 在这里,除了处理主题之外,我还处理卡片的颜色变化。 见下文:

BaseActivity.java

 public class BaseActivity extends ActionBarActivity { private static final int DEFAULT_THEME_ID = R.style.AppTheme_Dark; @Override protected void onCreate(Bundle savedInstanceState) { int theme_id = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getInt("THEME_ID", DEFAULT_THEME_ID); setTheme(theme_id); int card_color; if (theme_id == DEFAULT_THEME_ID){ card_color = R.color.cv_dark; } else{ card_color = R.color.cv_light; } Constants.CARD_COLOR = card_color; super.onCreate(savedInstanceState); } } 

这绝对不是最好的办法,但直到别人能find一个更好的方式来实现样式,这是我所能想到的。