自定義View學習總結(一)

1.為什么會引入自定義view

現(xiàn)有的控件不滿足我們的需求,或者項目中頻繁用到一種需要我們自定義的控件,把它封裝起來提高復用性。

2.自定義view的使用
2.1 自定義控件的繪制流程:
1,準備工作:(加載階段)
2,規(guī)劃大小:(測量階段)
3,繪制位置:(布局階段)
4,畫:(繪制階段)

1.定義一個類繼承View或View的子類

public class MyView extends View {
  ...
}

2.重寫構造方法

//當需要new當前視圖的時候需要重寫這個構造
public MyView(Context context) {
//一般處理為讓其調用含有兩個參數(shù)的構造方法
    this(context, null);
}
//當需要將自定義View聲明在xml文件中使用的時候需要重寫這個構造方法
public MyView(Context context, AttributeSet attrs) {
//一般處理為調用第三個構造
    this(context, attrs, 0);
}
//當需要將自定義View聲明在xml文件中,并且當前控件需要自定義主題樣式的時候.重寫這個構造方法
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
//做初始化操作
    init();
}

構造方法一般用于數(shù)據(jù)的初始化加載
開發(fā)中也存在只重寫兩個參數(shù)的構造方法的情況,但這樣做就不能再去直接new控件了.

3.重寫onMeasure
onMeasure在自定義view中有時候不用重寫,因為如果是自定義view的話在xml聲明中給定的是確定的數(shù)值或者match_parent時不用重寫該方法,但是如果給定的數(shù)值時wrap_content的時候就需要重寫了,因為此時view不知道采用哪個大小。但是在自定義ViewGroup的時候要重寫onMeasure方法。

onMeasure()方法:用于測量控件,如果控件還有子控件,則會遞歸測量子控件
如果是ViewGroup,默認只會測量自身控件

MeasureSpec:是由父布局和子控件共同決定的,是一個組合值,用于控件的寬高
MeasureSpec是一個32位int值
MeasureSpec是由兩部分組成:
mode:控件尺寸的模式,前兩位
size:控件的尺寸,后三十位

其中mode分為三種:
1,UNSPECIFIED:數(shù)值為0<<30
未限定實際寬高,這種情況較少,例如:ScrollView對于其子視圖的高度的限定
2,EXACTLY:數(shù)值為1<<30
明確的尺寸,例如:xxdp,MATCH_PARENT
3,AT_MOST:數(shù)值為2<<30
至多為多少,例如WRAP_CONTENT,若控件本身沒有默認尺寸,則系統(tǒng)會盡可能的把空間賦予控件,為MATCH_PARENT

常用api

setMeasureDimension(width,height):設置控件的最終尺寸
MeasureSpec spec=  MeasureSpec.makeMeasureSpec(size,mode);用于指定MeasureSpec
MeasureSpec.getSize(measureSpec);通過MeasureSpec獲取size
MeasureSpec.getMode(measureSpec);通過MeasureSpec獲取mode
getSuggestedMinimumWidth():獲得背景圖的寬度,如果沒有背景,則返回值為0

4.onDraw 繪制
onDraw里面只有一個參數(shù)Canvas canvas,這個參數(shù)是用來繪制自定義View的,這個方法里面還有一個重要的變量,Paint paint,這個變量是用來給設置畫筆的

(Paint畫筆相關api)

//給Paint設置顏色
paint.setColor(Color.RED);
//用此Paint繪制出的圖形沒有鋸齒,但會損耗性能
paint.setAntiAlias(true);
//設置Paint樣式(不填充),如:繪制一個空心圓,則設置如下樣式
paint.setStyle(Paint.Style.STROKE);

繪制線,矩形,圓角矩形,圓形,環(huán)形,弧形等
相關api:

//定義一個點,包含x和y坐標
PointF point= new PointF(x, y);

//繪制一個圓
參數(shù)1,2:圓心坐標
//參數(shù)3:半徑
//參數(shù)4:畫筆
canvas.drawCircle(x, y, radius, paint);

//繪制直線
//參數(shù)1,2:起點的x,y坐標
//參數(shù)3,4:起點的x,y坐標
canvas.drawLine(x1, y1,x2,y2, paint);

//定義一個矩形
//參數(shù)1:矩形的左邊相對于屏幕左邊緣的距離
//參數(shù)2:矩形的上邊相對于屏幕上邊緣的距離
//參數(shù)3:矩形的右邊相對于屏幕左邊緣的距離
//參數(shù)4:矩形的下邊相對于屏幕上邊緣的距離
RectF rect= new RectF(l, t, r, b);

//繪制弧形
//參數(shù)1:繪制弧形依賴的矩形,繪制出的弧形會與此矩形內切
//參數(shù)2:弧形的起始角度
//參數(shù)3:弧形的弧度
canvas.drawArc(rect, startAngle,sweepAngle
, false, paint);

//繪制一個矩形
canvas.drawRect(rect,paint);

//繪制一個點
//參數(shù)1,2:繪制的點的x,y坐標
canvas.drawPoint(x,y,paint);

//繪制多個點的x,y坐標
float[] pts = {x1, y1, x2, y2, x3,y3...};
//參數(shù)2:從pts集合中的哪個元素開始繪制(從哪里開始,哪里就作為x坐標,后面是y坐標,依此類推)
//參數(shù)3:包含pts集合中共幾個元素
canvas.drawPoints(pts,offset,count,paint);
canvas.drawRoundRect(rectF,30f,30f,paint);

canvas的變換處理:
Android中的坐標系:默認是以屏幕左上角為原點,x方向向右為+,y方向向下為正
繪制界面是基于坐標系繪制的
若調用了canvas的translate或rotate方法相當于對坐標系進行了平移和旋轉,基于旋轉后的坐標系進行繪制工作.

2.5.Canvas的其他處理
注:canvas在做下列處理前必須先調用save方法處理后要調用restore方法

1,平移
canvas.translate(100,0);
2,旋轉
canvas.rotate(300);
3,縮放
canvas.scale(0.2f,0.2f);
canvas的平移和旋轉可以看成是對繪制坐標系進行的平移或旋轉
3.自定義ViewGroup

自定義ViewGroup除了要進行上面的操作外還需要有一步,重寫onLayout方法

onLayout方法就是主要為了擺放ViewGroup內部的子視圖
onLayout方法參數(shù)四個參數(shù):l,t,r,b:分別為系統(tǒng)賦予ViewGroup的左上右下的值

2,常用api:

addView():向當前控件添加子視圖
getChildCount():獲取當前控件的孩子視圖的個數(shù)
getChildAt():通過指定的位置獲取對應的子視圖
layout():用于對子視圖的擺放處理,可以根據(jù)實際需求傳入對應的l,t,r,b

For example

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//獲取子視圖總數(shù)
    int childCount = getChildCount();
//遍歷所有的子視圖
    for (int i = 0; i < childCount; i++) {
//獲取某個子視圖
        View child = getChildAt(i);
//將這個子視圖擺放到當前空間的某個位置
//1,橫向擺放
    child.layout(30*i,0,30*(i+1),30);
//2,縱向擺放
    //child.layout(0,30*i,30,30*(i+1));
}
//按照倒三角形形狀擺放
int top = 0;
int childIndex = 0;
for (int i = 2; i >= 0; i--) {
    for (int j = 0; j <= i; j++) {
        View child = getChildAt(childIndex);
        child.layout(30 * j, top, 30 * (j + 1), top + 30);
        childIndex++;
    }
    top += 30;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容