Android中XML的命名空間、自定義屬性


命名空間(namespace)

XML 命名空間提供避免元素命名沖突的方法。

舉個例子,A學校有名學生叫做林小明,B學校也有名學生叫林小明,那我們如何識別這兩名擁有相同名字的同學呢?這時候命名空間就派上用場了。A和B此時就可以被當成是命名空間了。也就是說,命名空間里面存放的是特定屬性的集合。

Android中常見的命名空間

下面分別介紹android、tools、app(自定義命名空間)這幾個常見的命名空間

1、android

xmlns:android=”http://schemas.android.com/apk/res/android” 

在Android布局文件中我們都必須在根元素上定義這樣一個命名空間,接下來對這行代碼進行逐一講解: 
xmlns:即xml namespace,聲明我們要開始定義一個命名空間了 
android:稱作namespace-prefix,它是命名空間的名字 
http://schemas.android.com/apk/res/android這看起來是一個URL,但是這個地址是不可訪問的。實際上這是一個URI(統一資源標識符),所以它的值是固定不變的,相當於一個常量)。

有了他,就會提示你輸入什么,也可以理解為語法文件。

使用這行代碼,我們就可以引用命名空間中的屬性,如:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="New Text"
        android:id="@+id/textView" />
</LinearLayout>

在這個布局中,只要以android:開頭的屬性便是引用了命名空間中的屬性。

android是賦予命名空間一個名字,就跟我們平時在定義變量一樣,比如我把它取成myns,那么上面的代碼我們也可以寫成:

<LinearLayout xmlns:myns="http://schemas.android.com/apk/res/android"
    myns:layout_width="match_parent"
    myns:layout_height="match_parent" >
    <TextView
        myns:layout_width="wrap_content"
        myns:layout_height="wrap_content"
        myns:layout_gravity="center"
        myns:text="New Text"
        myns:id="@+id/textView" />
</LinearLayout>

2、tools

xmlns:tools=”http://schemas.android.com/tools”

接下來會介紹,關於tools的三種使用方法吧,也算是他的特性。

2.1、tools只作用於開發階段

我們可以把他理解為一個工具(tools)的命名空間,它的只作用於開發階段,當app被打包時,所有關於tools屬性將都會被摒棄掉。

例如,基本上在android命名空間內的屬性,我們想在編寫代碼階段測試某個組件在屏幕上的效果,而當app安裝到手機上時,摒棄掉這條代碼,那么我們就可以用tools命名空間來代替掉android:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        tools:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello,World"/>
</LinearLayout>

以上是在layout中的布局,當我們切換到視圖窗口(Design)中查看時,看到的是標簽頂部居中顯示(左圖),然后,當我們運行到手機上時,確是這樣的:

 

如上所示,tools:layoutgravity= “center”確實在運行后背拋棄掉了!

2.2、tools:context開發中查看Activity布局效果

context的用法,在后面跟一個Activtiy的完整包名,它有什么作用呢?

當我們設置一個Activity主題時,是在AndroidManifest.xml中設置中,而主題的效果又只能在運行后在Activtiy中顯示

使用context屬性, 可以在開發階段中看到設置在Activity中的主題效果

tools:context=”com.littlehan.myapplication.MainActivity”

在布局中加入這行代碼,就可以在design視圖中看到與MainActivity綁定主題的效果。

2.3、tools:layout開發中查看fragment布局效果

當我們在Activity上加載一個fragment時,是需要在運行后才可以看到加載后的效果,有沒有方法在測試階段就在布局預覽窗口上顯示呢?

答案是有的,借助layout屬性,例如,在布局中加入這樣一行代碼: 

tools:layout=@layout/yourfragmentlayoutname 

這樣你的編寫的fragment布局就會預覽在指定主布局上了

3、自定義命名空間

如果使用DataBinding 會在xml用到 app屬性,其實這是個自定義命名空間。

xmlns:app=”http://schemas.android.com/apk/res-auto”

讀者可能會問了,這里哪里體現出是自定義的??

實際上也可以這么寫: 

xmlns:app=”http://schemas.android.com/apk/res/完整的包名” 

在res/后面填寫包名即可。但是,在Android Studio2.0上,是不推薦這么寫的,所以建議大家還是用第一種的命名方法。

通常自定義命名空間往往是和自定義View分不開的,當Android自帶的控件不能滿足需求時,可以自己去繪制一些View,而要為自定義View加上自定義的屬性時,就需要創建自定義命名空間。

命名空間里面存放的是特定屬性的集合,這樣一來,思路就很清晰,也就是說自定義命名空間的實際過程就是自定義屬性。

我們通過一個簡單的自定義TextView來學習下自定義命名空間是怎么一回事,自定義View的過程可以分成以下幾個步驟:

3.1、繼承View類

創建一個類名為CustomTextView繼承View(View是所有視圖的父類)並實現它三個構造方法

public class CustomTextView extends View {
    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//畫筆
    public CustomTextView(Context context) {
        super(context);
    }
    public CustomTextView(Context context, AttributeSet attrs){
        this(context, attrs, 0);//注意不是super(context,attrs,0);
    }
    public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr){
        super(context,attrs,defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("I am a CustomTextView",100, 100, mPaint);
    }
}

3.2、 使用自定義布局

將自定義的控件引入布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    >
<com.littlehan.customtextview.CustomTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
</RelativeLayout>

到了這里,一個自定義的控件就被引入布局使用了,我們可以切換到視圖窗口看看效果:

但是這個自定義控件,並不能在xml中去改變字體顏色,字體大小、自定義文本等。這個功能的實現,需要XML創建自定義屬性和在自定義View中解析屬性

3.3、自定義屬性

在values根目錄下新建一個名為attrs的xml文件來自定義屬性(自定義的屬性便是自定義命名空間里面的屬性)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomTextView">
       <attr name="customColor" format="color"/>
       <attr name="customText" format="string"/>
    </declare-styleable>
</resources>

name定義的是屬性的名字 
format定義的是屬性的類型

自定義屬性也可以不使用declare-styleable,參考這里

3.4、解析屬性

在CustomeTextView中解析這些屬性

public class CustomTextView extends View {
    private int mColor = Color.RED;//默認為紅色
    private String mText="I am a Custom TextView";//默認顯示該文本
    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//畫筆
    public CustomTextView(Context context) {
        super(context);
//        init();
    }
    public CustomTextView(Context context, AttributeSet attrs){
        this(context, attrs, 0);//注意不是super(context,attrs,0);
        init();
    }
    public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr){//解析自定義屬性
        super(context,attrs,defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.CustomTextView);
        mColor = typedArray.getColor(R.styleable.CustomTextView_customColor, Color.RED);
//        如果沒有判斷,當沒有指定該屬性而去加載該屬性app便會崩潰掉
        if(typedArray.getText(R.styleable.CustomTextView_customText) != null ){
            mText = typedArray.getText(R.styleable.CustomTextView_customText).toString();
        }
        typedArray.recycle();//釋放資源
        init();
    }
    private void init(){
        mPaint.setColor(mColor);// 為畫筆添加顏色
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText(mText, 100, 100, mPaint);
    }
}

3.5、使用自定義屬性

要使用自定義屬性,就需要自定義屬性命名空間,在布局文件的根元素下插入這樣一行代碼: 

xmlns:app=”http://schemas.android.com/apk/res-auto”

於是就可以使用自定義屬性了:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    >
<com.littlehan.customtextview.CustomTextView
    app:customColor="@color/colorAccent"
    app:customText="Test Message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
</RelativeLayout>

切換到視圖預覽窗口,可以看到自定義的屬性已經生效了:

總結

在Android中,命名空間可分為3種:

  1. xmlns:android=”http://schemas.android.com/apk/res/android
  2. xmlns:tools=”http://schemas.android.com/tools
  3. xmlns:app=”http://schemas.android.com/apk/res-auto

其中,1和2命名空間里的屬性是系統封裝好的,第3種命名空間里的屬性是用戶自定義的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM