本文讲一下自定义控件的另一种方法:继承View,或者叫重写View,是属于自定义绘制的方式。
继承View类在理解起来比较高级,但是实际编写起来是非常简单的。只需要提供一个构造器并调用View构造器,并重写onDraw方法。即可完成一个基本的自定义View。
public class CustomView extends View {
private Paint paint = new Paint();
private RectF rf = new RectF();
/**
* @param context
*/
public CustomView(Context context) {
super(context);
initViewParams();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
initViewParams();
}
private void initViewParams(){
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
rf.set(0f, 0f, 300f, 200f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.BLUE);
canvas.drawArc(rf, 0f, 360f, true, paint);
}
}
像这样,CustomView就是我定义的一个控件,显示的效果是一个蓝色椭圆。你可以在xml文件里像别的原生控件一样使用,也可以在java代码里面new一个实例来使用。但是,仅有以上代码是不够的,比如在xml文件里面设置的layout_width过小的话,椭圆就显示不完整。这种情况应该在代码里加以判断。稍后会告诉大家处理的方法。
如果希望自己的控件更加健壮并且符合安卓控件的规范,比如在xml文件中也可以设置自定义属性、添加点击事件等。
首先,是在res/values/下创建一个attrs.xml文件:
<resources>
<declare-styleable name="CustomView">
<attr name="clickable" format="boolean"/>
<attr name="orientation" format="enum">
<enum name="horizontal" value="0"/>
<enum name="vertical" value="1"/>
</attr>
</declare-styleable>
</resources>
name="CustomView"可以是任意名称,不过一般和控件名称保持一致。
在这我定义了一个是否可点击属性和一个让控件横向或竖向显示的属性。
接着是自定义控件的类,补充以上CustomView:
/**
* @author Ives
*
*/
public class CustomView extends View {
private boolean isClickable;
private int orientation;
private final int HORIZONTAL = 0;
private final int VERTICAL = 1;
private OnMyClickListener mListener;
private Paint paint = new Paint();
private RectF rf = new RectF();
/**
* @param context
*/
public CustomView(Context context) {
super(context);
setDefault();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
setDefault();
//获取自定义的参数值
TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, 0, 0);
try{
isClickable = typeArray.getBoolean(R.styleable.CustomView_clickable, true);
orientation = typeArray.getInt(R.styleable.CustomView_orientation, HORIZONTAL);
}finally{
typeArray.recycle();
}
}
private void setDefault(){
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
isClickable = true;
orientation = HORIZONTAL;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.BLUE);
switch(orientation){
case HORIZONTAL: //横向椭圆
rf.set(0f, 0f, 300f, 200f);
break;
case VERTICAL: //纵向椭圆
rf.set(0f, 0f, 200f, 300f);
break;
}
canvas.drawArc(rf, 0f, 360f, true, paint);
}
public void setClickable(boolean clickable){
this.isClickable = clickable;
}
//如果仅仅是为了增加自定义点击判断,也可以直接重写setOnClickListener实现
public interface OnMyClickListener{
void OnMyClick();
}
public void setOnMyClickListener(OnMyClickListener listener){
mListener = listener;
}
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP){
if(isClickable&&mListener!=null){
mListener.OnMyClick();
}
}
return true;
}
// @Override
// public void setOnClickListener(OnClickListener listener){
// if(isClickable){
// super.setOnClickListener(listener);
// }
// }
}
最后是调用。在xml文件里面增加 xmlns:custom="http://schemas.android.com/apk/res/cc.ives.customview"这一行即可使用自定义的属性。"cc.ives.customview"是app的包名:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/cc.ives.customview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<cc.ives.view.CustomView
android:layout_width="400dp"
android:layout_height="300dp"
custom:orientation="horizontal"
custom:clickable="true"/>
</LinearLayout>
在java代码里面的使用方式和自有控件一样,这里就不写了。
(转载请标明本来源)