自定义View

来源:互联网 发布:淘宝美工练手 编辑:程序博客网 时间:2024/04/30 02:45

Android自定义View实现很简单

继承View,重写构造函数、onDraw,(onMeasure)等函数。

如果自定义的View需要有自定义的属性,需要在values下建立attrs.xml。在其中定义你的属性。

在使用到自定义View的xml布局文件中需要加入xmlns:前缀=”http://schemas.android.com/apk/res/你的自定义View所在的包路径”.
这里写图片描述

1、制作简易手表

先写一个类继承View,重写onMeasure(),onDraw()

public class MyView extends View {    private int width;    private int height;    private  Paint mPaintDuan;    private Paint mPaintLine;    private  Paint mPaintSecond;    private Paint mPaintCircle;    private Paint mPaintText;    private Calendar mCalendar;    public static  final  int NEED_INVALIDATE=0X23;    private Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            switch (msg.what){                case NEED_INVALIDATE:                    mCalendar = Calendar.getInstance();//每次要刷新时间                    invalidate();//告诉主线程重新绘制                    handler.sendEmptyMessageDelayed(NEED_INVALIDATE, 1000);                    break;            }        }    };    public MyView(Context context) {        super(context);    }    public MyView(Context context, AttributeSet attrs) {        super(context, attrs);        mCalendar =Calendar.getInstance();        mPaintDuan = new Paint();//设置直线的参数        mPaintDuan.setColor(Color.RED);        mPaintDuan.setStrokeWidth(8);        mPaintLine = new Paint();//设置直线的参数        mPaintLine.setColor(Color.GREEN);        mPaintLine.setStrokeWidth(10);        mPaintSecond= new Paint();//设置秒针线的参数        mPaintSecond.setColor(Color.GREEN);        mPaintSecond.setStrokeWidth(5);        mPaintCircle = new Paint();//设置圆的参数        mPaintCircle.setColor(Color.LTGRAY);        mPaintCircle.setStrokeWidth(10);        mPaintCircle.setStyle(Paint.Style.STROKE);        mPaintText = new Paint();        mPaintText.setColor(Color.BLACK);        mPaintText.setTextSize(30);        mPaintText.setTextAlign(Paint.Align.CENTER);        handler.sendEmptyMessage(NEED_INVALIDATE);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);        setMeasuredDimension(width, height);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //是由UI主线程自动调用,只需要在此绘制即可        //       canvas.drawLine(0,0,300,300,mPaintLine);//画直线        //    canvas.drawCircle(350,350,100,mPaintCircle);//画圆        canvas.drawCircle(width / 2, height / 2, 300, mPaintCircle);        canvas.drawCircle(width / 2, height / 2, 10, mPaintCircle);        for (int i = 1; i <= 12; i++) {//用FOR循环画12条短线            canvas.save();//保存画布当前的状态            canvas.rotate(360 / 12 * i, width / 2, height / 2);//旋转画布,每次转30度            canvas.drawLine(width / 2, height / 2 - 300, width / 2, height / 2 - 280, mPaintDuan);            canvas.drawText("" + i, width / 2, height / 2 - 250, mPaintText);            canvas.restore();        }        //获得分钟数,小时数        int minute = mCalendar.get(Calendar.MINUTE);        int hour = mCalendar.get(Calendar.HOUR);        float minuteDegree = minute / 60f * 360;//获得分针的旋转度        canvas.save();        canvas.rotate(minuteDegree, width / 2, height / 2);        canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 200, mPaintLine);        canvas.restore();        float hourDegree = (hour*60+minute)/12f/60*360;//计算时针所占表盘的度数        canvas.save();        canvas.rotate(hourDegree, width / 2, height / 2);        canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 150, mPaintLine);        canvas.restore();        int second = mCalendar.get(Calendar.SECOND);        float secondDegree = second/60f*360;//计算秒针此刻的位置        canvas.save();        canvas.rotate(secondDegree, width / 2, height / 2);        canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 230, mPaintSecond);        canvas.restore();    }}

然后再布局文件下添加这个view

<LinearLayout 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"    android:orientation="vertical"    tools:context=".MainActivity">    <com.my.administrator.zdyview.MyView//这里的MyView要和上面写的类名一致        android:id="@+id/tiaoxingview"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

在Activity中只需要 setContentView(R.layout.activity_main);即可。
简易手表如下:
这里写图片描述

2、往容器中倒满水案例

public class TiaoxingView extends View {    private int width;    private int height;    private Paint lineLeft;    private Paint lineRight;    private Paint lineButtom;    private Paint lineNewRight;    private  Paint mPaintText;    private int progress=100;    private int progressCurrent;    public int getProgress() {        return progress;    }    public void setProgress(int progress) {        this.progress = progress;    }    public int getProgressCurrent() {        return progressCurrent;    }    public void setProgressCurrent(int progressCurrent) {        this.progressCurrent = progressCurrent;        invalidate();//告诉主线程重新绘制    }    public TiaoxingView(Context context) {        super(context);    }    public TiaoxingView(Context context, AttributeSet attrs) {        super(context, attrs);        lineLeft=new Paint();        lineLeft.setColor(Color.BLACK);        lineLeft.setStrokeWidth(5);        lineRight=new Paint();        lineRight.setColor(Color.BLACK);        lineRight.setStrokeWidth(5);        lineButtom=new Paint();        lineButtom.setColor(Color.BLACK);        lineButtom.setStrokeWidth(5);        lineNewRight=new Paint();        lineNewRight.setColor(Color.GREEN);        lineNewRight.setStrokeWidth(300);        mPaintText = new Paint();        mPaintText.setColor(Color.BLUE);        mPaintText.setTextSize(60);        mPaintText.setTextAlign(Paint.Align.CENTER);//设置文本在给定坐标中间    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);        setMeasuredDimension(width, height);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //绘制如下图的容器        canvas.drawLine(50, 100, 50, 500, lineLeft);        canvas.drawLine(50,500,350,500,lineButtom);        canvas.drawLine(350,500,350,100,lineRight);        canvas.drawLine(200,500,200,500-progressCurrent*400f/progress,lineNewRight);//progressCurrent*400f/progress是此时应该画的长度,progressCurrent从activity中获得        canvas.drawText(progressCurrent*100f/progress+"%",200,300,mPaintText);//给定文本坐标,写入文本    }}

这里写图片描述

布局问价:

<LinearLayout 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"    android:orientation="vertical"    tools:context=".MainActivity">    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="开始" />    <com.my.administrator.zdyview.TiaoxingView        android:id="@+id/tiaoxingview"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

Activity

public class MainActivity extends AppCompatActivity {    private TiaoxingView view;    private Button mButton;    private int progress;    private Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case 0x21:                    progress++;                    if (progress <= 100) {                        view.setProgressCurrent(progress);//设置当前的进度                        handler.sendEmptyMessageDelayed(0x21, 200);                    }                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        view = (TiaoxingView) findViewById(R.id.tiaoxingview);        mButton = (Button) findViewById(R.id.button);        mButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                handler.sendEmptyMessage(0x21);            }        });    }}

运行如下:
这里写图片描述

弧形进度条案例

其他代码和上面相同,view类如下:

public class ArcView extends View {    private int width;    private int height;    private int progress=100;    private int progressCurrent;    private  Paint mCircle;    private Paint mArc;    private RectF mRectf;    private Paint mText;    public int getProgress() {        return progress;    }    public void setProgress(int progress) {        this.progress = progress;    }    public int getProgressCurrent() {        return progressCurrent;    }    public void setProgressCurrent(int progressCurrent) {        this.progressCurrent = progressCurrent;        invalidate();    }    public ArcView(Context context) {        super(context);    }    public ArcView(Context context, AttributeSet attrs) {        super(context, attrs);        mArc = new Paint();        mArc.setColor(Color.GREEN);        mArc.setStrokeWidth(50);        mArc.setStyle(Paint.Style.STROKE);        mCircle = new Paint();        mCircle.setColor(Color.GRAY);        mCircle.setStyle(Paint.Style.STROKE);        mCircle.setStrokeWidth(10);        mText = new Paint();        mText.setColor(Color.BLUE);        mText.setTextSize(60);        mText.setTextAlign(Paint.Align.CENTER);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);        setMeasuredDimension(width, height);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawCircle(width / 2, height / 2, 300, mCircle);        canvas.drawCircle(width / 2, height / 2, 250, mCircle);        mRectf = new RectF(width/2-275,height/2-275,width/2+275,height/2+275);//设置画弧度的矩形框        canvas.drawArc(mRectf,0,progressCurrent*360f/progress,false,mArc);        canvas.drawText(progressCurrent * 100f / progress + "%", width / 2, height / 2, mText);    }}

运行如下;
这里写图片描述

0 0
原创粉丝点击