Android开发-自定义view-入门级自定义view全注解

本文的实例是别人写的,我又重写了一遍,在代码中加上了详细的注解。

1.首先新建工程,在工程的res/values目录下新建attrs.xml文件,用于添加自定义控件的属性。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomProgressBar">
        <attr name="firstColor" format="color" />
        <attr name="secondColor" format="color" />
        <attr name="circleWidth" format="dimension" />
        <attr name="speed" format="integer" />
    </declare-styleable>
</resources>

2.接下来新建一个类继承view,开始编写控件类

public class Mycustomview extends View {
private int FirstColor;//第一圈颜色
private int SecondColor;//第二圈颜色
private int circlewidth;//圆弧宽
private int speed;//速度
private Paint mpaint;//画笔
private int mprogress;//进度
private boolean next;//是否开始下一轮
private int center;//圆心的位置(x/y)
private int radius;//半径
public Mycustomview(Context context) {

//注意这里是 this  不是super   
this(context,null);

}
public Mycustomview(Context context, AttributeSet attrs) {

//目的为了让下面构造中的代码一定执行
this(context, attrs,0);
}
public Mycustomview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

//获取对自定义属性设置的类 typearray
TypedArray a=context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomProgressBar, defStyle,0);

//对自定义的属性值进行获取
FirstColor=a.getColor(R.styleable.CustomProgressBar_firstColor, Color.BLACK);
SecondColor=a.getColor(R.styleable.CustomProgressBar_secondColor, Color.RED);

//第二个参数的方法的作用是转换成标准尺寸。 如本文中此的意思是20“dp”
circlewidth=a.getDimensionPixelSize(R.styleable.CustomProgressBar_circleWidth,(int) TypedValue.applyDimension(  
                TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()));
speed=a.getInt(R.styleable.CustomProgressBar_speed, 10);

//获取typearray结束后一定要调用recycle方法,防止对下次调用的影响。
a.recycle();

//初始化画笔
mpaint=new Paint();

//启动一条线程,使进度条自增,再睡眠speed毫秒,speed值越小,进度条速度越快。

//next用于切换进度条状态(true的时候旋转的是第一个颜色进度条,false时旋转的是第二个颜色进度条)
new Thread(){
@Override
public void run() {
while(true){
mprogress++;
if(mprogress==360){
mprogress=0;
if(next){
next=false;
}else{
next=true;
}
}

//重新构造视图

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。 一个Android 程序默认情况下也只有一个进程,但一个进程下却可以有许多个线程。

在这么多线程当中,把主要是负责控制UI界面的显示、更新和控件交互的线程称为UI线程,由于onCreate()方法是由UI线程执行的,所以也可以把UI线程理解为主线程。其余的线程可以理解为工作者线程。

invalidate()得在UI线程中被调动,在工作者线程中可以通过Handler来通知UI线程进行界面更新。

而postInvalidate()在工作者线程中被调用

/*

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。

invalidate()得在UI线程中被调动,在工作者线程中可以通过Handler来通知UI线程进行界面更新。
而postInvalidate()在工作者线程中被调用

*/
postInvalidate();
try {

sleep(speed);

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}.start();
}

//重写绘制视图的方法
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
center=getWidth()/2;//x坐标
radius=center-circlewidth/2;//半径
mpaint.setStrokeWidth(circlewidth);//设置线条宽度
mpaint.setAntiAlias(true);//设置抗锯齿
mpaint.setStyle(Paint.Style.STROKE);

//设置绘制范围
RectF rectf=new RectF(center-radius,center-radius, center+radius, center+radius);
if(!next){//初始状态为false  第一层直接绘制,第二层按照扇形绘制,角度为动态变化的mprogress
mpaint.setColor(FirstColor);
//x坐标 y坐标  半径   画笔
canvas.drawCircle(center, center, radius, mpaint);
mpaint.setColor(SecondColor);
//扇形区域   初始角度   扇形角度    是否填充  画笔
canvas.drawArc(rectf, -90, mprogress, false, mpaint);
}else{//第二层绘制完成后,执行此方法,底部绘制第二层,第一层按照扇形绘制。
mpaint.setColor(SecondColor);
canvas.drawCircle(center, center, radius, mpaint);
mpaint.setColor(FirstColor);
canvas.drawArc(rectf, -90, mprogress, false, mpaint);
}
}
}

3.在布局中调用该控件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"

<!--这一句必须加,意为指向自定义控件属性 “app”可自由定义名称(com.example.mycustomview01为项目包名)  该句也可写为    xmlns:app="http://schemas.android.com/apk/res-auto"-->
    xmlns:app="http://schemas.android.com/apk/res/com.example.mycustomview01"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.example.mycustomview01.Mycustomview 
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:firstColor="#0000aa"
        app:secondColor="#00aa00"
        app:circleWidth="40dp"
        android:background="#33333333"
        app:speed="50"/>
</RelativeLayout>


下附源码

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值