之前的自定義控件——初識自定義控件,
我們了解到了自定義控件分為三種,自制控件,組合控件,拓展控件。
而我們在
自制控件1 開關按鈕
自制控件2 —— 自制控件 仿qq側滑菜單
也已經針對自制控件寫了幾個小demo
現在,讓我們開始進行自定義控件的第二種,組合控件。
組合控件常常和自定義屬性結合在一起,在本文的后半部分,我們也會涉及到自定義屬性。
正式開始
假設我們有很多個這樣的設置框,
組合控件其實可以分為這么大概幾個步驟
1、新建一個類,比如叫做JmLayout,繼承自RelativeLayout或者LinearLayout等。(反正都是繼承自ViewGroup的子類,因為組合嘛,里面要放控件)
2、寫一個xml布局文件,這里就是我們想要組合的控件。
3、在JmLayout里面的構造方法將xml填充進去
4、利用JmLayout的全路徑名就可以成功使用這個組合控件。
至此組合控件完成,
一、組合幾個控件成為一個新的控件
1、新建一個類,比如叫做JmLayout,繼承自RelativeLayout或者LinearLayout等。(反正都是繼承自ViewGroup的子類,因為組合嘛,里面要放控件)
public class JmLayout extends RelativeLayout{
private View view;
public JmLayout(Context context) {
super(context);
}
public JmLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
2、寫一個xml布局文件,這里就是我們想要組合的控件。
item_my_style_view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#88877b7b"
>
<TextView
android:id="@+id/mTvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="選項名稱"
android:textSize="20dp"
android:textColor="#ff0000"
android:layout_margin="10dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="備注"
android:textSize="18dp"
android:layout_below="@id/mTvName"
/>
<ImageView
android:id="@+id/mIv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10sp"
/>
</RelativeLayout>
3、在JmLayout里面的構造方法將xml填充進去
JmLayout
注意 View.inflate方法的第三個參數在這里我們寫的是JmLayout.this
public class JmLayout extends RelativeLayout{
private View view;
public JmLayout(Context context) {
super(context);
initView();
}
public JmLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
// View.inflate View的填充器
// 最后一個參數表示把誰當做父容器,這里我們當MySettingView當做父容器
// 當然,如果這里寫null就什么都沒有顯示了
view = View.inflate(getContext(),R.layout.item_my_style_view, JmLayout.this);
}
}
4、利用JmLayout的全路徑名就可以成功使用這個組合控件。
main_activity
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.amqr.combinationview.MainActivity">
<com.amqr.combinationview.JmLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</com.amqr.combinationview.JmLayout>
</RelativeLayout>
MainActivity 當前那里都不需要動。
//本Demo是為演示 組合控件
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
運行效果圖:
二、自定義屬性
經過上過上面的步驟,可能有人會說,我直接include不就好,何必這么麻煩。組合控件的當然不止只有這點用處。
下面就結合來演示下 組合控件+自定義屬性
什么是屬性?就比如TextView來說,text是屬性,layout_width是屬性,textSize也是屬性,但是這些都是系統給我們的。我們這里來自定義一下屬性。
1,在values文件夾下新建一個名為 attrs 的資源文件(名字一定得是 attrs)
根節點是resources
declare-styleable節點的name是指明適用于哪一個 控件
<attr name="kind" format="string"/> name 是自定義屬性的名稱,format是自定義屬性的輸入類型
<?xml version="1.0" encoding="utf-8"?>
<resources>
// 這個自定義屬性適用于哪個控件
<declare-styleable name="JmLayout">
// name 自定義屬性的名稱 format 自定屬性的輸入類型
<attr name="kind" format="string"/>
<attr name="desc" format="string"/>
</declare-styleable>
</resources>
2、引用到當前控件的布局文件根節點添加命名空間,使用自定義屬性
- 先添加命名空間
eclipse下的命名空間命名規則:
xmlns:命名空間="http://schemas.android.com/apk/res/程序包名"
android studio下的命名空間命名規則:
xmlns:命名控件="http://schemas.android.com/apk/res-auto"
- 后在控件里通過 命名空間名:自定義屬性名="屬性值" 的方式使用自定義屬性
大概如下使用
<?xml version="1.0" encoding="utf-8"?>
<!--xmlns:命名空間="http://schemas.android.com/apk/res/程序包名"-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:amqr="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.amqr.combinationview.MainActivity">
<com.amqr.combinationview.JmLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
amqr:kind="皮膚"
>
</com.amqr.combinationview.JmLayout>
</RelativeLayout>
3、在自定義控件里面對自定義屬性進行相關的操作(可選)
public class JmLayout extends RelativeLayout{
private View view;
private TextView mTvKind;
private TextView mTvDesc;
public JmLayout(Context context) {
super(context);
initView();
}
public JmLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
// 得到自定義輸入的值
String kind = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "kind");
mTvKind.setText(kind);
}
private void initView() {
// View.inflate View的填充器
// 最后一個參數表示把誰當做父容器,這里我們當MySettingView當做父容器
// 當然,如果這里寫null就什么都沒有顯示了
view = View.inflate(getContext(),R.layout.item_my_style_view, JmLayout.this);
mTvKind = (TextView) view.findViewById(R.id.mTvKind);
mTvDesc = (TextView) view.findViewById(R.id.mTvDesc);
}
}
最終運行效果
在上面的代碼中,我們還有一個自定義屬性desc沒有使用到,但是使用方式相同。
通過自定義控件+自定義屬性的方式,我們可以一次造輪子,多次方便地使用,減少冗余代碼,提高開發效率。
關于組合控件的設置框的博文到此結束
在自制控件2 —— 自制控件 仿qq側滑菜單中,將繼續進行組合控件的demo編寫。
本文完。