web-dev-qa-db-ja.com

カスタムCardViewスタイルをテーマに添付する

私のアプリには2つのテーマ(明暗)があり、選択したテーマに応じてすべてのCardViewsの背景色を変更します。

私がしたくないことは:

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

上記のコードは動的ではありません。明るいテーマと暗いテーマのどちらが選択されているかに応じて、2つのスタイルを自動的に適用する必要があります。


私が今持っているものは機能しません:

<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>

どこかでstyleable.xmlファイル/res/values/で単語cardViewStyleにキーを付けるため、次のようにしました。

styleable.xml:

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

更新

同様の質問 here も回答なし。

22

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"
19
David Park

David Parkのソリューションを実装する方法の詳細を表示するには...

これを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>
9
flar2

追加したくない場合はstyle="?cardViewStyle"レイアウト内のすべてのCardViewに、CardViewをサブクラス化して、コンストラクターでスタイル属性を設定できます(サポートライブラリでそうしなかったのは残念です)。次に、CardViewの代わりに、XMLでそのサブクラスを使用します。

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>
1
arekolek

私が思いついた唯一の解決策は、カードの色の定数変数を手動で保持することであり、テーマを変更するたびに行う必要があります。次に、アプリケーションにあるカードのすべてのインスタンスを取得し、その色をその定数変数に設定します。

だから、私は私の活動のすべてがそこから伸びる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);
    }
}

これは間違いなくこれを行うための最良の方法ではありませんが、他の誰かがスタイリングを実装するより良い方法を見つけるまで、これは私が考えることができるすべてです。

0