一、View的大家族
大枝分类
详细分类
二、使用自定义View的方法
- 通过直接继承View 例如 ABC extends View
- 重写View子类实现逻辑的View 例如 ABC extends TextView 然后实现方法
注意点:方法二相比较与方法一更简单
三、使用自定义View的步骤
- 自绘控件:直接继承View类的方式自绘控件
- 重写控件:间接继承View子类的方式重写控件
- 组合控件:间接继承View子类,将需要用到的原生控件组合到一起
四、自绘控件的步骤
- 继承View
- 实现Listener接口
- 实现构造方法
- 重写onDraw方法
注意点:在自绘控件中,绘制的逻辑基本都写在此方法中
需调好Paint画笔,将Paint画在Canvas上,输出到屏幕上
5 Paint画笔
方法名 | 解释 |
---|---|
setAntiAlias | 设置画笔的锯齿效果 |
setColor | 设置画笔颜色 |
setARGB() | 设置画笔A,R,G,B的值 |
setAlpha | 设置画笔的Alpha值 |
setStyle | 设置画笔的风格(空心或实心) |
setStrokeWidth | 设置空心边框的宽度 |
getColor | 获取画笔的颜色 |
6. Canvas绘制
方法名 | 解释 |
---|---|
drawLine() | 绘制直线 |
drawCircle() | 绘制圆形 |
drawBitmap() | 绘制图形 |
drawRect() | 绘制矩形 |
drawText() | 绘制字符 |
7. invalidate方法刷新
8. 在布局文件中引用
五、使用自绘控件的示例(以时钟为例)
要达到的效果是和我们日常看到的时钟一样
效果图
1.首先新建一个类继承View,实现他自带的方法,定义出画笔
public class MyView2 extends View {
private Paint paint=new Paint();
public MyView2(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
2.实现onDraw方法,在里面用画笔对象开始绘制时钟
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);//空心圆
paint.setAntiAlias(true);//减弱锯齿效果
paint.setStrokeWidth(10);
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/3,paint);
canvas.drawCircle(getWidth()/2,getHeight()/2,5,paint);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(2);
paint.setTextSize(20);
3.我们知道时钟的一圈是1-12的数字,所以我们要用for循环来写这12个数字,注意要写在onDraw方法里
for(int i=1;i<=12;i++){
canvas.save();//保存画布当前的状态
canvas.rotate(30*i,getWidth()/2,getHeight()/2);
canvas.drawLine(getWidth()/2,getHeight()/2-getWidth()/3,getWidth()/2,getHeight()/2-getWidth()/3+20,paint);
canvas.drawText(i+"",getWidth()/2-10,getHeight()/2-getHeight()/3+190,paint);
canvas.restore();//画布复原
}
4.涉及到旋转就势必要牵扯到角度问题,所以我们自定义一个角度,并设置其初始化
public int sec=0;//设置初始化角度
5.用Calendar来获取模拟器也就是现在的时间
//获取当前时间
Calendar calendar=Calendar.getInstance();
int hour=calendar.get(Calendar.HOUR);
int minute=calendar.get(Calendar.MINUTE);
int second=calendar.get(Calendar.SECOND);
6.接下来就是绘制时针,分针,秒针了
//绘制秒钟
canvas.save();
canvas.rotate(second*6,getWidth()/2,getHeight()/2);
paint.setColor(Color.RED);
canvas.drawLine(getWidth()/2,getHeight()/2,getWidth()/2,getHeight()/2-getHeight()/3+200,paint);
canvas.restore();
//绘制分钟
canvas.save();
canvas.rotate(minute*6,getWidth()/2,getHeight()/2);
paint.setColor(Color.BLACK);
canvas.drawLine(getWidth()/2,getHeight()/2,getWidth()/2,getHeight()/2-getHeight()/3+250,paint);
canvas.restore();
//绘制时钟
canvas.save();
canvas.rotate(hour*30+minute*30/60,getWidth()/2,getHeight()/2);
paint.setColor(Color.GREEN);
canvas.drawLine(getWidth()/2,getHeight()/2,getWidth()/2,getHeight()/2-getHeight()/3+300,paint);
canvas.restore();
invalidate();
}
7.由于要运行一次就刷新页面来制造出在旋转的效果,所以要用到onTouchEvent方法。并且在里面开一个子线程
public boolean onTouchEvent(MotionEvent event) {
new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(sec);
sec++;
}
}
}).start();
return super.onTouchEvent(event);
}
8.在上面写Handler来接受子线程传来的消息(因为子线程不能更新UI)
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
invalidate();
}
};
9.最后回到layout布局文件里把你定义的这个类写进去,主要要导你自己的包。不然会报错
<com.example.view.MyView2
android:layout_width="match_parent"
android:layout_height="match_parent" />
笔芯!