彻底搞清楚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.mzph.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…

网络爬虫--19.【Scrapy-Redis实战】分布式爬虫爬取房天下--环境准备

文章目录0. 思路一. 虚拟机Ubuntu0中安装Redis二. 虚拟机Ubuntu1中安装Redis三. Windows服务器上安装Redis四. 安装cmder五. 安装RedisDesktopManager六. 修改Windows中的配置文件redis.windows.conf七. Ubuntu连接Windows上 的Redis服务器-----------------------------------…

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…

计算机图形学理论(4):缓冲区

本系列根据国外一个图形小哥的讲解为本&#xff0c;整合互联网的一些资料&#xff0c;结合自己的一些理解。 什么是缓冲区&#xff1f; 缓冲区是保存某些数据的临时存储空间。 为什么我们需要缓冲区&#xff1f;原因很简单&#xff0c;当数据量很大时&#xff0c;因为计算机无…

网络爬虫--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;予以重视。以下是全文。 我最近…

网络爬虫--21.Scrapy知识点总结

文章目录一. Scrapy简介二. Scrapy架构图三. Scrapy框架模块功能四. 安装和文档五. 创建项目六. 创建爬虫一. Scrapy简介 二. Scrapy架构图 三. Scrapy框架模块功能 四. 安装和文档 中文文档&#xff1a;https://scrapy-chs.readthedocs.io/zh_CN/latest/intro/tutorial.html …

Ubuntu将在明年推出平板及手机系统

4月26日下午消息&#xff0c;知名Linux厂商Canonical今天正式发布Ubuntu 12.04版开源操作系统。Ubuntu中国首席代表于立强透露&#xff0c;针对平板电脑的Ubuntu操作系统将在明年推出。 Ubuntu 12.04版开源操作系统发布 Ubuntu操作系统是一款开源操作系统&#xff0c;主要与OE…

Android Studio 超级简单的打包生成apk

为什么要打包&#xff1a; apk文件就是一个包&#xff0c;打包就是要生成apk文件&#xff0c;有了apk别人才能安装使用。打包分debug版和release包&#xff0c;通常所说的打包指生成release版的apk&#xff0c;release版的apk会比debug版的小&#xff0c;release版的还会进行混…

推荐16款最棒的Visual Studio插件

Visual Studio是微软公司推出的开发环境&#xff0c;Visual Studio可以用来创建Windows平台下的Windows应用程序和网络应用程序&#xff0c;也可以用来创建网络服务、智能设备应用程序和Office插件。 本文介绍16款最棒的Visual Studio扩展&#xff1a; 1. DevColor Extension…

网络爬虫--22.【CrawlSpider实战】实现微信小程序社区爬虫

文章目录一. CrawlSpider二. CrawlSpider案例1. 目录结构2. wxapp_spider.py3. items.py4. pipelines.py5. settings.py6. start.py三. 重点总结一. CrawlSpider 现实情况下&#xff0c;我们需要对满足某个特定条件的url进行爬取&#xff0c;这时候就可以通过CrawlSpider完成。…

怎么安装Scrapy框架以及安装时出现的一系列错误(win7 64位 python3 pycharm)

因为要学习爬虫&#xff0c;就打算安装Scrapy框架&#xff0c;以下是我安装该模块的步骤&#xff0c;适合于刚入门的小白&#xff1a; 一、打开pycharm&#xff0c;依次点击File---->setting---->Project----->Project Interpreter&#xff0c;打开后&#xff0c;可以…

xpath-helper: 谷歌浏览器安装xpath helper 插件

1.下载文件xpath-helper.crx xpath链接&#xff1a;https://pan.baidu.com/s/1dFgzBSd 密码&#xff1a;zwvb&#xff0c;感谢这位网友&#xff0c;我从这拿到了 2.在Google浏览器里边找到这个“扩展程序”选项菜单即可。 3.然后就会进入到扩展插件的界面了,把下载好的离线插件…

网络爬虫--23.动态网页数据抓取

文章目录一. Ajax二. 获取Ajax数据的方式三. seleniumchromedriver获取动态数据四. selenium基本操作一. Ajax 二. 获取Ajax数据的方式 三. seleniumchromedriver获取动态数据 selenium文档&#xff1a;https://selenium-python.readthedocs.io/installation.html 四. sele…

gcc g++安装

2019独角兽企业重金招聘Python工程师标准>>> 安装之前要卸载掉老版本的gcc、g sudo apt-get remove gccgcc-xx #可能有多个版本&#xff0c;都要删掉 sudo apt-get remove g sudo apt-get install gcc 安装g编译器&#xff0c;可以通过命令 sudo apt-get installb…

网络爬虫--24.【selenium实战】实现拉勾网爬虫之--分析接口获取数据

文章目录一. 思路概述二. 分析数据接口三. 详细代码一. 思路概述 1.拉勾网采用Ajax技术&#xff0c;加载网页时会向后端发送Ajax异步请求&#xff0c;因此首先找到数据接口&#xff1b; 2.后端会返回json的数据&#xff0c;分析数据&#xff0c;找到单个招聘对应的positionId…

bzoj 1999: [Noip2007]Core树网的核【树的直径+单调队列】

我要懒死了&#xff0c;所以依然是lyd的课件截图 注意是min{max(max(d[uk]),dis(u1,ui),dis(uj,un))}&#xff0c;每次都从这三个的max里取min #include<iostream> #include<cstdio> using namespace std; const int N500005; int n,m,h[N],cnt,d[N],s,t,mx,f[N],a…

Java 设计模式-【单例模式】

单例解决了什么问题&#xff1a;为了节约系统资源&#xff0c;有时需要确保系统中某个类只有唯一一个实例&#xff0c;当这个唯一实例创建成功之后&#xff0c;我们无法再创建一个同类型的其他对象&#xff0c;所有的操作都只能基于这个唯一实例。为了确保对象的唯一性&#xf…