人生最大的悲哀不是失去太多,而是计较太多,这也是导致一个人不快乐的重要原因。
本讲内容:自定义View是如何实现的!
一、继承View自定义一个View的子类CustomView:
public class CustomView extends View {
private Paint mPaint;
public CustomView(Context context) {
this(context, null);
}
//系统默认的布局文件调用的是两个参数的构造方法</span>
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
private void initPaint() {
// 实例化画笔并打开抗锯齿
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
二、onDraw方法
自定义View里面什么都没有,需要我们往View里画点东西,Android给我们提供了一个onDraw(Canvas
canvas)方法来让我们绘制自己想要的东西:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
我们画画需要两样东西:笔和纸。同样地,Android也给我们提供了这两样东西:Paint(画笔)和Canvas(画布)
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//错误的写法,new对象一般不能在频繁重复的过程中new,浪费内存
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); // 实例化画笔并打开抗锯齿
paint.setAntiAlias(true); //设置了抗锯齿(一种让图像边缘显得更圆滑光泽动感的碉堡算法)
}
Paint.FILTER_BITMAP_FLAG是使位图过滤的位掩码标志Paint.ANTI_ALIAS_FLAG是使位图抗锯齿的标志
Paint.DITHER_FLAG是使位图进行有利的抖动的位掩码标志
1、Paint(画笔)通过set方法各种属性:比如setColor()设置画笔颜色,setStrokeWidth()设置描边线条,setStyle()设置画笔的样式等等
2、Canvas(画布)通过drawXXX方法绘制各种不同的东西,比如绘制一个圆drawCircle(),绘制一个圆弧drawArc(),绘制一张位图drawBitmap()等等
示例一:画个圆环
下面是res/layout/activity_main.xml
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:orientation="vertical" >
<com.view.CustomView
android:id="@+id/myView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
下面是MeasureUtil.java文件:
/**
* 测绘工具类
*/
public final class MeasureUtil {
/**
* 获取屏幕尺寸
*
* @param activity
* @return 屏幕尺寸像素值,下标为0的值为宽,下标为1的值为高
*/
public static int[] getScreenSize(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return new int[] { metrics.widthPixels, metrics.heightPixels };
}
}
下面是自定义CustomTitleView.java文件:
public class CustomView extends View {
private Paint mPaint;// 画笔
// 上下文环境引用 就是一个装满信息的信使,Android需要它从里面获取需要的信息。
private Context mContext;
public CustomView(Context context) {
super(context,null);
}
//默认的布局文件调用的是两个参数的构造方法
public CustomView(Context context, AttributeSet attrs) {
super(context,attrs);
this.mContext=context;
initPaint();// 初始化画笔
}
//初始化画笔
private void initPaint() {
// 实例化画笔并打开抗锯齿
mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
/*
* 设置画笔样式为描边,圆环嘛……当然不能填充不然就么意思了
*
* 画笔样式分三种:
* 1.Paint.Style.STROKE:描边
* 2.Paint.Style.FILL_AND_STROKE:描边并填充
* 3.Paint.Style.FILL:填充
*/
mPaint.setStyle(Paint.Style.STROKE);
// 设置画笔颜色为浅灰色
mPaint.setColor(Color.LTGRAY);
//设置描边的粗细,单位:像素px 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
mPaint.setStrokeWidth(10);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制圆环
canvas.drawCircle(MeasureUtil.getScreenSize((Activity) mContext)[0]/2, MeasureUtil.getScreenSize((Activity) mContext)[1]/2, 200, mPaint);
}
}
注意:drawCircle表示绘制的是圆形,但是在我们的画笔样式设置为描边后其绘制出来的就是一个圆环!其中drawCircle的前两个参数表示圆心的XY坐标,这里我们用到了一个工具类获取屏幕尺寸以便将其圆心设置在屏幕中心位置,第三个参数是圆的半径,第四个参数则为我们的画笔!
这里有一点要注意:在Android中设置数字类型的参数时如果没有特别的说明,参数的单位一般都为px像素。
下面是MainActivity.java主界面文件:
<span style="font-size:18px;">public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
}</span>
示例二:画个圆环半径从小到大地不断变化
我们都知道动画的原理是:一个动画是由无数张连贯的图片构成的,这些图片之间快速地切换
下面是自定义CustomTitleView.java文件:
public class CustomView extends View implements Runnable{
private Paint mPaint;// 画笔
// 上下文环境引用 就是一个装满信息的信使,Android需要它从里面获取需要的信息。
private Context mContext;
private int radiu;// 圆环半径
public CustomView(Context context) {
super(context,null);
}
//默认的布局文件调用的是两个参数的构造方法
public CustomView(Context context, AttributeSet attrs) {
super(context,attrs);
this.mContext=context;
initPaint();// 初始化画笔
}
//初始化画笔
private void initPaint() {
// 实例化画笔并打开抗锯齿
mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
//设置画笔样式为描边
mPaint.setStyle(Paint.Style.STROKE);
// 设置画笔颜色为浅灰色
mPaint.setColor(Color.LTGRAY);
//设置描边的粗细
mPaint.setStrokeWidth(10);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制圆环
canvas.drawCircle(MeasureUtil.getScreenSize((Activity) mContext)[0]/2, MeasureUtil.getScreenSize((Activity) mContext)[1]/2, radiu, mPaint);
}
public void run() {
//确保线程不断执行刷新界面
while(true){
try {
//如果半径小于200则自加否则大于200后重置半径值以实现往复
if(radiu<=200){
radiu+=10;
//因为我们在非UI线程中更新了UI!而在Android中非UI线程是不能直接更新UI的,可用Handler,或postInvalidate()方法重绘
//invalidate();//重绘 刷新View
postInvalidate();
}else{
radiu=0;
}
// 每执行一次暂停40毫秒
Thread.sleep(40);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
下面是MainActivity.java主界面文件:
public class MainActivity extends Activity {
// 我们的自定义View
private CustomView mCustomView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mCustomView = (CustomView) findViewById(R.id.myView);// 获取控件
//开线程
new Thread(mCustomView).start();
}
}
Take your time and enjoy it 路过的、学习过的请留个言,顶个呗~~