web-dev-qa-db-fra.com

Attachez un style CardView personnalisé au thème

Dans mon application, j'ai deux thèmes (clair et foncé) et je veux que tous mes CardView changent leur couleur d'arrière-plan en fonction du thème sélectionné.

Ce que je ne veux pas c'est:

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

Le code ci-dessus n'est pas dynamique. J'ai besoin que mes deux styles soient appliqués automatiquement selon qu'un thème clair ou sombre est sélectionné.


Ce que j'ai en ce moment ne fonctionne pas:

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

J'ai lu quelque part que vous pouvez définir un styleable.xml fichier dans /res/values/ pour saisir le mot cardViewStyle, j'ai donc fait cela:

styleable.xml:

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

Mettre à jour

Question similaire ici sans réponse non plus.

22

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

Ensuite, dans votre autre xml pour utiliser le nouvel attribut, vous l'utiliseriez comme ceci

style="?attr/cardStyle"
19
David Park

Pour afficher plus de détails sur la façon d'implémenter la solution de David Park ...

Mettez ceci dans 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>

Ensuite, ajoutez cardStyle à votre thème dans styles.xml:

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

Ensuite, utilisez l'attr partout où vous avez un CardView:

<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

Si vous ne voulez pas ajouter style="?cardViewStyle" à chaque CardView dans vos mises en page, vous pouvez sous-classer CardView et définir l'attribut style dans le constructeur (dommage qu'ils ne l'aient pas fait dans la bibliothèque de support). Utilisez ensuite cette sous-classe dans le XML, au lieu de 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);
  }
}

L'attribut cardViewStyle doit être défini, par exemple dans attrs.xml comme:

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

Vous devrez définir cet attribut dans votre thème, comme d'habitude:

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

Et définissez le style lui-même, par exemple:

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

La seule solution que j'ai pu trouver est de maintenir manuellement une variable constante pour que la couleur de la carte soit après chaque changement de thème. Ensuite, j'obtiens chaque instance d'une carte qui se trouve dans mon application et définit sa couleur sur cette variable constante.

J'ai donc une BaseActivity à partir de laquelle toutes mes activités s'étendent. Dans ce document, je gère le changement de couleur de la carte en plus de gérer le thème. Voir ci-dessous:

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);
    }
}

Ce n'est certainement pas la meilleure façon de le faire, mais jusqu'à ce que quelqu'un d'autre puisse trouver une meilleure façon d'implémenter le style, c'est tout ce à quoi je peux penser.

0