view
如果说要按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件、组合控件、以及继承控件。那么下面我们就来依次学习一下,每种方式分别是如何自定义View的
一、自绘控件
自绘控件的意思就是,这个View上所展现的内容全部都是我们自己绘制出来的。绘制的代码是写在onDraw()方法中的,而这部分内容我们已经在【自定义View】Android视图绘制流程完全解析中学习过了
下面我们准备来自定义一个计数器View,这个View可以响应用户的点击事件,并自动记录一共点击了多少次。新建一个CounterView继承自View
public class CountView extends View implements View.OnClickListener{
private Paint mPaint;
private Rect mBounds;
private int mCount;
public CountView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mBounds = new Rect();
setOnClickListener(this);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.BLUE);
canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(40);
String number = String.valueOf(mCount);
mPaint.getTextBounds(number,0,number.length(),mBounds);
float textWidth = mBounds.width();
float textHeight = mBounds.height();
canvas.drawText(number, getWidth() / 2 - textWidth / 2, getHeight() / 2
+ textHeight / 2, mPaint);
}
@Override
public void onClick(View view) {
mCount++;
invalidate();
}
}
可以看到,首先我们在CounterView的构造函数中初始化了一些数据,并给这个View的本身注册了点击事件,这样当CounterView被点击的时候,onClick()方法就会得到调用。而onClick()方法中的逻辑就更加简单了,只是对mCount这个计数器加1,然后调用invalidate()方法。调用invalidate()方法会导致视图进行重绘,因此onDraw()方法在稍后就将会得到调用
既然CounterView是一个自绘视图,那么最主要的逻辑当然就是写在onDraw()方法里的了,下面我们就来仔细看一下。这里首先是将Paint画笔设置为蓝色,然后调用Canvas的drawRect()方法绘制了一个矩形,这个矩形也就可以当作是CounterView的背景图吧。接着将画笔设置为黄色,准备在背景上面绘制当前的计数,注意这里先是调用了getTextBounds()方法来获取到文字的宽度和高度,然后调用了drawText()方法去进行绘制就可以了
这样,一个自定义的View就已经完成了,并且目前这个CounterView是具备自动计数功能的。那么剩下的问题就是如何让这个View在界面上显示出来了,其实这也非常简单,我们只需要像使用普通的控件一样来使用CounterView就可以了。比如在布局文件中加入如下代码
<com.example.customview.CounterView
android:layout_width="100dp"
android:layout_height="100dp"
/>
运行程序,并不停地点击CounterView
二、组合控件
组合控件的意思就是,我们并不需要自己去绘制视图上显示的内容,而只是用系统原生的控件就好了,但我们可以将几个系统原生的控件组合到一起,这样创建出的控件就被称为组合控件
举个例子来说,标题栏就是个很常见的组合控件,很多界面的头部都会放置一个标题栏,标题栏上会有个返回按钮和标题,点击按钮后就可以返回到上一个界面。那么下面我们就来尝试去实现这样一个标题栏控件
新建一个title.xml布局文件,代码如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ffcb05" >
<Button
android:id="@+id/button_left"
android:layout_width="60dp"
android:layout_height="40dp"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:background="@drawable/btn_back"
android:text="Back"
android:textColor="#fff" />
<TextView
android:id="@+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is Title"
android:textColor="#fff"
android:textSize="20sp" />
</RelativeLayout>
接下来创建一个TitleView继承自FrameLayout
public class TitleView extends FrameLayout{
private Button mLeftButton;
private TextView mTitle;
public TitleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title,this);
mTitle = (TextView) findViewById(R.id.title_text);
mLeftButton = (Button) findViewById(R.id.button_left);
mLeftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((Activity) getContext()).finish();
}
});
}
public void setTitleText(String text) {
mTitle.setText(text);
}
public void setLeftButtonText(String text) {
mLeftButton.setText(text);
}
public void setLeftButtonListener(OnClickListener l) {
mLeftButton.setOnClickListener(l);
}
}
为了让TitleView有更强地扩展性,我们还提供了setTitleText()、setLeftButtonText()、setLeftButtonListener()等方法,分别用于设置标题栏上的文字、返回按钮上的文字、以及返回按钮的点击事件
运行程序
三、继承控件
继承控件的意思就是,我们并不需要自己重头去实现一个控件,只需要去继承一个现有的控件,然后在这个控件上增加一些新的功能,就可以形成一个自定义的控件了。这种自定义控件的特点就是不仅能够按照我们的需求加入相应的功能,还可以保留原生控件的所有功能,比如 Android PowerImageView实现,可以播放动画的强大ImageView 这篇文章中介绍的PowerImageView就是一个典型的继承控件
为了能够加深大家对这种自定义View方式的理解,下面我们再来编写一个新的继承控件。ListView相信每一个Android程序员都一定使用过,这次我们准备对ListView进行扩展,加入在ListView上滑动就可以显示出一个删除按钮,点击按钮就会删除相应数据的功能
首先需要准备一个删除按钮的布局,新建delete_button.xml文件,代码如下所示:
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/btn_clear" >
</Button>
总结自郭大神的博客
https://blog.csdn.net/guolin_blog/article/details/17357967
下一篇: 数据爬取之基本概念