新書內容連載(1):自訂Android組件之帶映像的TextView

來源:互聯網
上載者:User
本文為原創,如需轉載,請註明作者和出處,謝謝!

本文為新書《Android/OPhone 開發完全講義》的內容連載。《Android/OPhone開發完全講義》一書現已出版,敬請關注。

購 買:互動網

《Android/OPhone 開發完全講義》目錄

原始碼下載


    在本例中要實現一個可以在文本前方添加一個 映像(可以是任何Android系統支援的映像格式)的TextView組件。在編寫代碼之前,先看一下Android組件的配置代碼。

<TextView android:id="@+id/textview1" android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:text="textview1" />

     在構造方法中可以通過AttributeSet介面的相應getter方法來讀取指定的屬性值,如果 在配置屬性時指定了命名空間,需要在使用getter方法獲得屬性值時指定這個命名空間,如果未指定命名空間,則將命名空間設為null即可。

    IconTextView是本例要編寫的組件類,該類從TextView繼承,在onDraw方法中將TextView中的文本後移,並在文本的前方添加了一個映像,該映像的資源ID通過mobile:iconSrc屬性來指定。IconTextView類的代碼如下:

package net.blogjava.mobile.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;

public class IconTextView extends TextView
{
    //  命名空間的值
    private final String namespace = "http://net.blogjava.mobile";
    //  儲存映像資源ID的變數
    private int resourceId = 0;
    private Bitmap bitmap;
    public IconTextView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        //  getAttributeResourceValue方法用來獲得組件屬性的值,在 本例中需要通過該方法的第1個參數指
         //  定命名空間的值。該方法的第2個參數表示組件屬性名稱(不包括命名空間名稱),第3個 參數表示默
         //  認值,也就是如果該屬性不存在,則返回第3個參數指定的值
        resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc", 0);
        if (resourceId > 0)
              //  如果成功獲得映像資源的ID,裝載這個映像資源,並建立Bitmap對象
            bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
    }
    @Override
    protected void onDraw(Canvas canvas)
    {
        if (bitmap != null)
        {
            //  從原圖上截取映像的地區,在本例中為整個映像
            Rect src = new Rect();
            //  將截取的映像複製到bitmap上的目的地區域,在本例中與複製地區相同
            Rect target = new Rect();
            src.left = 0;
            src.top = 0;
            src.right = bitmap.getWidth();
            src.bottom = bitmap.getHeight();
            int textHeight = (int) getTextSize();
            target.left = 0;
            //  計算映像複製到目的地區域的縱座標。由於TextView組件的常值內容並不是
              //  從最頂端開始繪製的,因此,需要重新計算繪製映像的縱座標
            target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1;
            target.bottom = target.top + textHeight;
            //  為了保證映像不變形,需要根據映像高度重新計算映像的寬度
            target.right = (int) (textHeight * (bitmap.getWidth() / (float) bitmap.getHeight()));
            //  開始繪製映像
            canvas.drawBitmap(bitmap, src, target, getPaint());
            //  將TextView中的文本向右移動一定的距離(在本例中移動了映像寬度加2個象素 點的位置)
            canvas.translate(target.right + 2, 0);
        }
        super.onDraw(canvas);
    }
}

 

在編寫上面代碼時需要注意如下3點:
1.  需要指定命名空間的值。該值將在<LinearLayout>標籤的xmlns:mobile屬性中定義。
2.  如果在配置組件的屬性時指定了命名空間,需要在AttributeSet 介面的相應getter方法中的第1個參數指定命名空間的值,而第2個參數只需指定不帶命名空間的屬性名稱即可。
3.  TextView類中的onDraw方法一定要在translate方法後面執行,否則系統不會移動TextView中的文本。

運行本執行個體後,將顯示1所示的效果。

    注意:雖然很多人認為組件的屬性必須以android命名空間開頭,該命名空間的值必須是http://schemas.android.com/apk/res/android。實際上,只是命名空間的值必須是http://schemas.android.com/apk/res/android而已,命名空間的名稱可以是任何值,如下面的代碼所示:

<?xml version="1.0" encoding="utf-8"?>
<!--  將android換成了abcd  -->
<LinearLayout xmlns:abcd="http://schemas.android.com/apk/res/android"
    abcd:orientation="vertical" abcd:layout_width="fill_parent"
    abcd:layout_height="fill_parent">
     
</LinearLayout>

 
下一篇:新書內容連載(2):Android Activity的生命週期

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.