徹底搞清楚Android中的 Attr

版權聲明:本文為sydMobile原創文章,轉載請務必注明出處! https://blog.csdn.net/sydMobile/article/details/79978187

相信這個詞對于Android開發者來說十分熟悉了,那么你對他到底有多了解呢?

回憶起我剛開始接觸Android的時候對這三個詞有一些迷惑,有些時候只知道一些基本的使用,總之是有迷惑把。不能說的很清楚!

今天就來仔細說說這個詞。

本來寫的時候沒想多會牽扯這么多內容,因為在寫的過程,考慮到很細,想要寫的盡可能全面,讓“0基礎的朋友”也可以看懂,所有寫著寫著就很長了,建議收藏后慢慢看!耐心看到最后!

Attr基本概念

Attr :單詞的意思是屬性的意思(但是這里的屬性和xml控件中的屬性不是一個意思,不要混淆!Attr說是屬性只是說的是它的單詞的意思是屬性),我們是通過Attr文件來定義我們控件中所使用的屬性的,這樣說可能大家會有一迷惑,那么來舉個栗子:

比如我們在控件中最多使用的 layout_width 屬性

layout_width

layout_width

這個屬性就是在Attr里面定義的,那么如何來查找這個屬性呢?看圖片

Attribute位置

Attribute位置

View屬性

看到上面的圖片,我們可以看到在Android的sdk中給我們建立了一個attr文件,
這里面就是定義了我們在控件中用到的屬性。我們再到Android的SDK給我們定義的 attr 文件中去看看

圖片view

view

view

view

上面的屬性是為view這個控件定義的屬性,看注釋介紹的很清楚,這是為View和他的子類提供的屬性組,也就是說這里面的屬性都可以用在view和它的子類中,使用。看到這里面的屬性是不是很眼熟啊,這里面的屬性是不是我們在寫布局的時候都有用到過啊。

TextView屬性

再來看看Android SDK為TextView定義的屬性組

TextView 屬性

等等,我們用到的控件在這里都有對應的屬性進行聲明。看到這里是不是明白了attr的意思了,attr其實就是一個文件,這里面定義了我們的控件中所使用的屬性。

具體的說一下attr的一些知識

如何定義attr?

我們首先來看看Android的官方屬性是如何進行定義了

TextView屬性定義

我們看到首先聲明了一組屬性,取了一個名字叫 TextView,然后在這里面定義了一系列的屬性。

我在這里總結了屬性的定義格式:

1   <declare-styleable name="TextView">2  <attr  name ="屬性1" format = "這個屬性的取值格式">3  <enum name="取值1" value="程序中對應的值"/><enum name="取值1" value="程序中對應的值"/><enum name="取值1" value="程序中對應的值"/><enum name="取值1" value="程序中對應的值"/>4  <flag name="取值1" value="程序中對應的值" /><flag name="取值2" value="程序中對應的值" /><flag name="取值3" value="程序中對應的值" /></declare-styleable>

其中3和4是可以省略的, format也是可以省略的(我們之所以自定義屬性,一般就是在自定義View中使用,如果省略了format的話只是在布局中我們使用這個屬性的時候沒有提示,只要在布局中填的屬性內容和你的 java 文件的取值對應就沒問題,不過還是建議format要定義好,這樣更清晰不容易亂)3就是我們提前給這個屬性設置了幾個值,可以直接在這幾個值中取。與4的區別就是:flag可以在布局文件中這樣使用 取值1|取值2 也就是說可以取多個值。
例子:

layout_width定義

這里就是我們常用的layout_width的定義方式:看到我們可以將layout_width的值設置為fill_parent或者match_parent或wrap_content或者自己填寫大小。

而textStyle 我們的取值就可以是多個了,就不再多介紹了。
好了,下面我們可以自己來定義屬性了。

自定義屬性

重點來介紹format里面的一些值
fraction:百分數
例子:
使用:
app:xshow = “70%”
reference : 指定某一資源ID
例子:
使用 : app:backgroundresourece = “@drawable/id”
別的格式基本上就是見名知意,就不再介紹了。

屬性的取值

在某些情況下,我們可能想讓某個屬性取另一個屬性的值,這樣說可能不太好懂。看例子!

test_attr

上圖是我自己定義的一個屬性,在我的布局中有一個TextView,我想讓Text的內容取test_attr的內容,怎么辦呢?

textView中使用test_attr屬性

沒錯就是 ?attr/屬性名字 這樣就是取 test_attr這個屬性的值,如果test_attr是
android里面的attr值呢?那么引入方式就是 :?android:attr/屬性名字 或者 省去attr
以上的操作都有一個前提:

attr的值只有在theme中被賦值才有效(否則這樣取值的結果就是程序報錯,注意在有些主題中有些屬性給了默認值,這個時候引用就沒有錯,但是如果沒有默認值,而你又沒有在主題中給定義上那樣就會出錯了),也就是說必須在清單文件中的 Application或者 Activity中設置 Theme,并且Theme指向的屬性有值才可以引用attr的值,在單獨的控件中使用 android:Theme 或者 app:theme添加樣式是沒有用的!

obtainStyledAttributes詳細說明

在自定義View中獲取我們自定義的attr的值,一般大家都會這樣寫:

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.屬性組名稱, defStyleAttr, defStyleRes);
a.getXX(R.styleable.XX_xxx);
a.recycle();

關于方法obainStyledAttributes()

obainStyledAttributes

我們可以看到這個方法是存在在Context中的方法,最終調用的是getTheme()里面的方法,所以我們有的時候看到 context.obainStyledAttributes和context.getTheme().obainStyledAttributes是其實一樣的。

下面來仔細說說這個方法:

我們可以看到

      public final TypedArray obtainStyledAttributes(AttributeSet set, @StyleableRes int[] attrs) {return getTheme().obtainStyledAttributes(set, attrs, 0,0);}  

最終是調用的是這個

    public TypedArray obtainStyledAttributes(AttributeSet set,@StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);}

我們就來說一說這個方法簡單來說這個方法就是返回一個TypedArray對象(理解為用來存放屬性值的數組),里面的參數
set:一個和xml中的標簽關聯的存放屬性的集合,int[] 就是我們要在xml中讀取的屬性。

defStyleAttr:當前主題中的一個屬性,其中包含對為TypedArray提供默認值的樣式資源的引用。可以為0以不尋找默認值。

defStyleRes:是具體的style資源。為TypedArray提供默認值的樣式資源的資源標識符,僅當defStyleAttr為0或在主題中找不到時才使用。 可以為0以不尋找默認值。

這么說起來可能有點迷糊,來一個例子保證你立馬領悟!

首先我在attrs中定義一組屬性

圖片myview1定義屬性

其中的 attr_defStyle 屬性名,就是我定義的defStyleAttr用obtainStyledAttributes中作為參數。

然后自己定義style和Theme

Theme

圖片 stylemy

我在上面的注釋中已經寫得很清楚了,就不多解釋了。

然后再自定義View

圖片自定義view

其中第一個構造方法一般就是Java代碼中new 控件的使用,第二個構造方法就是在解析xml中控件生成view的時候調用了。

可以看到我在 第二個構造方法中是這樣寫的
this(context, attrs, R.attr.attr_defStyle);
其中 R.attr.attr_defStyle 就是定義的 defStyleAttr,在自己定義的Theme中給它附了值(這樣就解釋了前面說的,它是當前主題中的一個屬性,包含了對style(style_attr_defStyleAttr)的引用)

R.style.style_defStyleRes就很好解釋了,就是一個style資源引用。

再來看看布局頁面

xml布局文件

在布局文件中給它設置了text1屬性,和style,我們來看一看程序運行的結果

默認屬性全部全了

看到這個運行結果就得出結論了,關于屬性的取值是由順序的

1.優先取在布局中給定的值
2.在布局中設置的style中的值
3.從defStyleAttr和defStyleRes中取值,注意如果 defStyleAttr有值,則不再去defStyleResult中的值,就算defStyleAttr有的屬性沒有賦值。(具體看上面的打印結果)
4.Theme中設置的屬性

注意 defStyleAttr的值一定要在Theme中設置才有效果,就拿上面的例子說,如果你沒有在Theme中給R.attr.attr_defStyle賦值,而是直接在布局文件中賦值,這樣做是沒有效果的。

做了上面的介紹,我們再來看看系統是怎么做的,隨便看一個button控件

button構造方法

我們看到 button 的構造方法的defStyleAttr傳的是com.android.internal.R.attr.buttonStyle屬性,這個屬性我們在系統的attr中找到

buttonstyle

這就是系統定義的默認屬性buttonStyle

我們再來看看系統Theme是怎么給它附的值

buttonTheme

這里給了一個指引,指向了一個style

buttonstyle1

所以我們的button就在不同的主題中有了默認的樣式。看看系統的定義是不是和我們定義的很相像啊!
現在清楚了嗎?建議還是多看看源碼。

小知識點

<style name="MyStyle" parent="Widget.Button"><item name="background">@drawable/btn_default_holo_light</item><item name="textAppearance">?attr/textAppearanceMediumInverse</item><item name="textColor">@color/primary_text_holo_light</item><item name="minHeight">48dip</item><item name="minWidth">64dip</item>
</style>

其中parent可以理解為 MyStyle 繼承自 Widget.Button這種繼承一般是繼承系統的,而自己繼承自己的style則是

<style name = "MyStyle.H"><item -----></item>
</style>

是的這里使用. 表示H 繼承自MyStyle

好了關于Attr的介紹就到這里,本來想一篇文章全部介紹完,結果寫著寫著就寫多了,主要是考慮到許多基礎問題,想要大家都能看的懂就寫多了。剩下的style和theme估計篇幅也很大。寫起來發現牽扯的知識點太多了,什么都想給大家介紹一下。

歡迎大家關注我的微信公眾號,和我交流分享

水平有限有什么問題可以指正批評

這里寫圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451978.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451978.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451978.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

D. Relatively Prime Graph

Lets call an undirected graph G(V,E)G(V,E) relatively prime if and only if for each edge (v,u)∈E(v,u)∈E GCD(v,u)1GCD(v,u)1 (the greatest common divisor of vv and uu is 11). If there is no edge between some pair of vertices vv and uu then the value of GC…

解決 : org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯&#xff1a; org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.tanj.mapper.SendDeta…

網絡爬蟲--19.【Scrapy-Redis實戰】分布式爬蟲爬取房天下--環境準備

文章目錄0. 思路一. 虛擬機Ubuntu0中安裝Redis二. 虛擬機Ubuntu1中安裝Redis三. Windows服務器上安裝Redis四. 安裝cmder五. 安裝RedisDesktopManager六. 修改Windows中的配置文件redis.windows.conf七. Ubuntu連接Windows上 的Redis服務器-----------------------------------…

開發人員,請愛護你的身體

最近一周身體極度不適&#xff0c;口腔潰瘍、嗓子痛、感冒咳嗽、發燒&#xff0c;統統來了一個遍&#xff0c;非常痛苦。所以最近一直關注有關于軟件開發人員的身體健康問題的網站、文章。 看了許多文章&#xff0c;在結合自己在這一周之內痛苦的感受&#xff0c;所以才寫這樣…

tkinter中scale拖拉改變值控件(十一)

scale拖拉改變值控件 使用戶通過拖拽改變值 簡單的實現&#xff1a; 1 import tkinter2 3 wuya tkinter.Tk() 4 wuya.title("wuya") 5 wuya.geometry("300x2001020") 6 7 8 # 創建對象 9 scale1 tkinter.Scale(wuya, from_0, to100) 10 scale1.pac…

vue+elementUI開發實踐問題總結

最近公司項目采用vue&#xff0c;實行前后端分離開發&#xff0c;采用element-ui框架&#xff0c;對于項目中遇到的問題進行記錄&#xff0c;便于日后查詢。 vueelementui怎樣點擊table中的單元格觸發事件&#xff1f;官方文檔是采用的cell-click方式。實際項目中需要在不同的t…

Socket的getInputStream()方法

Socket的getInputStream()方法可以獲得網絡連接輸入&#xff0c;同時返回一個InputStream實例 。

計算機圖形學理論(4):緩沖區

本系列根據國外一個圖形小哥的講解為本&#xff0c;整合互聯網的一些資料&#xff0c;結合自己的一些理解。 什么是緩沖區&#xff1f; 緩沖區是保存某些數據的臨時存儲空間。 為什么我們需要緩沖區&#xff1f;原因很簡單&#xff0c;當數據量很大時&#xff0c;因為計算機無…

解決:Every derived table must have its own alias

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯&#xff1a; com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Every derived table must have its own alias 解決&…

網絡爬蟲--20.【Scrapy-Redis實戰】分布式爬蟲獲取房天下--代碼實現

文章目錄一. 案例介紹二.創建項目三. settings.py配置四. 詳細代碼五. 部署1. windows環境下生成requirements.txt文件2. xshell連接ubuntu服務器并安裝依賴環境3. 修改部分代碼4. 上傳代碼至服務器并運行一. 案例介紹 爬取房天下&#xff08;https://www1.fang.com/&#xff…

同一臺電腦安裝python2python3

【安裝之前&#xff0c;先了解一下概念】 python是什么&#xff1f; Python是一種面向對象的解釋型計算機程序設計語言&#xff0c;由荷蘭人Guido van Rossum于1989年發明&#xff0c;第一個公開發行版發行于1991年。 Python是純粹的自由軟件&#xff0c; 源代碼和解釋器CPytho…

程序員的常見健康問題

其實這些問題不僅見于程序員&#xff0c;其他長期經常坐在電腦前的職場人士&#xff08;比如&#xff1a;網絡編輯、站長等&#xff09;&#xff0c;都會有其中的某些健康問題。希望從事這些行業的朋友&#xff0c;對自己的健康問題&#xff0c;予以重視。以下是全文。 我最近…

Java中BufferedReader和InputStreamReader

BufferedReader 類BufferedReader 由Reader類擴展而來&#xff0c;提供通用的緩沖方式文本讀取&#xff0c;而且提供了很實用的readLine&#xff0c;讀取一個文本行&#xff0c;從字符輸入流中讀取文本&#xff0c;緩沖各個字符&#xff0c;從而提供字符、數組和行的高效讀取。…

網絡爬蟲--21.Scrapy知識點總結

文章目錄一. Scrapy簡介二. Scrapy架構圖三. Scrapy框架模塊功能四. 安裝和文檔五. 創建項目六. 創建爬蟲一. Scrapy簡介 二. Scrapy架構圖 三. Scrapy框架模塊功能 四. 安裝和文檔 中文文檔&#xff1a;https://scrapy-chs.readthedocs.io/zh_CN/latest/intro/tutorial.html …

Spring 定時任務的幾種實現

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 近日項目開發中需要執行一些定時任務&#xff0c;比如需要在每天凌晨時候&#xff0c;分析一次前一天的日志信息&#xff0c;借此機會整…

trie樹(字典樹)

trie樹學習 學習trie樹 轉載于:https://www.cnblogs.com/cjoierljl/p/9317023.html

Vue 教程第四篇—— Vue 實例化時基本屬性

實例元素 el 實例元素指的是 Vue 實例化時編譯的容器元素&#xff0c;或者說是 Vue 作用的元素容器 <div id"app"></div> var vm new Vue({el: #app}) 也可以為實例元素指定其它選擇器 <div class"app"></div> var vm new Vue({…

Ubuntu將在明年推出平板及手機系統

4月26日下午消息&#xff0c;知名Linux廠商Canonical今天正式發布Ubuntu 12.04版開源操作系統。Ubuntu中國首席代表于立強透露&#xff0c;針對平板電腦的Ubuntu操作系統將在明年推出。 Ubuntu 12.04版開源操作系統發布 Ubuntu操作系統是一款開源操作系統&#xff0c;主要與OE…

scrapy框架異常--no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates)

解決方法&#xff1a; https://blog.csdn.net/qq_40176258/article/details/86527568 https://blog.csdn.net/weixin_39946931/article/details/88390797 謝謝博主分享&#xff01;