为什么要自定义view
在实际项目中安卓的view无法满足特定的需求,所以需要扩展或者修改原生view,满足特定需求。
安卓系统自带view结构
1.view类是layout和view容器的基类,这个类包含了所有的屏幕类型。
2.layout和view容器是安卓SDK封装好的基础组件,例如button,listview等控件和LinearLayout等布局容器
自定义view的定义
通过直接继承view或重写view子类,实现逻辑的view,称之为自定义为view。
如何使用自定义view
1.直接继承view类式的方式自绘控件
2.简洁继承view类式的方式重写控件
3.间接继承view子类,将需要用到的原生控件组合到一起
自绘控件的步骤
1.继承view
2.实现listener接口
3.重写构造方法
4.重写onDraw方法
5.paint 画笔
6.Canvas 绘制
7.invalidate方法刷新
8.在布局文件中引用
实现计数器
先新建一个myview的类继承View,然后实现画圆和写字的功能,最后在onTouchEvent里面使用invalidate方法,然后在调用onDraw方法。
public class MyView extends View {
private Paint paint = new Paint();
private int num = 0;
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//实现画圆功能
paint.setColor(Color.RED);
paint.setAntiAlias(true);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 4, paint);
//实现写字功能
paint.setColor(Color.GREEN);
paint.setTextSize(50);
canvas.drawText(num + "", getWidth() / 2 - 15, getHeight() / 2 + 25, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
num++;
invalidate();//点击一次,调用onDraw方法
return super.onTouchEvent(event);
}
}
最后引用布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="myapplication.com.example.viewdemo.MainActivity">
<myapplication.com.example.viewdemo.MyView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
实现模拟时钟
新建一个clickview继承view,然后定义一个paint画笔,先用画笔写一个数字,然后去除锯齿,用画布画东西时,需要先保存画布,最后在restore。接着定义一个second,在onTouchEvent里面写一个子线程,实现run的方法。然后通过子线程传递信息给主线程,在主线程里面实现 invalidate方法(子线程不能更新UI)。
获取本地时间和秒针时针,其实和获取分针是类似的方法。但是最后handler就不需要了。
public class ClickView extends View {
private Paint paint = new Paint();
/*
public Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
invalidate();
}
};*/
public ClickView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
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);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(2);
paint.setTextSize(20);
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 - getWidth() / 3 + 40, paint);
canvas.restore();
}
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
canvas.save();
canvas.rotate(6 * second, getWidth() / 2, getHeight() / 2);
canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2, getHeight() / 2 - getWidth() / 3 + 50, paint);
canvas.restore();
canvas.save();
canvas.rotate(minute * 6, getWidth() / 2, getHeight() / 2);
paint.setColor(Color.RED);
canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2, getHeight() / 2 - getWidth() / 3 + 60, paint);
canvas.restore();
canvas.save();
canvas.rotate(hour * 30 + minute * 30 / 60, getWidth() / 2, getHeight() / 2);
paint.setColor(Color.BLUE);
canvas.drawLine(getWidth() / 2, getHeight() / 2, getWidth() / 2, getHeight() / 2 - getWidth() / 3 + 80, paint);
canvas.restore();
invalidate();
}
/*// @Override
// public boolean onTouchEvent(MotionEvent event) {
// new Thread(new Runnable() {
// @Override
// public void run() {
// while (secDegree<40){
secDegree++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(secDegree);
}
}
}).start();
return super.onTouchEvent(event);
}
*/
}
最后引用布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="myapplication.com.example.viewdemo.ClickActivity">
<myapplication.com.example.viewdemo.ClickView
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>