一、自定義組合控件介紹
開發(fā)中,為了使用的方便,經(jīng)常把一些控件組合成一個(gè)控件,那樣就成為了我們的自定義組合控件,嚴(yán)格意義來說,自定義組合控件并不屬于“自定義控件”。
二、自定義組合控件步驟 1、創(chuàng)建一個(gè)java類,繼承View(或者View的子類),改寫構(gòu)造函數(shù)。如下所示,NumberAddSubView是我們的自定義組合控件的名字。通過構(gòu)造函數(shù)的改造,使得一個(gè)調(diào)用另外一個(gè),最終我們只要修改的是參數(shù)最多的那個(gè)就可以了。
public NumberAddSubView(Context context) { this(context, null); } public NumberAddSubView(Contextcontext, AttributeSet attrs) { this(context, attrs, 0); } public NumberAddSubView(Contextcontext, AttributeSet attrs, intdefStyleAttr) { super(context, attrs, defStyleAttr); }
2、為這個(gè)自定義組合控件創(chuàng)建一個(gè)布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape_number_view_bg" android:gravity="center" android:orientation="horizontal" android:padding="5dp"> <Button android:id="@+id/btn_sub" style="@style/NumberAddSubDefStyle" android:gravity="center" android:text="-"/> <EditText android:id="@+id/et_num" style="@style/TextDefStyle" /> <Button android:id="@+id/btn_add" style="@style/NumberAddSubDefStyle" android:gravity="center" android:text="+"/> </LinearLayout>
3、加載布局,通過ID找到所有控件。
private void initView(Context context) { View view = LayoutInflater.from(context).inflate(R.layout.number_add_sub_view, this, true); btn_add = (Button) view.findViewById(R.id.btn_add); btn_sub = (Button) view.findViewById(R.id.btn_sub); et_num = (EditText) view.findViewById(R.id.et_num); btn_add.setOnClickListener(this); btn_sub.setOnClickListener(this); et_num.addTextChangedListener(this); } 4、自定義屬性:在value文件夾創(chuàng)建attrs.xml文件,并且添加自定義屬性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="NumberAddSubView"> <attr name="value" format="integer|reference"/> <attr name="maxValue" format="integer|reference"/> <attr name="minValue" format="integer|reference"/> <attr name="btnDrawable" format="reference"/> </declare-styleable> </resources> 5、最后,在自定義控件里面做一切你想做的事情,例如按鈕點(diǎn)擊回調(diào),文字變化回調(diào)等。 下面是菜鳥商城項(xiàng)目中的需求: 自定義數(shù)字加減控件 1.輸入框只能是數(shù)字,且不能通過鍵盤輸入 2.通過加減按鈕操作數(shù)字 3.監(jiān)聽加減按鈕 4.數(shù)字有最小值和最大值的限制 5.自定義屬性 下面給出完整的java代碼: import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.support.v7.widget.TintTypedArray; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; /** * 自定義數(shù)字加減控件 */ public class NumberAddSubView extendsLinearLayout implements View.OnClickListener, TextWatcher { private int maxValue; private int minValue; private int value; private Button btn_add; private Button btn_sub; private EditText et_num; public NumberAddSubView(Contextcontext) { this(context, null); } public NumberAddSubView(Contextcontext, AttributeSet attrs) { this(context, attrs, 0); } public NumberAddSubView(Contextcontext, AttributeSet attrs, intdefStyleAttr) { super(context, attrs, defStyleAttr); //初始化布局 initView(context); //讀取自定義屬性的值并且設(shè)置 TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, attrs, R.styleable.NumberAddSubView, defStyleAttr, 0); value = a.getInt(R.styleable.NumberAddSubView_value, 1); maxValue = a.getInt(R.styleable.NumberAddSubView_maxValue, 1); minValue = a.getInt(R.styleable.NumberAddSubView_minValue, 1); Drawable btnBg = a.getDrawable(R.styleable.NumberAddSubView_btnDrawable); if (btnBg != null) { btn_add.setBackgroundDrawable(btnBg); btn_sub.setBackgroundDrawable(btnBg); } a.recycle(); } private void initView(Context context) { View view = LayoutInflater.from(context).inflate(R.layout.number_add_sub_view, this, true); btn_add = (Button) view.findViewById(R.id.btn_add); btn_sub = (Button) view.findViewById(R.id.btn_sub); et_num = (EditText) view.findViewById(R.id.et_num); btn_add.setOnClickListener(this); btn_sub.setOnClickListener(this); et_num.addTextChangedListener(this); } /** * 數(shù)字變化的監(jiān)聽 */ public interface OnNumberChangeListener { void onChange(int value, boolean isInRange); } private OnNumberChangeListener mListener; public void setOnNumberChangeListener(OnNumberChangeListener listener) { this.mListener = listener; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (mListener != null) { if (!TextUtils.isEmpty(s)) { int val = Integer.parseInt(s.toString()); if (val <= maxValue && val >= minValue) { mListener.onChange(val, true); } else { mListener.onChange(val, false); } } } } @Override public void afterTextChanged(Editable s) { } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_add: valueAdd(); break; case R.id.btn_sub: valueSub(); break; } } public void valueAdd() { if (!TextUtils.isEmpty(et_num.getText())) { int val = Integer.parseInt(et_num.getText().toString()); if (val < maxValue) { val++; } setValue(val); } } public void valueSub() { if (!TextUtils.isEmpty(et_num.getText())) { int val = Integer.parseInt(et_num.getText().toString()); if (val > minValue) { val--; } setValue(val); } } public int getMaxValue() { return maxValue; } public void setMaxValue(int maxValue) { this.maxValue = maxValue; } public int getMinValue() { return minValue; } public void setMinValue(int minValue) { this.minValue = minValue; } public int getValue() { return value; } public void setValue(int value) { this.value = value; et_num.setText(value + ""); } public void setRange(int minValue, int maxValue) { this.minValue = minValue; this.maxValue = maxValue; } }
三、自定義組合控件的使用 根據(jù)自己如何定義,使用的方法都不一樣。例如我在自定義控件里面添加了文字變化的回調(diào),那么我們就可以進(jìn)行監(jiān)聽。
不過大體來說,跟基本控件以及“自定義控件”的使用一模一樣。
1、在布局文件中放置自定義組合控件:
需要注意的是,命名空間需要自定義一個(gè),隨便寫“app”即可,至于寫什么沒有要求,但是它的值需要使用res-auto。
注意添加上我們自定義的屬性。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_green_light"> <com.nan.numaddsubview.NumberAddSubView android:id="@+id/num_view" android:layout_width="wrap_content" android:layout_height="wrap_content" app:maxValue="5" app:minValue="1" app:value="1"/> </RelativeLayout>
2、java代碼中的使用:
這里我設(shè)置文字變化的監(jiān)聽。
public class MainActivity extendsAppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NumberAddSubView numberAddSubView = (NumberAddSubView) findViewById(R.id.num_view); // numberAddSubView.setMaxValue(10); numberAddSubView.setOnNumberChangeListener(new NumberAddSubView.OnNumberChangeListener() { @Override public void onChange(int value, boolean isInRange) { Toast.makeText(MainActivity.this, value + "" + isInRange, Toast.LENGTH_SHORT).show(); } }); } }
四、效果 為了方便看,我把activity的背景顏色換了一下。好了,今天的筆記就到這里~\(≧▽≦)/~啦啦啦。
|