自定義控件2.第一個自定義view

自定義一個View, 繼承自 View,  實現以下效果:
 
 
其實就是一個寬高爲100的藍色方塊, 左下角紅色字題 Hello! (上面的Hello world 是系統的 TextView).

1. 繼承 View, 重寫 onDraw 方法

   
   
   
   
  1. // 通常要實現下面兩個構造方法
  2. // 第二個參數後面會講到
/** * 自定義一個簡單的 View * * @author GAOYUAN * */public class CustomView1 extends View { private Paint mPaint = new Paint(); private Rect mRect = new Rect(); public CustomView1(Context context) { super(context); } public CustomView1(Context context, AttributeSet attrs) { super(context, attrs); }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setStyle(Style.FILL); mPaint.setColor(Color.BLUE); mRect.set(0, 0, 100, 100); // Avoid object allocations during draw/layout operations (preallocate // and reuse instead) // 避免在 draw/layout 方法中進行對象分配, 提早分配, 或者重用. // canvas.drawRect(new Rect(0, 0, 100, 100), mPaint); canvas.drawRect(mRect, mPaint); // mPaint.reset(); mPaint.setColor(Color.RED); mPaint.setTextSize(30.0f); // 注意, 畫文字的時候, 是從左下角開始畫的. canvas.drawText("Hello!", 0, 100, mPaint); }}
這裏面有幾個注意的點, 在註釋裏寫的都比較詳細了.

2. 在佈局文件中使用

    
    
    
    
<TextView android:id="@+id/tv_hello" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <com.gaoyuan4122.customui.views.CustomView1 android:id="@+id/cv_custom1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/tv_hello" /> <TextView android:id="@+id/tv_hello2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:layout_below="@id/cv_custom1" />
最外層是 RelativeLayout, 這裏就不寫了, 注意要使用自定義View的全名做爲標籤名.

3. 關於控件的寬高

上面這樣就實現了想要的效果, 可是有個問題是, 佈局文件中, 給這個控件設置的寬高爲 wrap_content, 可是實際上這個控件的寬高倒是 match_parent,  它下面的 TextView沒有顯示出來,  以下如所示.

 
這涉及到了View 的測量和繪製過程, 這裏能夠先這樣理解:  咱們並無設置它的寬高, 雖然寫了 wrap_content, 可是系統並不知道這個 "content" 究竟是多大, 因此係統默認就把能夠給的最大的繪製區域給它了, 從效果上來看好像是 match_parent. 可是, 若是給它設置一個確切的寬高, 他就會按照設置的顯示:
   
   
   
   
<TextView android:id="@+id/tv_hello" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <com.gaoyuan4122.customui.views.CustomView1 android:id="@+id/cv_custom1" android:layout_width="100dp" android:layout_height="100dp" android:layout_below="@id/tv_hello" /> <TextView android:id="@+id/tv_hello2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:layout_below="@id/cv_custom1" />
顯示效果以下:

 
下面先簡單的解決一下這個問題, 重寫 CustomView1 的 onMeasure 方法:
   
   
   
   
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { widthMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY); heightMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
這段話的意思是告訴父控件個人大小是100*100, 不管怎樣都是這麼大, 此時佈局文件中的寬高都仍是 wrap_content, 效果就變成下面的樣子了:

 
而且, 不管寬高設置的是多少, 都是100*100. 這裏就先這樣作, 後面會說 onMeasure 的意思.








相關文章
相關標籤/搜索