2019年3月8日 星期五

Android 使用 Java 手動新增 CardView 及設定漣漪效果

Android 中要手動設定漣漪 (Ripple) 效果,要做成 TypedArray  或  TypeValue 的形式,才能令 CardView.setForeground 去讀取目標要的 Drawable 波紋效果。


(圖) 為 CardView 手動新增效果。


使用XML 新增



手動的情況,在 XML 會這樣設定:


<android.support.v7.widget.CardView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:layout_marginBottom="16dp"
    android:clickable="true"
    android:foreground="?android:attr/selectableItemBackground"
    app:cardBackgroundColor="@color/cyan_50"
    app:cardCornerRadius="8dp"
    app:cardElevation="8dp">

    <TextView
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:fontFamily="@font/noto_sans_bold"
        android:padding="20dp"
        android:text="屏東市"
        android:textAlignment="center"
        android:textColor="@color/cyan"
        android:textSize="25sp"
        tools:text="屏東市" />
</android.support.v7.widget.CardView>

使用其中的 "android:foreground" 這段屬性。



使用 Java 新增


在 Java 中直接新增可以這麼設定:


CardView card = new CardView(getContext());

//basic attribute setup
card.setClickable(true);
card.setCardBackgroundColor(getResources().getColor(R.color.cyan_50));


//android:foreground setup
int[] attrs = new int[]{R.attr.selectableItemBackground};
TypedArray typedArray = getActivity().obtainStyledAttributes(attrs);
card.setForeground(typedArray.getDrawable(0));
typedArray.recycle();


//mind: all unit is using px, so you need to convert dip to px manually!
card.setRadius(conv.dpToPx(8));
card.setElevation(conv.dpToPx(8));

//setup width/height
ViewGroup.LayoutParams l = new BaseCardView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

//setup margins
((BaseCardView.LayoutParams) l).setMargins(conv.dpToPx(16),0,conv.dpToPx(16),conv.dpToPx(16));
card.setLayoutParams(l);

//setup textview.
TextView tv = new TextView(rootView.getContext());
tv.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
tv.setText(cityName);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams((int) conv.dpToPx(150),ViewGroup.LayoutParams.WRAP_CONTENT);
tv.setPadding((int) conv.dpToPx(20),(int) conv.dpToPx(20),(int) conv.dpToPx(20),(int) conv.dpToPx(20));
tv.setTypeface(Typeface.create("@font/noto_sans_bold", Typeface.BOLD));
tv.setLayoutParams(params);
tv.setTextColor(getResources().getColor(R.color.cyan));
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setTextSize(25);

//add textview to parent
card.addView(tv);

其中使用 TypedArray 中放入所有需要的外部屬性號碼 (attrs 陣列),然後設定 foreground 時要變更為 getDrawable 而不是 getResourceId。


Reference:
https://stackoverflow.com/questions/7896615/android-how-to-get-value-of-an-attribute-in-code
https://stackoverflow.com/questions/18013971/how-to-use-standard-attribute-androidtext-in-my-custom-view

沒有留言:

張貼留言

© ERIC RILEY , 自由無須告知轉貼
Background Japanese Sayagata by Olga Libby