由於Android提供的空間有限,不能滿足程序的需求,所以纔有了自定義控件
時鐘
首先要寫一個類繼承自View
package com.example.administrator.myselfview.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import java.util.Calendar;
/**
* Created by Administrator on 2015/9/16.
*/
public class MyAlarmview extends View {
private int width;
private int height;
private Paint mPaintLine;
private Paint mPaintSecondLine;
private Paint mPaintCricle;
private Paint mPaintText;
private Calendar mCalendar;
public static final int UPDATE_TIME=0X22;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_TIME:
mCalendar=Calendar.getInstance();
invalidate();
handler.sendEmptyMessageDelayed(UPDATE_TIME,1000);
break;
}
}
};
public MyAlarmview(Context context) {
super(context);
}
public MyAlarmview(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintLine=new Paint();
mPaintLine.setColor(Color.BLACK);//設置顏色
mPaintLine.setStrokeWidth(10);//畫筆寬度
mPaintSecondLine=new Paint();
mPaintSecondLine.setColor(Color.GRAY);
mPaintSecondLine.setStrokeWidth(5);
mPaintCricle=new Paint();
mPaintCricle.setColor(Color.BLACK);
mPaintCricle.setStrokeWidth(10);
mPaintCricle.setStyle(Paint.Style.STROKE);//圓形畫筆空心
mPaintText=new Paint();
mPaintText.setColor(Color.BLACK);
mPaintText.setTextSize(30);//字體畫筆設置字體大小
mPaintText.setTextAlign(Paint.Align.CENTER);//讓字體居中顯示
mCalendar=Calendar.getInstance();
handler.sendEmptyMessage(UPDATE_TIME);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
height=getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//先畫一個圓,調用canvas的drawCircle方法,第一個參數爲圓心的橫座標,第二個參數爲圓心縱座標,第三個參數爲半徑,第四個參數爲畫筆
canvas.drawCircle(width/2,height/2,300,mPaintCricle);
//劃出12個表示小時的線
for (int i=1;i<=12;i++){
canvas.rotate(30,width/2,height/2);//畫布旋轉30度
canvas.drawLine(width/2,height/2-300,width/2,height/2-280,mPaintLine);
canvas.drawText(""+i,width/2,height/2-250,mPaintText);
}
//劃出表示分鐘的60個點
for (int i=0;i<60;i++){
canvas.rotate(6,width/2,height/2);
canvas.drawLine(width/2,height/2-300,width/2,height/2-290,mPaintLine);
}
//用Calendar類得到當前的小時分鐘秒
int minute=mCalendar.get(Calendar.MINUTE);
int hour=mCalendar.get(Calendar.HOUR);
int second=mCalendar.get(Calendar.SECOND);
//然後得到當前的時間時針分針秒針需要旋轉的角度
float minDegree=minute/60f*360;
float hourDegree=(hour*60+minute)/12f/60*360;
float secondDegree=second/60f*360;
canvas.save();//保存當前狀態
canvas.rotate(hourDegree,width/2,height/2);
canvas.drawLine(width/2,height/2-150,width/2,height/2+10,mPaintLine);
canvas.restore();//返回之前保存的狀態
canvas.save();
canvas.rotate(minDegree,width/2,height/2);
canvas.drawLine(width/2,height/2-200,width/2,height/2+15,mPaintLine);
canvas.restore();
canvas.save();
canvas.rotate(secondDegree,width/2,height/2);
canvas.drawLine(width/2,height/2-230,width/2,height/2+20,mPaintSecondLine);
canvas.restore();
}
}
在XML文件中定義一下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.administrator.myselfview.view.MyAlarmview
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
由於是自定義控件,所以要寫全名
然後MainActivity中不需要多寫什麼,只需加入這個界面就行。
繼承自View之後需要重寫其構造器,View有四個構造器,這裏重寫其前兩個構造器,並在第二個構造器中定義自定義的畫筆。然後重寫onMeasure()和onDraw()方法,在onMeasure()方法中定義畫布的寬和高,這裏使用的是系統定義的畫布的大小;然後在onDraw()方法中進行對畫布的操作,即作圖。最後利用Handler類來對信息進行處理,使用 invalidate()對畫布進行重畫刷新操作。
進度條
這裏做了三個簡單的進度條,方法都一樣,爲圓形擴散型進度條,矩形填充進度條,弧形旋轉進度條
圓形進度條
同樣首先需要新建一個自定義控件的類並繼承自View,並重寫其兩個構造器和兩個方法
package com.example.administrator.myselfview.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by Administrator on 2015/9/16.
*/
public class MyProgressBallView extends View{
private int width;
private int height;
private Paint mPaintBack;
private Paint mPaintCurrent;
private Paint mPaintText;
private int maxProgress=100;
private int currentProgress;
public void setCurrentProgress(int currentProgress) {
this.currentProgress = currentProgress;
}
public MyProgressBallView(Context context) {
super(context);
}
public MyProgressBallView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintBack=new Paint();
mPaintBack.setColor(Color.GRAY);
mPaintBack.setAntiAlias(true);
mPaintCurrent=new Paint();
mPaintCurrent.setColor(Color.GREEN);
mPaintCurrent.setAntiAlias(true);
mPaintText=new Paint();
mPaintText.setColor(Color.BLUE);
mPaintText.setTextSize(80);
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);
invalidate();//重新繪製
canvas.drawCircle(width/2,height/2,300,mPaintBack);//最底下作爲背景的圓
canvas.drawCircle(width/2,height/2,currentProgress*300f/maxProgress,mPaintCurrent);
//根據進度實時更新畫出的表示進度的圓
canvas.drawText(currentProgress*100f/maxProgress+"%",width/2,height/2,mPaintText);
}//文本畫筆實時更新表示下載進度
}
在自定義View中千萬不要忘記每次都要重新繪製,即invalidate();要不然界面是不會動的。
然後在Activity中簡單的模仿一個下載進度,並把當前進度傳遞到自定義View類中來,好實時地重繪到屏幕上。
package com.example.administrator.myselfview.subactivity;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.administrator.myselfview.R;
import com.example.administrator.myselfview.view.MyProgressBallView;
/**
* Created by Administrator on 2015/9/16.
*/
public class ProgressBallActivity extends Activity {
private MyProgressBallView myProgressBallView;
private Button mButton_start;
private int count=0;
private static final int PROGRESSBALL=121;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case PROGRESSBALL:
count++;
if (count<=100){
myProgressBallView.setCurrentProgress(count);
handler.sendEmptyMessageDelayed(PROGRESSBALL, 150);
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progressball);
mButton_start= (Button) findViewById(R.id.button_progress_ball_start);
myProgressBallView= (MyProgressBallView) findViewById(R.id.progress_ball);
mButton_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.sendEmptyMessage(PROGRESSBALL);
}
});
}
}
利用Handler類通過子線程控制UI,設置當前進度。
然後在XML文件中聲明
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_progress_ball_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="開始下載"/>
<com.example.administrator.myselfview.view.MyProgressBallView
android:id="@+id/progress_ball"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
這裏定義自定義控件的時候,切記一定要寫全名
弧形進度條
弧形進度條跟圓形是一樣,只不過是繪製圖形的時候用到的方法不一樣而已,其他完全相同,這裏只寫繪製時候的代碼
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
invalidate();
canvas.drawArc(new RectF(width/2-300,height/2-300,width/2+300,height/2+300),90f,360f,false,mPaintBack);
canvas.drawArc(new RectF(width/2-300,height/2-300,width/2+300,height/2+300),-90f,currentProgress*360f/maxProgress,false,mPaintCurrent);
canvas.drawText(currentProgress*100f/maxProgress+"%",width/2,height/2,mPaintText);
}
矩形進度條
同樣,這裏只是舉出矩形進度條繪製時候的方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
invalidate();
canvas.drawRect(width/2-120,height/2-300,width/2+120,height/2+300,mPaintBack);
canvas.drawRect(width/2-120,height/2+300-currentProgress*600f/maxProgress,width/2+120,height/2+300,mPaintCurrent);
canvas.drawText(currentProgress*100f/maxProgress+"%",width/2,height/2,mPaintText);
}