第一种方式:继承View,View是android中界中最基础的元素,也就是说是基类,所有控件或者布局都是view的子类。
第二种方式:继承View的子类,比如说TextView,ImageView,Button之类的。。
第三种方式:继承ViewGroup,这种实现方式也比较复杂,与继承View相信,如果使用用这种方式,我们必须在onMeasure()和onLayout中处理margin,padding之类的工作。
第四种方式:继承ViewGroup的子类(Linearlayout,Relativelayout),ViewGroup是View的子类,而ViewGroup又是所有layout的基类。
首先画出员盘的位置,在画出盘上的数字,然后画出时针分针秒针,设计时针分针秒针的时间用变量表示,主线程获得当前时间,传递给自定义view的一个方法,方法里把主线程获得当前时间赋值给时针分针秒针的时间用变量,再用invalidate()刷新;再开启子线程,让主线程每过一秒得到系统的秒的变量加一,然后给handler传递一个消息,handler继续调用view的一个方法传递时间变量。
代码如下:
package com.example.lianxi;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import java.util.Calendar;
public class MyView extends View {
private ObjectAnimator objectAnimator;
private int hour=0;
private int minute=0;
private int seconds=0;
public MyView(Context context) {
super(context);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint=new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
canvas.save();
RectF rectF=new RectF(getWidth()/4,getHeight()/2-getWidth()/4,getWidth()/4*3,getHeight()/2+getWidth()/4);
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.biaopan);
canvas.drawBitmap(bitmap,null,rectF,paint);
canvas.restore();
for (int i=1;i<13;i++){
canvas.save();
canvas.rotate(30*i,getWidth()/2,getHeight()/2);
canvas.drawText(i+"",getWidth()/2-17,getHeight()/2-getWidth()/4+30,paint);
canvas.restore();
}
canvas.save();
canvas.drawLine(getWidth()/2,getHeight()/2, getWidth()/2,getHeight()/2-getWidth()/4+40,paint);
paint.setStrokeWidth(4);
canvas.rotate(6*seconds,getWidth()/2,getHeight()/2);
canvas.restore();
canvas.save();
paint.setColor(Color.RED);
canvas.drawLine(getWidth()/2,getHeight()/2, getWidth()/2,getHeight()/2-getWidth()/4+60,paint);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(6);
canvas.rotate(minute*6,getWidth()/2,getHeight()/2);
canvas.restore();
canvas.save();
canvas.drawLine(getWidth()/2,getHeight()/2, getWidth()/2,getHeight()/2-getWidth()/4+80,paint);
canvas.rotate(hour*30+minute*30/60,getWidth()/2,getHeight()/2);paint.setStrokeWidth(8);
canvas.restore();
for(int x=1;x<=60;x++){
canvas.save();
if(x%5==0){
paint.setStrokeWidth(8);
canvas.drawLine(getWidth()/2,getHeight()/2-getWidth()/4, getWidth()/2,getHeight()/2-getWidth()/4+25,paint);
}else {
paint.setStrokeWidth(4);
canvas.drawLine(getWidth()/2,getHeight()/2-getWidth()/4, getWidth()/2,getHeight()/2-getWidth()/4+20,paint);
}
canvas.restore();
}
}
void refresh(int h, int m, int s){
this.hour=h;
this.minute=h;
this.seconds=h;
invalidate();
}
package com.example.lianxi;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.util.Calendar;
public class MyViewActivity extends AppCompatActivity {
private int hour;
private int minute;
private int second;
private MyView myView;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
myView.refresh(msg.arg2,msg.arg1,msg.what);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_view);
Calendar calendar = Calendar.getInstance();
hour = calendar.get(Calendar.HOUR_OF_DAY); //时
minute = calendar.get(Calendar.MINUTE); //分
second = calendar.get(Calendar.SECOND); //秒
myView=findViewById(R.id.my_view);
myView.refresh(hour,minute,second);
new Thread(
new Runnable() {
@Override
public void run() {
while(true){
second++;
if (second==60){
second=0;
minute++;
}
if (minute==60){
hour++;
minute=0;
}
if (hour==12){
hour=0;
}
Message message=handler.obtainMessage();
message.what=second;
message.arg1=minute;
message.arg2=hour;
handler.sendMessage(message);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}}
).start();
}
}
我这里是用传递一个bitmap和半径代码如下
private Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
//比较初始Bitmap宽高和给定的圆形直径,判断是否需要缩放裁剪Bitmap对象
if (bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f,
sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);
//核心部分,设置两张图片的相交模式,在这里就是上面绘制的Circle和下面绘制的Bitmap
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}