編輯:關於Android編程
當Android自帶的View滿足不了開發者時,自定義View就發揮了很好的作用。
建立一個自定義View,需要繼承於View類,並且實現其中的至少一個構造函數和兩個方法:onMeasure()和onDraw();
onMeasure()用於設置自定義View的尺寸,onDraw()用於繪制View中的內容。
在onDraw()方法中,需要調用畫筆繪制圖形或文本,繪制的模板時Canvas對象, Canvas類中用來繪制圖形文本的方法有:
drawRect(RectF rect, Paint paint) //繪制區域,參數一為RectF一個區域
drawPath(Path path, Paint paint) //繪制一個路徑,參數一為Path路徑對象
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) //貼圖,參數一就是我們常規的Bitmap對象,參數二是源區域(這裡是bitmap),參數三是目標區域(應該在canvas的位置和大小),參數四是Paint畫刷對象,因為用到了縮放和拉伸的可能,當原始Rect不等於目標Rect時性能將會有大幅損失。
drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) //畫線,參數一起始點的x軸位置,參數二起始點的y軸位置,參數三終點的x軸水平位置,參數四y軸垂直位置,最後一個參數為Paint 畫刷對象。
drawPoint(float x, float y, Paint paint) //畫點,參數一水平x軸,參數二垂直y軸,第三個參數為Paint對象。
drawText(String text, float x, floaty, Paint paint) //渲染文本,Canvas類除了上面的還可以描繪文字,參數一是String類型的文本,參數二x軸,參數三y軸,參數四是Paint對象。
drawOval(RectF oval, Paint paint)//畫橢圓,參數一是掃描區域,參數二為paint對象;
drawCircle(float cx, float cy, float radius,Paint paint)// 繪制圓,參數一是中心點的x軸,參數二是中心點的y軸,參數三是半徑,參數四是paint對象;
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//畫弧,參數一是RectF對象,一個矩形區域橢圓形的界限用於定義在形狀、大小、電弧,參數二是起始角(度)在電弧的開始,參數三掃描角(度)開始順時針測量的,參數四是如果這是真的話,包括橢圓中心的電弧,並關閉它,如果它是假這將是一個弧線,參數五是Paint對象。
繪制圖形需要畫筆Paint對象,Paint類中的方法有:
setARGB(int a, int r, int g, int b) // 設置 Paint對象顏色,參數一為alpha透明值
setAlpha(int a) // 設置alpha不透明度,范圍為0~255
setAntiAlias(boolean aa) // 是否抗鋸齒
setColor(int color) // 設置顏色,這裡Android內部定義的有Color類包含了一些常見顏色定義
setTextScaleX(float scaleX) // 設置文本縮放倍數,1.0f為原始
setTextSize(float textSize) // 設置字體大小
setUnderlineText(booleanunderlineText) // 設置下劃線
一個自定義時鐘視圖的寫法:
public class MyView extends View {
private int width;
private int height;
private Paint mPaintLine;
private Paint mPaintCircle;
private Paint mPaintHour;
private Paint mPaintMinute;
private Paint mPaintSec;
private Paint mPaintText;
private Calendar mCalendar;
public static final int NEED_INVALIDATE = 0X23;
//每隔一秒,在handler中調用一次重新繪制方法
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case NEED_INVALIDATE:
mCalendar = Calendar.getInstance();
invalidate();//告訴UI主線程重新繪制
handler.sendEmptyMessageDelayed(NEED_INVALIDATE,1000);
break;
default:
break;
}
}
};
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
mCalendar = Calendar.getInstance();
mPaintLine = new Paint();
mPaintLine.setColor(Color.BLUE);
mPaintLine.setStrokeWidth(10);
mPaintCircle = new Paint();
mPaintCircle.setColor(Color.GREEN);//設置顏色
mPaintCircle.setStrokeWidth(10);//設置線寬
mPaintCircle.setAntiAlias(true);//設置是否抗鋸齒
mPaintCircle.setStyle(Paint.Style.STROKE);//設置繪制風格
mPaintText = new Paint();
mPaintText.setColor(Color.BLUE);
mPaintText.setStrokeWidth(10);
mPaintText.setTextAlign(Paint.Align.CENTER);
mPaintText.setTextSize(40);
mPaintHour = new Paint();
mPaintHour.setStrokeWidth(20);
mPaintHour.setColor(Color.BLUE);
mPaintMinute = new Paint();
mPaintMinute.setStrokeWidth(15);
mPaintMinute.setColor(Color.BLUE);
mPaintSec = new Paint();
mPaintSec.setStrokeWidth(10);
mPaintSec.setColor(Color.BLUE);
handler.sendEmptyMessage(NEED_INVALIDATE);//向handler發送一個消息,讓它開啟重繪
}
@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);
int circleRadius = 400;
//畫出大圓
canvas.drawCircle(width / 2, height / 2, circleRadius, mPaintCircle);
//畫出圓中心
canvas.drawCircle(width / 2, height / 2, 20, mPaintCircle);
//依次旋轉畫布,畫出每個刻度和對應數字
for (int i = 1; i <= 12; i++) {
canvas.save();//保存當前畫布
canvas.rotate(360/12*i,width/2,height/2);
//左起:起始位置x坐標,起始位置y坐標,終止位置x坐標,終止位置y坐標,畫筆(一個Paint對象)
canvas.drawLine(width / 2, height / 2 - circleRadius, width / 2, height / 2 - circleRadius + 30, mPaintCircle);
//左起:文本內容,起始位置x坐標,起始位置y坐標,畫筆
canvas.drawText(+i, width / 2, height / 2 - circleRadius + 70, mPaintText);
canvas.restore();//
}
int minute = mCalendar.get(Calendar.MINUTE);//得到當前分鐘數
int hour = mCalendar.get(Calendar.HOUR);//得到當前小時數
int sec = mCalendar.get(Calendar.SECOND);//得到當前秒數
float minuteDegree = minute/60f*360;//得到分針旋轉的角度
canvas.save();
canvas.rotate(minuteDegree, width / 2, height / 2);
canvas.drawLine(width / 2, height / 2 - 250, width / 2, height / 2 + 40, mPaintMinute);
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 - 200, width / 2, height / 2 + 30, mPaintHour);
canvas.restore();
float secDegree = sec/60f*360;//得到秒針旋轉的角度
canvas.save();
canvas.rotate(secDegree,width/2,height/2);
canvas.drawLine(width/2,height/2-300,width/2,height/2+40,mPaintSec);
canvas.restore();
}
}
需要在布局中加載自定義View,名字必須是全名(包括包名):
activity_timer
主活動setContentView就行了
public class TimerActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
}
}
演示結果:
前言:在移動客戶端的開發中,地理位置定位是一個非常重要的環節,有些時候用戶可能會限制web app或者Android app的一些權限,或者由於信號不佳的原因無法獲得准確
添加水印的方法挺簡單的,具體內容如下public class MainActivity extends AppCompatActivity { @Override p
最近翻看以前的某項目時,發現了一個極其常用的效果——廣告條,或者也稱不上自定義組件,但是使用頻率還是相當普遍的。 打開市面上各大A
Android基於Linux2.6+內核,我們看一張圖,以對Android系統的架構有個感性的認識。 我們從Kernel層簡單說明: 1、