Android 自定義View 一般View定義

在我們編寫android程序時一般是自定義以一個類繼承自Activity 並且重寫onCreate方法:

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

 

setContentView()方法包含多個重載其中一個便是“setContentView(View view)”,也就是說可以直接通過一個View的實例來構建內容。我們嘗試放入一個TextView,上面的代碼變成了這樣:

@Override
 public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  // setContentView(R.layout.main);

      TextView sayHello = new TextView(this);
      sayHello.setText("Hello world! I'm a TextView.");
      setContentView(sayHello);
        
    }

運行這段代碼,在模擬器上你應該可以看到以下結果:

截屏(2011-12-05 22_08_58).jpg

如此簡單不是嗎?好吧讓我們再讓它豐富點:

@Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // setContentView(R.layout.main);
//  TextView sayHello = new TextView(this);
//  sayHello.setText("Hello world! I'm a TextView.");
  setContentView(new SayHello(this));
        
    }
 
 
 class SayHello extends View{

  public SayHello(Context context) {
   super(context);
  }

  @Override
  protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);
   Paint mPaint=new Paint() ;
   mPaint.setTextSize(22f);
   mPaint.setColor(Color.RED);
   canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
  }
 }

這次我們自定義了一個局部類SayHello 繼承自View並且重寫了 onDraw 方法(需要注意的是由於View沒有無參構造函數所以我們爲其指定實現哪一個構造函數)。在onDraw 方法中我們定義了一個Paint,現在你只需要理解它有繪畫的功能即可,那麼它要在哪裏繪畫呢?答案就是在Canvas上,可以把Canvas理解成畫布。

現在我們設置mPaint的字體大小爲22F  顏色爲紅色,然後在畫布上寫出“Hello world。。。”這幾個紅色的字,並且把onCreate裏的setContentView 爲setContentView(new SayHello(this));
最後在模擬器上你應該看到的是:

 截屏(2011-12-05 22_37_57).jpg

so cool! 不是嗎?

不!不對,我們在Android的開發View不是這樣的,它應該是通過 Xml.......@##¥%

好吧 讓我們再把例子修改一下。

 首先我們將SayHello 類提取出來,並且將它放入一個單獨的類文件中,接下來就是重點:我們需要添加另外的一些構造函數以便給View傳遞參數,最好你看到的SayHello 類應該是這樣的:

public class SayHello extends View {
 
 public SayHello(Context context)
 {
  super(context);
 }

 public SayHello(Context context, AttributeSet attrs) {
  this(context, attrs,0);
 }
 
 public SayHello(Context context, AttributeSet attrs,int defStyle)
 {
  super(context, attrs, defStyle);
 }
 
 
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  Paint mPaint=new Paint() ;
  mPaint.setTextSize(22f);
  mPaint.setColor(Color.RED);
  canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
 }
 

}

這裏簡單講解一下新增的構造函數的作用,在新的構造函數中爲View的構造函數傳遞了AttributeSet attrs,int defStyle兩個參數,這代表着該View可以通過XML 來創建並且接受Style來設定樣式。等到相關博文時會再具體講解。

接下來,我們恢復Activity類裏的onCreate方法讓它看起來像這個樣子:

@Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
   setContentView(R.layout.main);

        
    }

和一開始沒啥兩樣對吧。

  最後我們需要去修改佈局文件main 在文件里加入以下 xml標籤:

 <com.××××.customview.SayHello
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </com.××××.customview.SayHello>

(注意××××,代表SayHello類所在的包,這裏需要的是全名)。

然後再次運行程序,你應該看到以下結果:

 截屏(2011-12-05 22_58_04).jpg

是不是和我們平常定義View時很像了?

你感覺得還不夠,還缺乏些什麼?

好吧,你很聰明,我們的Text應該是在XML上通過某個屬性配置而成的,而不是寫在代碼裏!

爲了將SayHello的屬性暴露到XMl上首先我們需要在res/value 文件夾下新建一個XMl文件,命名爲:atts。

在裏面添加如下代碼:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="SayHello">
     <attr name="content" format="string"></attr>
     <attr name="text_color" format="color"></attr>
 </declare-styleable>
    
</resources>

 需要注意的是這裏是沒有智能提示的

然後我們需要修改SayHello類,還記得那個AttributeSet嗎?我們將通過它來獲取XML配置上的屬性值。修改後的SayHello類代碼是這樣的:

private int mColor;
 private String mContent;

public SayHello(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  TypedArray typeArray = context.obtainStyledAttributes(attrs,
    R.styleable.SayHello);
  mColor=typeArray.getColor(R.styleable.SayHello_text_color, 0XFF00FF00);
  mContent=typeArray.getString(R.styleable.SayHello_content);
  
 }

@Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  Paint mPaint = new Paint();
  mPaint.setTextSize(22f);
  mPaint.setColor(mColor);
  canvas.drawText(mContent, 0, 100, mPaint);
 }

現在可以去XML上爲哥哥屬性添加值了,不過先彆着急我們的得將命名空間告訴它。

在佈局文件的根源是上(通常是Layout)添加: xmlns:SayHello="http://schemas.android.com/apk/res/com.XXXX.customview"

SayHello 可以爲您任意想要定義的名字,它將作爲屬性的前綴使用就像android:Layout 一樣而我們的爲:SayHello:content,後半段http://schemas.android.com/apk/res/ 爲固定值,緊接着的是你整個APP的包命名,你不知道自己包名稱?趕去去 AndroidManifest.xml文件中看看吧(注意該包名需要保持和manifest中的 package 保持一致,否則會提示無法找到XML屬性)。

最後我們終於可以在XML上定義自己想要的字體顏色的內容了:

<com.XXXX.customview.SayHello
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        SayHello:text_color="#1212f0"
        SayHello:content="this is a xml attr view">
    </com.XXXX.customview.SayHello>

 運行程序您應該會看到以下結果:

剪切板(2011-12-05 23_29_55).png

 

 

這就是我們View 一般的定義方式和過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章