Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發技巧——自定義控件之使用style

Android開發技巧——自定義控件之使用style

編輯:關於Android編程

Android開發技巧——自定義控件之使用style

回顧

在上一篇《Android開發技巧——自定義控件之自定義屬性》中,我講到了如何定義屬性以及在自定義控件中獲取這些屬性的值,也提到了關於這些屬性除了可以在布局文件中指定之外,也可以在主題中指定。接下來將分享我所了解的關於在主題中指定屬性值的兩種方式。

在主題中指定屬性值

我們在開發過程中,雖然關於自定義控件學會了如何在布局文件中指定它的值,以應對不同的需求。但有時還會遇到這樣一種情況:我們希望對某個控件的屬性,能夠做一個全局的配置,這樣我在本項目中使用它的時候,都是同樣的表現,而不需要每個布局文件都復制一次屬性的值,而在另一個項目中,我們可以進行另一個全局的配置。

屬性定義及關於實現的思考

在上一篇中,我們講到了自定義屬性,如下所示:

 

其中format定義了這個屬性的格式,它支持以下這些方式:

boolean 布爾值 color 顏色 dimension 尺寸 enum 枚舉 flag 位或運算 float 浮點值 fraction 百分數 integer 整型值 string 字符串 reference 引用某一資源ID

在定義格式時,還可以指定多種格式。比如

 

而這裡要說的就是reference,引用某一資源ID。

我們可以定義一個屬性,格式為reference,然後在theme中配置它的值為某個style,這樣我們就可以讀取到這個style的屬性。這是我們對這個實現過程的思考。

下面以我以前寫的一個項目IconTabPageIndicator為例,全部代碼見其develop分支。這是一個底部菜單指示器,其中每個tab(繼承自TextView)的具體表現我們都希望能夠在style中定義。所以首先我們先定義一個屬性,用於指定這個tab的style:

    

下面分別說明對這個屬性的兩種使用方式。

在Java代碼中獲取

重寫構造方法。在本例子中,我們的TabView是通過在java代碼中自己new出來的,調用的是構造方法TabView(Context context),所以我們需要重寫這個構造方法,在這個構造方法中調用this(context, null, R.attr.tabView),第三個參數傳入的是R.attr.tabView,即我們定義的style屬性。

        public TabView(Context context) {
            this(context, null, R.attr.tabView);
        }

然後我們重寫所調用的這個帶defStyle參數的構造方法,因為另外一個構造方法TextView(Context context, AttributeSet attrs)也是調用了它:

        public TabView(Context context, AttributeSet attr, int defStyle) {
            super(context, attr, defStyle);
            TypedArray a = context.obtainStyledAttributes(attr, R.styleable.TabView, defStyle, 0);
            iconWidth = a.getDimensionPixelSize(R.styleable.TabView_iconWidth, 0);
            iconHeight = a.getDimensionPixelSize(R.styleable.TabView_iconHeight, 0);
            a.recycle();
        }

在構造方法中,首先第一行是調用父構造方法。接下來,我們就需要獲取我們自定義的其他屬性了,比如在這個例子中的圖標寬高,獲取時調用的方法與昨天所使用的有點不同 ,我們調用的是
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes),第三個參數是我們定義的style屬性,第四個參數則是style資源。在確定一個屬性最終的值的時候,優先級順序是這樣的:

首先獲取給定的AttributeSet中的屬性值 如果找不到,則去AttributeSet中style(你在寫布局文件時定義的style=@style/xxxx)指定的資源獲取 如果找不到,則去defStyleAttr以及defStyleRes中的默認style中獲取。 最後去找的是當前theme下的基礎值。

所以在上面的方法中,我們也可以給第四個參數傳一個我們默認的style(R.style.xxx),當使用者沒有在第三個屬性所指定的style中聲明一些屬性時,就會使用我們第四個參數中的style裡的屬性。

在調用obtainStyledAttributes方法獲取到屬性之後,後面如何使用則可參考前一篇博客,或本項目。

別人如何使用

理論上,其他人使用的時候,只要寫一個style,然後在他的應用的主題中指定,就可以了。但是通常我們會需要指定許多屬性的值,而這些屬性的值大部分情況下都是通用的。所以我們首先應提供一個良好的style,如下:

在這個style中,我定義了tab文字居中,背景色,字體大小顏色,邊距等。在不重寫其中的屬性的情況下,就能提供一個外觀良好的效果。
然後寫個theme,在其中指定這個style,算是作為一個給其他開發者學習的示例:

這裡的tabView就是我們所定義的style屬性,也是我們在構造方法中指定的R.attr.tabView
如果庫的使用者需求對這style進行修改,只需要寫一個style,繼承自我們的TabViewstyle,重寫裡面的屬性值即可:

當然,還有最重要的一步:必須在自己的項目的主題中指定

此例子的完整項目請參考Github項目IconTabPageIndicator

在布局文件中指定style屬性

我們定義的style屬性,除了通過Java代碼來獲取使用之外,也可以直接通過布局文件來使用。需要使用到的是style屬性。
我們對一個控件的style屬性,通常的寫法都是:style=@style/xxxxx,或者是指定android系統中的屬性:style=@android:style/xxxx,除此之外,我們也可以用來指定我們所定義的style屬性。
我另一個練習的項目ActionSheet就是使用了這種方式。完整代碼請參見github上該項目地址,這裡僅摘取部分相關的代碼。
ActionSheet是我寫的一個和qq菜單有點像的菜單,我希望菜單的每一項都是可以配置的。由於菜單是通過Dialog來加載,而Dialog是在Java代碼中new出來,所以不能通過在xml中定義各個屬性來完成菜單外觀的配置,因此采用了這種方式。
首先同樣是定義一些屬性,和上面的一樣:

    
    
    

這裡表示的是菜單列表的屬性,取消按鈕的樣式,以及每一項菜單的樣式。然後在我們的菜單布局文件中,除了不允許配置的屬性我們進行了聲明之外,其他的都是用style屬性來指定,寫法是style=?attr/你所定義的屬性名,如下:

    

同樣在我們的style.xml文件中,需要定義這幾個style:


    下面代碼略...

而庫的使用者,在使用的時候,也需要指定這幾個屬性值:

本篇到此結束,相關項目如下:

IconPageIndicator 開發分支,學習自JakeWharton大神的ViewPagerIndicator ActionSheet,學習自哪個項目我也忘了。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved