創建複合控件

創建複合控件是自定義View的一項基本技能,這裏要介紹的不是簡單的將控件在xml文件中拖到一起,而是可以自定義屬性的。這裏就以自定義的一個TopBar來當作例子,這個topbar有左右兩個按鈕,以及中間有個標題。


創建自定義屬性

既然說到了自定義屬性,那麼我們就要自己寫一個文件來描述我們需要自定義的屬性。在Values文件夾下創建attrs.xml文件,我們就將屬性寫在裏面。

<resources>
    <declare-styleable name="TopBar">
        <attr name="Title" format="string"></attr>
        <attr name="titleTextSize" format="dimension"></attr>
        <attr name="titleTextColor" format="color"></attr>
        <attr name="leftText" format="string"></attr>
        <attr name="leftTextBackground" format="reference|color"></attr>
        <attr name="leftTextColor" format="color"></attr>
        <attr name="rightText" format="string"></attr>
        <attr name="rightTextTextBackground" format="reference|color"></attr>
        <attr name="rightTextTextColor" format="color"></attr>
        ></declare-styleable>
</resources>

其中有幾項注意事項,首先declare-styleable name="TopBar" 中的name必須要跟你後來取的類名相同,後面的attr中的name救是屬性名稱,format就是屬性格式,是color,dimension還是string都在這裏申明,若要同時兼容兩種屬性格式,就用| 將其隔開。


創建自己的類

接下來就要創建自己的類了,我們取名叫TopBar並且繼承自RelativeLayout,當我們在寫構造方法的時候一定要注意要寫public TopBar(Context context, AttributeSet attrs)
因爲我們的屬性都包含在 AttributeSet中了。
接下來我們創建TypedArray數組將attrs吸收轉化爲我們好操作的數組。TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TopBar);
這個應該很簡單。得到了屬性數組,那麼我們就要將屬性一個個的取出來,放入我們自己創建的類的變量中。

        mLeftText = typedArray.getString(R.styleable.TopBar_leftText);

        mLeftTextColor = typedArray.getColor(R.styleable.TopBar_leftTextColor,0);

        mLeftBackGround = typedArray.getDrawable(R.styleable.TopBar_leftTextBackground);

        mRightBackGround = typedArray.getDrawable(R.styleable.TopBar_rightTextTextBackground);

        mRightText = typedArray.getString(R.styleable.TopBar_rightText);

        mRightTextColor = typedArray.getColor(R.styleable.TopBar_rightTextTextColor,0);

        mTitleSize = typedArray.getDimension(R.styleable.TopBar_titleTextSize,10);

        mTitleText = typedArray.getString(R.styleable.TopBar_Title);

        mTitleTextColor = typedArray.getColor(R.styleable.TopBar_titleTextColor,0);

        typedArray.recycle();

要記住的是color屬性要int變量來保存而不是Color對象,記得最後要recycler這個數組。
現在我們的TopBar空空如也,裏面什麼控件都沒有,那麼現在我們就要addView()幾個控件,那就是創建兩個Button和一個TextView。然後給這些控件把我們從屬性數組裏取出來的屬性設置進去.

 leftButton.setTextColor(mLeftTextColor);
        leftButton.setText(mLeftText);
        leftButton.setBackground(mLeftBackGround);

        rightButton.setTextColor(mRightTextColor);
        rightButton.setText(mRightText);
        rightButton.setBackground(mRightBackGround);

        titleView.setText(mTitleText);
        titleView.setTextColor(mTitleTextColor);
        titleView.setTextSize(mTitleSize);
        titleView.setGravity(Gravity.CENTER);

這些都很好理解。那麼現在我們又想控件都準備好了,那麼我們該如何往Bar中放置呢,很明顯,一個在左邊,一個在中間,一個在右邊。要給控件如何佈局,那麼就要用到LayoutParams 來幫忙了。

 mLefttParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        mLefttParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
        addView(leftButton, mLefttParams);

        mRightParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        mRightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
        addView(rightButton, mRightParams);

        mTitleParam = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        mTitleParam.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE);
        addView(titleView,mTitleParam);

再addRule時就可以按照我們想要的佈局來安排了,最後addView,就會按照你想要得佈局就行安排了。
那麼如果我想給控件增加點擊事件怎麼辦呢?
當然是給控件增加點擊事件了,我們自己創建一個監聽器接口。

 public interface topBarClickListenner//暴露接口給使用者
    {
        void leftClick();

        void RightClick();
    }

將這個接口暴露給使用者,當然我們的監聽器需要初始化,我們要在類中創建一個監聽器變量。private topBarClickListenner clickListenner;

然後在set方法中讓使用者初始化它

 public void setOnTopBarClickListenner(topBarClickListenner listenner)//在調用時初始化自定義的監聽器
    {
        this.clickListenner = listenner;
    }

接着我們就在構造函數裏調用監聽器了。

rightButton.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                clickListenner.RightClick();
            }
        });

        leftButton.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                clickListenner.leftClick();
            }
        });

分別調用我們的左右按鈕的方法.
當我們在外部使用這個監聽器的時候就是這樣的。

 topBar.setOnTopBarClickListenner(new TopBar.topBarClickListenner()
        {
            @Override
            public void leftClick()
            {
                Toast.makeText(MainActivity.this, "你點擊了左按鈕", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void RightClick()
            {
                Toast.makeText(MainActivity.this, "你點擊了右按鈕", Toast.LENGTH_SHORT).show();
            }
        });

佈局文件中使用自定義view

 <com.program.gyf.viewtest.TopBar
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:id="@+id/topBar"
        Hugo:leftText="haha"
        Hugo:leftTextColor="#FFFFFF"
        Hugo:leftTextBackground="@mipmap/ic_launcher"
        Hugo:rightText="yeye"
        Hugo:rightTextTextBackground="@mipmap/ic_launcher"
        Hugo:rightTextTextColor="#FFFFFF"
        Hugo:Title="自定義的"
        Hugo:titleTextColor="#123412"
        Hugo:titleTextSize="10sp">


    </com.program.gyf.viewtest.TopBar>

就這樣使用,要注意的一點是要使用代碼中Hugo(可以自定義名稱)需要在最外層ViewGroup中聲明與默認不同的命名控件。默認的命名控件就是這麼申明的xmlns:android="http://schemas.android.com/apk/res/android"
而我們自己的命名空間這麼申明

    xmlns:Hugo="http://schemas.android.com/apk/res-auto"

注意只有在Android Studio下才能這麼申明。


最後的效果

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章