自定义控件实现的方式主要有:重写控件,组装控件,继承View,opengL等。这里说的控件是指安卓自有的控件,TextView、Button等。
本篇先讲第一种方式:重写控件。
重写控件,也就是继承控件类,主要是重写原有的方法,增加自定义方法,修改原有部分属性。更多的应用场景是为父控件设置一个特定的布局,或者是设置特定的点击响应。以便在app里达到重用或者是简化代码的目的。是自定义控件的一个常用的方式。
这里我将创建一个自定义的Dialog用来讲解这个方法。
我们将修改Dialog原有的样式,提供确定和取消键。
首先,我们构造一个Dialog的完整布局。注意是完整布局,包括标题等。整个弹窗的视图都在这里创建。对于原有标题,我们将通过创建无标题样式将其去掉。这样我们可以很方便地控制标题的位置等。以下是名为dialog.xml的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#b98304"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="30dp"
android:layout_marginBottom="15dp"
android:layout_marginRight="30dp"
android:textColor="#FFFFFF"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="2dp"
android:includeFontPadding="false"
android:background="#992a942f"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginBottom="15dp"
android:gravity="center">
<TextView
android:id="@+id/message"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#FFFFFF"/>
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#992a942f"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/positiveButton"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent"
android:includeFontPadding="false"
android:textSize="18sp"
android:textColor="#FFFFFF"
android:gravity="center"
android:singleLine="true"
android:clickable="true"
android:text="确定"/>
<TextView
android:id="@+id/txv_dialog_common_diliver"
android:layout_width="1dp"
android:layout_height="60dp"
android:includeFontPadding="false"
android:background="#992a942f"/>
<TextView
android:id="@+id/negativeButton"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="fill_parent"
android:includeFontPadding="false"
android:textSize="18sp"
android:textColor="#FFFFFF"
android:gravity="center"
android:singleLine="true"
android:clickable="true"
android:text="取消"/>
</LinearLayout>
</LinearLayout>
然后,我们还需要创建一个style文件,其属性大致有以下即可:
<style
name="CustomDialog"
parent="android:style/Theme.Dialog">
<item
name="android:windowFrame">@null</item><!--边框 -->
<item
name="android:windowIsFloating">true</item><!--是否浮现在activity之上 -->
<item
name="android:windowIsTranslucent">true</item><!--半透明 -->
<item
name="android:windowNoTitle">true</item><!--无标题 -->
<item
name="android:windowBackground">@android:color/transparent</item><!--背景透明 -->
<item
name="android:backgroundDimEnabled">true</item><!--模糊 -->
</style>
接着,也是最关键的一步,就是要继承一个Dialog类。然后调用父类的方法,为自定义控件填充视图。并重写一些必要的方法。
/**
* 自定义控件-自定义对话框
* @author Ives
*
*/
public class CustomDialog extends Dialog {
private TextView titleTxv; //标题
private TextView msgTxv; //提示内容文字
private TextView positiveTxv; //确定按钮
private TextView negativeTxv; //取消按钮
/**
* @param context
*/
public CustomDialog(Context context) {
super(context,R.style.CustomDialog); //自定义style主要去掉标题,标题将在setCustomView中自定义设置
setCustomView();
}
public CustomDialog(Context context, boolean cancelable,
OnCancelListener cancelListener) {
super(context, R.style.CustomDialog);
this.setCancelable(cancelable);
this.setOnCancelListener(cancelListener);
setCustomView();
}
public CustomDialog(Context context, int theme) {
super(context, R.style.CustomDialog);
setCustomView();
}
/**
* 设置整个弹出框的视图
*/
private void setCustomView(){
View mView = LayoutInflater.from(getContext()).inflate(R.layout.dialog, null);
titleTxv = (TextView) mView.findViewById(R.id.title);
msgTxv = (TextView) mView.findViewById(R.id.message);
positiveTxv = (TextView) mView.findViewById(R.id.positiveButton);
negativeTxv = (TextView) mView.findViewById(R.id.negativeButton);
super.setContentView(mView);
}
@Override
public void setContentView(View view){
//重写本方法,使外部调用时不可破坏控件的视图。
//也可以使用本方法改变CustomDialog的内容部分视图,比如让用户把内容视图变成复选框列表,图片等。这需要获取mView视图里的其它控件
}
@Override
public void setTitle(CharSequence title) {
titleTxv.setText(title);
}
@Override
public void setTitle(int titleId) {
setTitle(getContext().getString(titleId));
}
/**
* 设置提示内容文字
* @param msg
*/
public void setMessage(CharSequence msg){
msgTxv.setText(msg);
}
/**
* 设置确定键文字
* @param text
*/
public void setPositiveText(CharSequence text){
positiveTxv.setText(text);
}
/**
* 设置取消键文字
* @param text
*/
public void setNegativeText(CharSequence text){
negativeTxv.setText(text);
}
/**
* 确定键监听器
* @param listener
*/
public void setOnPositiveListener(View.OnClickListener listener){
positiveTxv.setOnClickListener(listener);
}
/**
* 取消键监听器
* @param listener
*/
public void setOnNegativeListener(View.OnClickListener listener){
negativeTxv.setOnClickListener(listener);
}
}
代码里说得比较详细,这是比较基本的一个实现。使用方式直接new之后,set完上面几个方法,调用show方法即可显示。
其实这个例子已经有点偏向组装控件的方式了,组装控件将会在下一篇中讲到。更典型更纯粹的继承控件的例子你可以写一个自定义的Toast或者TextView,这样更纯粹是继承控件,就没有组装控件的内容了。总的来说,继承控件只要有以下两步:
1.继承一个自有控件;
2.重写父类的一些方法。