问题
In the latest Android SDK we now have the new CardView, I have replaced my old CustomCardView with the new version, but when running with this on older versions of Android I see that the state_pressed
& state_focused
are ugly squares which show up above the CardView...
does anyone know how I could emulate the following in the new CardView but only when using older versions of Android?
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:enterFadeDuration="150"
android:exitFadeDuration="150" >
<item android:state_pressed="true"
android:drawable="@drawable/card_on_press"/>
<item android:state_focused="true" android:state_enabled="true"
android:drawable="@drawable/card_on_focus"/>
<item android:state_enabled="true"
android:drawable="@drawable/card_default"/>
<item android:state_enabled="false"
android:drawable="@drawable/card_on_press"/>
</selector>
And for those of you interested here is the CardView that I am using now:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:foreground="?android:attr/selectableItemBackground"
android:onClick="RunSomeMethod"
card_view:cardCornerRadius="4dp"
android:focusable="true"
android:elevation="2dp">
<LinearLayout
android:id="@+id/LinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:focusable="false"
android:visibility="visible">
</LinearLayout>
</android.support.v7.widget.CardView>
回答1:
Fixed with the following code:
values-v21\styles.xml:
<style name="CardViewStyle" parent="CardView.Light">
<item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>
values\styles.xml:
<style name="CardViewStyle" parent="android:Widget.TextView">
<item name="android:foreground">@drawable/card</item>
</style>
A card from layout\main_layout.xml:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/Card_View"
style="@style/CardViewStyle"
android:layout_width="480dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
card_view:cardCornerRadius="4dp"
android:elevation="2dp">
This will allow you to offer the animations in v21+ but also offer alternative animations in pre-v21 rather than the big blue/grey square.
Here is the card.xml I'm using as a drawable for those of you interested:
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:enterFadeDuration="150"
android:exitFadeDuration="150" >
<item android:state_pressed="true"
android:drawable="@drawable/card_on_press"/>
<item android:state_focused="true" android:state_enabled="true"
android:drawable="@drawable/card_on_focus"/>
<item android:state_enabled="true"
android:drawable="@drawable/card_default"/>
<item android:state_enabled="false"
android:drawable="@drawable/card_on_press"/>
</selector>
Note: Drawable default will be fine as a transparent item as CardView provides a default background for all android versions.
回答2:
Maybe the library has been updated but when I use the following it looks fine on older versions of Android.
You can use the 'CardView.Dark' and CardView.Light' (will auto-generate with the card support library)
In your values/styles.xml
<style name="CardViewStyle.Light" parent="CardView.Light">
<item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>
<style name="CardViewStyle.Dark" parent="CardView.Dark">
<item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>
Layouts for CardView
Create two layouts, one for dark and one for light. They will include the card views like this:
<android.support.v7.widget.CardView
android:id="@+id/my_card_view"
style="@style/CardViewStyle.Light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="2dp"
android:elevation="2dp">
... other layout stuff ...
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/my_card_view"
style="@style/CardViewStyle.Dark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="2dp"
android:elevation="2dp">
... other layout stuff ...
</android.support.v7.widget.CardView>
Take note to switching the style in each CardView.
Other customizations
If you want to customize the color rather than just having black or white, you can use the following:
To get the CardView drawable you can use:
View cardView = findViewById(R.id.my_card_view);
Drawable cardViewDrawable cardView.getBackground();
convertIcon(setViewBackground(cardView, cardViewDrawable));
My 'convertIcon' is simply the following:
/**
*
* @param drawable e.g. "getResources().getDrawable(R.drawable.my_drawable)"
* @param tint e.g. "Color.parseColor(lightTitlebarFg)"
* @return Drawable
*
*/
public static Drawable convertIcon(Drawable drawable, int tint) {
ColorFilter filter = new PorterDuffColorFilter(tint, PorterDuff.Mode.SRC_ATOP);
drawable.setColorFilter(filter);
return drawable;
}
My 'setViewBackground' is simply the following:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@SuppressWarnings("deprecation")
public static void setViewBackground(View view, Drawable drawable){
if (UIUtils.isJB()) {
view.setBackground(drawable);
} else {
view.setBackgroundDrawable(drawable);
}
}
StateListDrawable
If you want to create a StateListDrawable programmatically can use the following:
StateListDrawable states = new StateListDrawable();
states.addState(new int[] { android.R.attr.state_focused }, focusedDrawable);
states.addState(new int[] { android.R.attr.state_activated }, activatedDrawable);
states.addState(new int[] { android.R.attr.state_enabled }, defaultDrawable);
states.addState(new int[] {}, defaultDrawable);
回答3:
Here is the code that I used in the card_on_press.xml file which is stored in the drawable folder of the project:
<item>
<shape>
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
<solid android:color="@color/transparent" />
</shape>
</item>
<item>
<shape>
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
<solid android:color="@color/card_shadow_1_on_press" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<shape>
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
<solid android:color="@color/card_shadow_2_on_press" />
<corners android:radius="8dp" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="@color/card_background_on_press" />
<corners android:radius="8dp" />
</shape>
</item>
来源:https://stackoverflow.com/questions/24518376/override-android-l-cardview-state-pressed-for-older-versions-of-android