Android 自訂View – 啟航 一般View定義

來源:互聯網
上載者:User

   Android應用程式使用View和ViewGroup來構建使用者介面,它們都是繼承自View類(或其子類)例如:Button、TextView、EditText等。各類View搭配上Style和Animation可以編織出非常豐富的UI,足以應付絕大部分的需求。但有時候我們也需要一些特別的View
,以帶給使用者與眾不同的體驗。

    在此我打算寫一個大長篇都是關於android
View的,主要內容為:SDK上部分文章翻譯(英文水平有限盡請拍磚);自訂的View、android原始碼分析、開源View程式碼分析;各類App應用的介面模仿;以理論+程式碼範例+實踐
的方式指導本系列博文的撰寫。

    ——因為本人水平有限,而且寫系列經常虎頭蛇尾,所以這個系列就不寫總目錄了。如果哪天您發現本系列不在更新,而我又開始了另一個“大長篇”,那麼請扔雞蛋吧。(但是我們不退票!)

    ——出於前車之鑒,本系列中的源碼將不提供打包服務。

 

   言歸正傳,在我們編寫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);
       
    }

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

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

@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));
最後在模擬器上你應該看到的是:

 

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類所在的包,這裡需要的是全名)。

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

 

是不是和我們平常定義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>

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

 

 

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

——啟航。

 

 

 

 //本筆記從 麥庫中複製過來, 圖片連不上,請見諒

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.