View顯示流程
1、onMeasure()測量寬高
2、ViewGroup 佈局, onLayout()
3 、 draw() 視圖顯示自身的內容
1 、繪製背景
2 、爲顯示漸變框做一些準備動作
3 、調用自身的 onDraw(),(ViewGroup 不需要 )
4 、 dispatchDraw() 繪製子視圖 ( 調用了 drawChild() 通知孩子 draw() 自身 )
5 、畫滾動條
View 的自定義的認識
要自定義 View 的顯示效果,可以重寫其 onDraw 方法,然後在 Canvas 上繪製內容即可
public class MyView extends View {
public MyView(Context context) {
super(context);
Log.e("m_tag","MyView(Context context)");
init();
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
Log.e("m_tag","MyView(Context context, AttributeSet attrs)");
init();
}
private Paint paint;
private void init(){
setBackgroundColor(0xff999999);
// 創建畫筆對象
paint = new Paint();
// 設置畫筆的顏色
// paint.setColor(0xFFFF0000);
paint.setColor(Color.RED);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 畫圖 : 畫布 畫筆 顏色
canvas.drawRect(50,100,150,200,paint);
}
}
使用:
<com.xykj.viewdemo.MyView
android:layout_width="match_parent"
android:layout_height="300dp" />
Canvas的基本繪製
// 畫矩形
// 前面 4 個參數表示矩形的左上右下,第五個參數表示畫筆
canvas.drawRect(50,100,150,200,paint);
// 創建一個矩形對象
Rect rect = new Rect(150,300,350,400);
canvas.drawRect(rect,paint);
// 畫一個圓
//( 圓心 x 座標,圓心 y 座標,半徑,畫筆 )
canvas.drawCircle(50,300,50,paint);
Paint的基本設置
設置顏色
paint.setColor(0xFFFF0000);
paint.setColor(Color.RED); // 從 Color 類中獲取的顏色值
// 消除鋸齒
paint.setAntiAlias(true);
// 分開設置各個顏色參數 0x00-0xff 十進制就是 0-255
paint.setARGB(255,20,50,100);
paint.setAlpha(100); // 設置透明度
// 設置畫筆樣式 STROKE 表示空心 FILL 表示實心
paint.setStyle(Paint.Style.STROKE);
// 空心邊框寬度
paint.setStrokeWidth(5);
View的刷新
如果要修改視圖顯示的內容,需要讓視圖重新 onDraw ,然後在畫布上畫上新的內容即可,要讓視圖重新畫需要使用其刷新方法
主線程刷新:invalidate() ; –> 使視圖重新繪製
結合觸摸監聽實現刷新
public class RefreshView extends View {
public RefreshView(Context context) {
super(context);
init();
}
public RefreshView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private Paint paint;
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
}
// 圓的圓心
private int cx = 50, cy = 100;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 畫圓
canvas.drawCircle(cx, cy, 50, paint);
}
// 視圖的觸摸監聽
@Override
public boolean onTouchEvent(MotionEvent event) {
// 獲取觸摸的行爲
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// 手指觸摸到視圖的瞬間
// 得到觸控點跟視圖左上角點的座標 ( 相對位置 )
int x = (int) event.getX();
// int pX = event.getRawX(); // 得到觸控點和屏幕左上角的位置
int y = (int) event.getY();
cx = x;
cy = y;
invalidate(); // 刷新視圖 ( 視圖會重新繪製 )
break;
case MotionEvent.ACTION_MOVE:
// 按下之後離開之前的整個過程 ( 重複執行 )
cx = (int) event.getX();
cy = (int) event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
// 手指離開視圖的瞬間
break;
}
return true;
}
}
子線程刷新,需要使用 postInvalidate 方法,該方法等效於 Handler+invalidate 方式
private Thread changeThread;
// 隨機數 ( 產生 0-255 之間的數字 )
private Random r = new Random();
public void startChangeColor() {
if (null != changeThread && changeThread.isAlive()) {
return;
}
changeThread = new Thread() {
@Override
public void run() {
try {
while(true) {
Thread.sleep(500);
// 改變畫筆顏色
paint.setARGB(255,r.nextInt(256),r.nextInt(256),r.nextInt(256));
// 刷新視圖 ( 子線程 )
postInvalidate(); // 等效於 Handler+invalidate
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
changeThread.start();
}
canvas其他的各種畫
// 圓角矩形
RectF rectF = new RectF(300,10,400,80);
//( 矩形區域,圓角 x 方向半徑,圓角 y 方向半徑 )
canvas.drawRoundRect(rectF,20,20,paint);
// 畫橢圓
RectF oval = new RectF(300,100,400,300);
canvas.drawOval(oval,paint);
RectF arcRectF = new RectF(450,10,550,110);
// 畫弧線或者扇形
// 第一個參數 : 扇形所在的圓所在的矩形區域
// 第二個參數:起始角度
// 第三個參數:跨越的總度數
// 第四個參數: true 表示扇形, false 表示弧線
// 第五個參數:畫筆
canvas.drawArc(arcRectF,-90,90,false,paint);
Path p = new Path();
// 指定起始點
p.moveTo(450,100);
// 畫直線到下一個點
p.lineTo(600,200);
p.lineTo(500,400);
// 畫貝塞爾曲線
// 前面兩個表示弧度控制點,後面兩個參數表示弧線的終點
p.quadTo(300,300,500,200);
// 將最後一個點連接到起始點上
p.close();
// 畫路徑
canvas.drawPath(p,paint)