标签:
1.自定义控件时钟的布局和Java类
values文件下的attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyClock"> <attr name="circleColor01" format="color"/> <attr name="circleColor02" format="color"/> <attr name="circleWidth" format="dimension"/> </declare-styleable> <declare-styleable name="Textview"> <attr name="lineColor" format="color"></attr> <attr name="lineWidth" format="dimension"></attr> </declare-styleable> </resources>
Java
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Handler; import android.util.AttributeSet; import android.view.View; import java.util.Calendar; public class MyClock extends View { private int hour,minute,second; private boolean running; private Paint circlePaint,linePaint,timerPaint,numPaint; //circlePaint---画圆的画笔,linePaint---画刻度线画笔,timerPaint---画时分秒的画笔,以及时钟上的数字 private int circleColor01,circleColor02;//颜色 private int circleWidth;//时钟外圈的宽度 private Handler handler; private float density = getResources().getDisplayMetrics().density;//取手机密度 public MyClock(Context context){ super(context); circleColor01 = 0xFFFF0000; circleColor02 = 0xFFFFFFFF; circleWidth = (int)(4*density); init(); } public MyClock(Context context,AttributeSet attrs){ super(context,attrs); //通过TypedArray的相应方法获得attrs.xml定义的参数值,格式TypedArray的name+下划线+属性名称 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyClock); circleColor01 = a.getColor(R.styleable.MyClock_circleColor01,0xFFFF0000); circleColor02 = a.getColor(R.styleable.MyClock_circleColor02,0xFFFFFFFF); circleWidth = a.getDimensionPixelOffset(R.styleable.MyClock_circleWidth, 4); init(); a.recycle(); } private final void init(){ hour = 0;minute = 0;second = 0; running = false; handler = new Handler(); //初始化各个画笔 circlePaint = new Paint(); circlePaint.setAntiAlias(true); linePaint = new Paint(); linePaint.setColor(0xFF000000); linePaint.setAntiAlias(true); linePaint.setStrokeWidth(2.0f * density); timerPaint = new Paint(); timerPaint.setColor(0xFF000000); timerPaint.setAntiAlias(true); timerPaint.setStrokeWidth(3.0f * density); numPaint = new Paint(); numPaint.setColor(0xFF000000); numPaint.setAntiAlias(true); numPaint.setTextSize(40); numPaint.setStrokeWidth(3.0f*density); } //用onMeasure方法询问组件大小 protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){ int width = measureWidth(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); int result = Math.min(width,height); setMeasuredDimension(result, result); } //调用此方法得到模式和大小 private int measureWidth(int measureSpec){ int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if((specMode == MeasureSpec.EXACTLY)||(specMode == MeasureSpec.AT_MOST)){ result = specSize; }else { result = 256; } return result; } private int measureHeight(int measureSpec){ int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if((specMode == MeasureSpec.EXACTLY)||(specMode == MeasureSpec.AT_MOST)){ result = specSize; }else { result = 256; } return result; } //绘画 protected void onDraw(Canvas canvas){ super.onDraw(canvas); circlePaint.setColor(0xFF0000FF); canvas.drawCircle(this.getWidth() / 2, this.getHeight() / 2, this.getWidth() / 2, circlePaint); circlePaint.setColor(circleColor02); canvas.drawCircle(this.getWidth() / 2, this.getHeight() / 2, this.getWidth() / 2 - circleWidth, circlePaint); for (int i = 1;i<=12;i++){ canvas.save(); canvas.rotate(30*i,this.getWidth()/2, this.getHeight()/2); canvas.drawLine(this.getWidth()/2,25*density,this.getWidth()/2,circleWidth + 1*density, linePaint); canvas.drawText(""+i,this.getWidth()/2,20*density+65,numPaint); canvas.restore(); } for (int i = 1;i<=60; i++){ canvas.save(); canvas.rotate(6*i, this.getWidth()/2, this.getHeight()/2); canvas.drawLine(this.getWidth()/2,15*density,this.getWidth()/2,circleWidth + 1*density, linePaint); //canvas.drawText(""+i,this.getWidth()/2,20*density+60,numPaint); canvas.restore(); } canvas.save(); canvas.rotate(hour * 30 + minute / 2, this.getWidth() / 2, this.getHeight() / 2); timerPaint.setStrokeWidth(5.0f * density); //canvas.drawLine(this.getWidth() / 2, this.getHeight() / 2, this.getWidth() / 2, circleWidth + (this.getHeight()/4) * density, timerPaint); canvas.drawLine(this.getWidth()/2, this.getHeight()/2, this.getWidth()/2, this.getHeight() / 2 - (this.getWidth() /10-circleWidth)*density, timerPaint); canvas.restore(); canvas.save(); canvas.rotate(minute * 6, this.getWidth() / 2, this.getHeight() / 2); timerPaint.setStrokeWidth(4.0f * density); //canvas.drawLine(this.getWidth() / 2, this.getHeight() / 2, this.getWidth() / 2, circleWidth + (this.getHeight()/12) * density, timerPaint); canvas.drawLine(this.getWidth()/2, this.getHeight()/2, this.getWidth()/2, this.getHeight() / 2 - (this.getWidth()/8-circleWidth)*density, timerPaint); canvas.restore(); canvas.save(); canvas.rotate(second*6, this.getWidth()/2, this.getHeight()/2); timerPaint.setStrokeWidth(3.0f*density); //canvas.drawLine(this.getWidth()/2, this.getHeight()/2, this.getWidth()/2, circleWidth + (this.getHeight()/18)*density, timerPaint); canvas.drawLine(this.getWidth()/2, this.getHeight()/2, this.getWidth()/2, this.getHeight()/2-(this.getWidth()/7-circleWidth)*density, timerPaint); canvas.restore(); } private class TimerTask implements Runnable{ public void run(){ while (running){ try{ Thread.sleep(1000); }catch (InterruptedException e){ return; } Calendar c = Calendar.getInstance(); hour = c.get(Calendar.HOUR); minute = c.get(Calendar.MINUTE); second = c.get(Calendar.SECOND); handler.post(new Runnable(){ public void run(){ MyClock.this.invalidate(); } }); } } } protected void onAttachedToWindow(){ super.onAttachedToWindow(); start(); } public void onDetachedFromWindow(){ super.onDetachedFromWindow(); stop(); } public void start(){ if(running == false){ running = true; Thread t = new Thread(new TimerTask()); t.start(); } } public void stop(){ running = false; } }
2.在现有组件上添加自定义
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.widget.TextView; public class Textview extends TextView { private int lineColor; private int lineWidth; private Paint linePaint; public Textview(Context context){ super(context); lineColor=0xFF000000; lineWidth=2; init(); } public Textview(Context context,AttributeSet attrs){ super(context,attrs); TypedArray a=context.obtainStyledAttributes(attrs,R.styleable.Textview); lineColor=a.getColor(R.styleable.Textview_lineColor,0xFF000000); lineWidth=a.getDimensionPixelOffset(R.styleable.Textview_lineWidth,2); init(); a.recycle(); } private final void init(){ linePaint=new Paint(); linePaint.setColor(lineColor); linePaint.setAntiAlias(true); linePaint.setStrokeWidth(lineWidth); } protected void onDraw(Canvas canvas){ super.onDraw(canvas); canvas.drawLine(0,this.getHeight(),this.getWidth(),this.getHeight(),linePaint); } }
3.布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" 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="com.rj141.sb.myclockview.MainActivity" android:orientation="vertical"> <com.rj141.sb.myclockview.Textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" app:lineColor="#FFFF0000" android:textSize="24dp" app:lineWidth="3dp" android:text="@string/clock" /> <com.rj141.sb.myclockview.MyClock android:layout_marginTop="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/id_clock" app:circleColor01 = "#FF0000FF" app:circleColor02 = "#ffffff" app:circleWidth = "4dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/start" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/start"/> <Button android:id="@+id/stop" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/stop"/> </LinearLayout> </LinearLayout>
4.显示
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button start,stop; private MyClock myClock; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myClock=(MyClock)this.findViewById(R.id.id_clock); start=(Button)this.findViewById(R.id.start); start.setOnClickListener(this); stop=(Button)this.findViewById(R.id.stop); stop.setOnClickListener(this); } @Override public void onClick(View v){ switch (v.getId()) { case R.id.start: myClock.start(); break; case R.id.stop: myClock.stop(); break; default: break; } } }
标签:
原文地址:http://blog.csdn.net/qq_29481375/article/details/51357265