En bref:
Comment pouvons-nous définir les états de couleur de la propriété cardBackgroundColor de CardView (dans un modèle ListView, dans ce cas)?
(J'utilise la RC1 de Android L, sur un téléphone avec une version 4.4 installée, et "com.Android.support:cardview-v7:21.0.0-rc1" dans le fichier build.gradle)
Plus long:
Dans la présentation CardView, nous définissons le rayon de coin et la couleur d'arrière-plan de CardView via cardCornerRadius et cardBackgroundColor.
Cependant, la couleur d’arrière-plan ne correspond pas aux états sélectionnés, c’est-à-dire si l’élément de la liste est activé, par exemple.
Si, dans la vue interne de CardView, vous définissez une couleur d'arrière-plan et les états associés, qui sont respectés, elle s'affichera toutefois sur les coins que vous avez définis dans CardView.
Alors, comment pouvons-nous nous assurer que les états de cardBackgroundColor de CardView sont respectés?
Voici la couleur utilisée pour 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>
Et la mise en page qui utilise le 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>
Bien que cela ne soit pas idéal, étant donné que les bords ne sont pas arrondis, vous pouvez ajouter un retour tactile à un CardView
comme ceci:
<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>
Ajout des attributs Android:foreground
Et Android:clickable
À CardView
.
Cela a également un effet négatif en ce que l'attribut Android:clickable
A priorité sur tout clickListener et que, par conséquent, ces clickListeners ne sont pas déclenchés.
J'ai quelques exemples d'implémentations CardView
Boucle ( https://github.com/lawloretienne/Loop ) - https://github.com/lawloretienne/Loop/blob/master/app/src/main/res/ layout/category_card.xml
QuickReturn ( https://github.com/lawloretienne/QuickReturn ) - https://github.com/lawloretienne/QuickReturn/blob/master/sample/src/main/res/ layout/activity_quick_return.xml
Après plus de recherches, j'ai trouvé une bonne solution pour CardViews sur toutes les versions d'API, y compris la pré-Lollipop.
https://medium.com/@etiennelawlor/layout-tips-for-pre-and-post-Lollipop-bcb2e4cdd6b2#.9h0v1gmaw
Parfois, vous voudrez peut-être que le CardView
ait un retour tactile visuel. La solution Android:foreground="?android:attr/selectableItemBackground"
Est parfaite pour cela.
Cependant, vous pouvez envisager d'utiliser drawSelectorOnTop(true)
avec votre ListView. Cela ne nécessitera aucun changement de votre CardView
.
Faites-moi savoir si des éclaircissements supplémentaires sont nécessaires.
Voici ma façon de résoudre votre problème.
Commencez par créer une classe personnalisée nommée CustomCardView
extend CardView
Puis remplacez la méthode drawableStateChanged()
, changez la couleur de fond de la carte par appel setCardBackgroundColor()
lorsque le statut de la carte est modifié.
Enfin, remplacez le CardView par ce CustomCardView dans votre fichier de mise en page.
le seul inconvénient de cette solution est que cardview ne peut pas afficher d’effet de pression d’ondulation sur Android 5.0 et supérieur.
voici mon code:
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));
}
}
}
Une solution de contournement que j'ai utilisée consistait à effectuer les modifications d'interface utilisateur par programme en remplaçant le gestionnaire d'événements View.OnTouchListener OnTouch () dans mon ViewHolder personnalisé.
@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;
}
** Ajoutez simplement des lignes dans la vue de la carte **
Android:clickable="true"
Android:focusableInTouchMode="true"
Android:foreground="?android:attr/selectableItemBackground"
Utilisation Android:foreground
au lieu de Android:background
dans votre <CardView/>
. Vous trouverez ci-dessous un exemple de code d'un 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>
J'ai utilisé une forme de rectangle avec le même rayon de coin que la vue de la carte. Et ensuite utilisé le xml pouvant être dessiné comme arrière-plan pour la vue interne de la vue de la carte. L’arrière-plan ne s’affiche pas au-dessus du coin de la carte, même si j’ai toujours un petit rembourrage entre la carte et sa vue interne.
Si vous regardez la définition de la propriété carBackgroundColor, au moins dans la Android bibliothèque de support, elle est:
<resources>
<declare-styleable name="CardView">
<!-- Background color for CardView. -->
<attr name="cardBackgroundColor" format="color" />
</declare-styleable>
</resource>
Ici, il est indiqué qu’il ne faut que la couleur pour cardBackgroundValue. J'imagine que cela signifie que le sélecteur n'est pas respecté mais qu'il passe à la valeur par défaut, c'est-à-dire. couleur au bas de votre sélecteur.