2- 自定义组合控件-通用Common_Title
前言:
自定义组合控件应该是自定view中比较简单的一种情况了;
自定义view的常见三种情况:
- 自定义组合控件
- 自定义继承控件
- 自定义自绘制控件
1:自绘控件
View上
所展现的内容全部都是我们自己绘制出来的。绘制的代码是写在onDraw()
方法中。
2:组合控件
组合控件的意思就是,我们并不需要自己去绘制视图上显示的内容,而只是用系统原生的控件就好了,但我们可以将几个系统原生的控件组合到一起,这样创建出的控件就被称为组合控件。
3:继承控件 --需要设计事件处理机制
继承控件的意思就是,我们并不需要自己重头去实现一个控件,只需要去继承一个现有的控件,然后在这个控件上增加一些新的功能,就可以形成一个自定义的控件了。这种自定义控件的特点就是不仅能够按照我们的需求加入相应的功能,还可以保留原生控件的所有功能
自定义组合控件,也就是将多个系统控件组合在一起,形成一个新的控件,可以大大的提高 控件的复用性,减少代码的冗余程度和提高效率;
常用的复用的方法是采用include
标签,将布局重用,这样的方法固然是可取的,但是如果重用的布局是大部分相同,但是又有一点差异性的;就有点问题了,因为include
只能将布局完全的重用过来,但是不能修改这个布局的一些差异,这样就只能在代码中动态去修改相关的属性,会导致与activity
的耦合性很大,如果activity
的逻辑不复杂这样还好一点,一旦activity
的逻辑复杂,那么维护起来就很困难;
所以使用自定义组合控件的方式完全完全可以将这种差异通过自定义属性的方式,在xml
布局中设置,而不用过分依赖代码动态改变,而且方便维护和控制,并且扩展性极强;
/自定义一个CommonTitle组合控件*************/
1- 先上图 看看
2- 首先我们要写一个xml的布局 commonTitleLayout
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@android:color/holo_green_light">
<Button
android:id="@+id/title_left_btn"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="@null"
android:text=""/>
<TextView
android:id="@+id/title_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@color/colorAccent"
android:text=""/>
<Button
android:id="@+id/title_right_btn"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="@null"
android:layout_alignParentRight="true"
android:text=""/>
</merge>
注释:这里的顶层使用merge
是为了减少一层嵌套,因为整个布局最后会成为一个viewGroup
的子view
,也是属于一种布局优化
3- 开始自定义我们的组合控件了,继承一个RelativeLayout
,将上面的xml
变成他的子view
public class CommonTitileView extends RelativeLayout{
private Button leftBtn,rightBtn;
private TextView titleContent;
public CommonTitileView(Context context) {
this(context,null);
}
public CommonTitileView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CommonTitileView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//将 R.layout.item_common_title生成的view 绑定到当前的CommonTitileView下作为子view
LayoutInflater.from(context).inflate(R.layout.item_common_title,this,true);
initView();
initAttrs(context,attrs);
}
private void initView() {
leftBtn = (Button) findViewById(R.id.title_left_btn);
rightBtn = (Button) findViewById(R.id.title_right_btn);
titleContent = (TextView) findViewById(R.id.title_content);
}
/**
* 设置从xml布局中获取的属性
* @param context
* @param attrs
*/
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CommonTitileView);
if(typedArray == null)return;
int titleBackground = typedArray.getResourceId(R.styleable.CommonTitileView_title_background, R.color.colorAccent);
setBackgroundResource(titleBackground);
String contentText = typedArray.getString(R.styleable.CommonTitileView_title_content_text);
titleContent.setText(contentText);
float dimension = typedArray.getDimension(R.styleable.CommonTitileView_title_content_size, 20);
titleContent.setTextSize(dimension);
int color = typedArray.getColor(R.styleable.CommonTitileView_title_content_color, Color.BLACK);
titleContent.setTextColor(color);
boolean leftBtnVisblity = typedArray.getBoolean(R.styleable.CommonTitileView_left_button_visible, true);
if(leftBtnVisblity){
leftBtn.setVisibility(VISIBLE);
}else {
leftBtn.setVisibility(INVISIBLE);
}
boolean rightBtnVisblity = typedArray.getBoolean(R.styleable.CommonTitileView_right_button_visible, true);
if(rightBtnVisblity){
rightBtn.setVisibility(VISIBLE);
}else {
rightBtn.setVisibility(INVISIBLE);
}
int leftBtnColor = typedArray.getColor(R.styleable.CommonTitileView_left_button_text_color, Color.BLACK);
leftBtn.setTextColor(leftBtnColor);
int rightBtnColor = typedArray.getColor(R.styleable.CommonTitileView_right_button_text_color, Color.BLACK);
rightBtn.setTextColor(rightBtnColor);
String rightText = typedArray.getString(R.styleable.CommonTitileView_right_button_text);
if(TextUtils.isEmpty(rightText)){
int rightDrawable = typedArray.getResourceId(R.styleable.CommonTitileView_right_button_drawable, R.mipmap.ic_launcher);
rightBtn.setBackgroundResource(rightDrawable);
}else {
rightBtn.setText(rightText);
}
String leftText = typedArray.getString(R.styleable.CommonTitileView_left_button_text);
if(TextUtils.isEmpty(leftText)){
int leftDrawable = typedArray.getResourceId(R.styleable.CommonTitileView_left_button_drawable, R.mipmap.ic_launcher);
leftBtn.setBackgroundResource(leftDrawable);
}else {
leftBtn.setText(leftText);
}
typedArray.recycle();
}
/**
* 左右按钮的监听
* @param listener
*/
public void setCommonTitleOnclick(OnClickListener listener){
leftBtn.setOnClickListener(listener);
rightBtn.setOnClickListener(listener);
}
4- 至此我们的自定义组合控件就完成了,下面就是如何调用他了,在需要使用到的地方直接调用该·view·就可以了
<com.example.view.CommonTitileView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/commonTitle"
android:layout_width="match_parent"
android:layout_height="40dp"
app:title_content_text="我是title1" //自定义属性
app:title_content_size="8dp"
app:left_button_text="back"
app:right_button_visible="false"
app:left_button_visible="true"
>
</com.example.bomei.myapplication.view.CommonTitileView>
5- 当然,别忘了还需要自定义属性,在value
中
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CommonTitileView">
<attr name="title_content_text" format="string"/>
<attr name="title_background" format="reference|integer"/>
<attr name="title_content_size" format="dimension"/>
<attr name="title_content_color" format="color"/>
<attr name="left_button_visible" format="boolean"/>
<attr name="right_button_visible" format="boolean"/>
<attr name="left_button_text" format="string"/>
<attr name="right_button_text" format="string"/>
<attr name="left_button_text_size" format="dimension"/>
<attr name="right_button_text_size" format="dimension"/>
<attr name="right_button_text_color" format="color"/>
<attr name="left_button_text_color" format="color"/>
<attr name="left_button_drawable" format="reference|integer"/>
<attr name="right_button_drawable" format="reference|integer"/>
</declare-styleable>
</resources>
这样就设计完了,呵呵,是不是很简单!
是不是还没玩儿够,很好,那我们再来做一个这样的自定义控件;
效果图如下:
/******************代码区*********************/
public class SetingView extends RelativeLayout {
TextView tv_dis_statue, title_text;
CheckBox checkBox;
public SetingView(Context context) {
this(context,null);
}
public SetingView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public SetingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater.from(context).inflate(R.layout.item_setting_view, this, true);
initView(context, attrs);
}
private void initView(Context context, AttributeSet attrs) {
tv_dis_statue = (TextView) findViewById(R.id.tv_dis_statue);
checkBox = (CheckBox) findViewById(R.id.my_check_box);
title_text = (TextView) findViewById(R.id.tv_update);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SettingView);
String dis_statue_on_text = typedArray.getString(R.styleable.SettingView_dis_statue_on_text);
String dis_statue_off_text = typedArray.getString(R.styleable.SettingView_dis_statue_off_text);
String titleText = typedArray.getString(R.styleable.SettingView_title_text);
boolean checked = typedArray.getBoolean(R.styleable.SettingView_set_check,false);
checkBox.setChecked(checked);
title_text.setText(titleText);
if (isChecked()) {
tv_dis_statue.setText(dis_statue_on_text);
} else {
tv_dis_statue.setText(dis_statue_off_text);
}
}
private boolean isChecked() {
return checkBox.isChecked();
}
/**
* 设置checkbox的状态
* @param isChecked
*/
public void setChecked(boolean isChecked){
checkBox.setChecked(isChecked);
//相当于把sv_setting_update.setDes("已打开提示更新");封装到了setChecked方法中
if (isChecked()) {
// tv_setting_des.setText(des_on);
}else{
// tv_setting_des.setText(des_off);
}
}
}
/***************************end****************************/
结果如下了: