Android 自定義view

wongstar發表於2018-01-23

在需求文案中有時候需要顯示如下資訊 1.點選某行顯示詳情ui,如下圖 2.填充某行左由兩邊title資訊. 3.箭頭的動畫. 通過上面需求定義了一個custom UIView Demo code github傳送點:github.com/wongstar/an…

如圖一所需要實現的需求。

圖一

下面簡單的分析所需要的知識點: 1.在attrs.xml中定義view 的style中屬性,這些屬性可以自定義如下:

<declare-styleable name="pullup">
        <attr name="leftText" format="string" />
        <attr name="leftTextSize" format="dimension" />
        <attr name="leftTextColor" format="color" />
        <attr name="leftTextVisible" format="integer" />
        <attr name="topBackground" format="integer" />
        <attr name="rightText" format="string" />
        <attr name="rightTextSize" format="dimension" />
        <attr name="rightTextColor" format="color" />
        <attr name="rightTextVisible" format="integer" />
        <attr name="moreVisible" format="integer"></attr>
        <attr name="tipVisible" format="integer"></attr>
        <attr name="tipText" format="string"></attr>
        <attr name="isMoreView" format="integer"></attr>
        <attr name="haveChildView" format="integer"></attr>
 </declare-styleable>
複製程式碼

如上述程式碼定義了當前行的左邊text,textsize,textcolor ,當前行的右邊的text,textsize,textcolor,visible,定義了是否存在moreview引數 format對應的是name相關屬性的類別,具體的format對應的類別列表如下: https://developer.android.com/reference/android/R.attr.html

在xml中呼叫attr中自定義的屬性

xmlns:pullup="http://schemas.android.com/apk/res-auto"
<pull.star.com.pullview.PullUpView
        android:id="@+id/zero"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dp"
        android:background="@color/white"
        android:minHeight="@dimen/setting_column_size"
        pullup:leftText="wight"
        pullup:leftTextSize="20sp"
        pullup:rightTextVisible="0"
        pullup:rightText="80"
        pullup:isMoreView="1"
        pullup:rightTextSize="20sp">
複製程式碼

要讓xml中pullup的屬效能夠找到,需要在xml中宣告xmlns:pullup的名稱空間,這樣後面的xml就能找到對應的attr中自定義的pullup屬性,這一部非常重要,否則不能編譯成功。

那在UIView中如何呼叫獲取到對應的屬性呢?

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.pullup); CharSequence leftText = a.getText(R.styleable.pullup_leftText); 通過呼叫TypedArray就能獲取到對應的引數,比如上面的pullup_leftText. TypedArray是android framework層通過解析xml獲取到xml中屬性值.通過context來獲取到。具體可以參考LayoutInflater 原始碼

再分析下PullUpView的構造。 public class PullUpView extends LinearLayout implements View.OnClickListener

1.該view是繼承LinearLayout,這樣你的detailView就可以直接add進去 2.設定當前LinearLayout的Orientation是VERTICAL 3.該view的第一個view是LayoutInflater一個FrameLayout具體如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:id="@+id/flTop"
    android:focusable="true"
    android:clickable="true"
    android:background="@drawable/selector_list_view"
    android:minHeight="@dimen/setting_column_size">
        <TextView
            android:id="@+id/tvLeft"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|left"
            android:layout_marginLeft="15dp"
            android:textColor="@color/black"
            android:textSize="@dimen/card_item_text_size" />
        <TextView
            android:visibility="gone"
            android:id="@+id/tvTip"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="20dp"
            android:layout_gravity="center_vertical|left"
            android:textSize="10sp"
            android:textColor="@color/share_title_color"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    <RelativeLayout
        android:id="@+id/rlPullUp"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_gravity="center_vertical|right"
        android:layout_marginRight="10dp"
        android:clickable="true">

        <ImageView

            android:id="@+id/ivPullUp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="15dp"></ImageView>
    </RelativeLayout>
    <TextView
        android:id="@+id/tvRight"
        android:textColor="@color/black"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|right"
        android:layout_marginRight="60dp"
        android:textSize="@dimen/card_item_text_size" />
</FrameLayout>
複製程式碼

通過LayoutInflater 把framelayout xml inflater到該LinearLayout中 LayoutInflater inflater = LayoutInflater.from(context); rlTop = (FrameLayout) inflater.inflate(R.layout.menu_item_top_view, null); addView(rlTop, 0); setOrientation(VERTICAL);//

通過上述的方式,把framelayout add到LinearLayout中

最後就是show Detail view 和hideDetailView,注意點是:Child的index是從1開始計算:

private void showViews() {
	for (int i = 1; i < getChildCount(); i++) {
		getChildAt(i).setVisibility(View.VISIBLE);
		}
	}
private void hideViews() {
        for (int i = 1; i < getChildCount(); i++) {
		getChildAt(i).setVisibility(View.GONE);
	}
}
複製程式碼

得出來的整體UI效果圖如下(圖二)所示:

圖二

#####想隨時瞭解我的動態,歡迎大家關注我的個人公眾號蟻農之家

蟻農之家.jpg

相關文章