View绘制体系(三)——AttributeSet与TypedArray详解

article/2025/10/7 3:02:06

View绘制体系(三)——AttributeSet与TypedArray详解


前言

上篇博客中讲了LayoutInflater.inflate机制,其中提到了AttributeSetXmlPullParser两个接口,这里我们来详细的了解一下Android中提供的AttributeSet接口和它与XmlPullParser的区别,以及如何使用TypedArray获取AttributeSet中对应的属性。


AttributeSet

AttributeSet是xml文件中元素属性的一个集合。其中提供了各种Api,供我们从已编译好的xml文件获取属性值,如getAttributeIntValuegetAttributeBooleanValuegetAttributeFloatValue等,会返回对应类型的属性值,传入的参数一般有两种形式,如下:

  • getAttributeXXXValue(int index, XXX defaultValue)根据对应属性的索引获取对应的属性值,index取值范围在0~count-1之间,找不到返回defaultValue
  • getAttributeXXXValue(String namespace, String attribute, XXX defaultValue)根据指定命名空间的属性名获取对应的属性值,找不到返回defaultValue

AttributeSet与XmlPullParser

我们现在知道了AttributeSet也是获取xml文件中属性值用的接口,那么它和XmlPullParser有什么关联和区别呢?

我们先看下下面这张类图:

XmlPullParser与AttributeSet

XmlPullParser和AttributeSet都能从Xml文件中获取数据,它们的相同点为:

  • 它们有一些重复的方法,如getAttributeNamegetAttributeValue等。

区别在于:

  • AttributeSet提供了额外的一系列getAttributeXXXValue的方法(如getAttributeIntValue),这些方法能返回对应XXX的类型值(如int值),而XmlPullParser获取属性值只能通过getAttributeValue方法,返回值只能是String类型
  • AttributeSet接口从XmlPullParser接口中只保留了必要的方法,去除了next()等方法,并且新增了一些Android独有的方法,可以说AttributeSet是Android独有的用来获取xml文件属性的一个接口

需要注意的是,在Android中,对于AttributeSet接口和XmlPullParser接口,其实现都是结合已有的编译好的xml资源,这些资源是编译时经过aapt生成的高度优化的资源,而不是通过pull方式解析原有的Xml字符串。这与我们常见的一般的XmlPullParser接口的实现机制(kXml,WbXml等)不同。

我们从类图中可以看到实现类有两个,分别是ParserXmlPullAttributes,我们可以看下XmlPullAttributes的具体实现:

class XmlPullAttributes implements AttributeSet {XmlPullParser mParser;public XmlPullAttributes(XmlPullParser parser) {mParser = parser;}public int getAttributeCount() {return mParser.getAttributeCount();}public String getAttributeNamespace (int index) {return mParser.getAttributeNamespace(index);}public String getAttributeName(int index) {return mParser.getAttributeName(index);}public String getAttributeValue(int index) {return mParser.getAttributeValue(index);}public String getAttributeValue(String namespace, String name) {return mParser.getAttributeValue(namespace, name);}public String getPositionDescription() {return mParser.getPositionDescription();}public int getAttributeNameResource(int index) {return 0;}public int getAttributeListValue(String namespace, String attribute,String[] options, int defaultValue) {return XmlUtils.convertValueToList(getAttributeValue(namespace, attribute), options, defaultValue);}//...其余AttributeSet中的接口都是类似getAttributeListValue通过XmlUtils转换类型来实现的}

可以看到XmlPullAttributes对于AttributeSet中和XmlPullParser相同的接口都是通过内部的XmlPullParser变量来实现的。

XmlPullParser还可以通过以下方式生成对应的AttributeSet:

public static AttributeSet asAttributeSet(XmlPullParser parser) {return (parser instanceof AttributeSet)? (AttributeSet) parser: new XmlPullAttributes(parser);
}

TypedArray

然而,我们很少用到AttributeSet类提供的方法来获取它的属性,常常都是通过Theme.obtainStyledAttributes方法来获取其中的属性的,方法如下:

public TypedArray obtainStyledAttributes(AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) 

获取到TypedArray之后,再去调用TypedArray的Api来处理。

为什么不直接用AttributeSet来解析属性值呢?

我们可以看下面这个xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="@dimen/w_50dp"android:layout_height="@dimen/w_50dp"android:orientation="vertical"/>

我们通过AttributeSet直接去获取属性的话:

final XmlResourceParser parser = getResources().getLayout(R.layout.ll);
int type;
while ((type = parser.getEventType()) != XmlPullParser.START_TAG&& type != XmlPullParser.END_DOCUMENT) {parser.next();
}
int count = parser.getAttributeCount();
Log.d(TAG, "count: " + parser.getAttributeCount());AttributeSet attributeSet = Xml.asAttributeSet(parser);for (int i = 0; i < count; i++) {String name = attributeSet.getAttributeName(i);String value = attributeSet.getAttributeValue(i);Log.d(TAG, "attribute: " + name + "   value: " + value);
}int resourceId = attributeSet.getAttributeResourceValue("http://schemas.android.com/apk/res/android", "layout_height", 0);
float dimension = getResources().getDimension(resourceId);
Log.d(TAG, "layout_height: " + dimension);

得到的结果如下:

count: 3
attribute: orientation   value: 1
attribute: layout_width   value: @2131034226
attribute: layout_height   value: @2131034226
layout_height: 150.0  #得到的是px

可以看到如果直接使用AttributeSet来获取属性值有以下缺点:

  • 通过索引index获取元素属性颇为麻烦,而且对于属性的顺序不熟悉的人很难将将index和属性值一一对应;而通过命名空间来获取,又要必须填入android的命名空间"http://schemas.android.com/apk/res/android",编写起来都是不太方便的
  • 对于"@String/hello_world"这一类通过索引资源文件获取属性值的,直接通过getAttributeValue获得的只是资源的id,虽然可以通过getAttributeResourceValue获取到id后,通过Resources类来获取对应的属性值,但是这样会有多步的操作。

我们来看看使用TypedArray是如何获取属性值的。TypedArray是一个存放属性值数组的一个容器,通常通过如下方式来获得TypedArray的:

Resources.Theme.obtainStyledAttributes(AttributeSet set,@StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes)

我们来分别看下每个参数的含义:

  • AttributeSet set表示从AttributeSet中挑选属性,可以为空
  • int[] attrs表示你想挑选的属性,你想得到哪些属性,你就可以将其写到这个int数组中
  • int defStyleAttr表示从defStyleAttr中挑选属性,可以为空
  • int defStyleRes表示从defStyleRes中挑选属性,可以为空

这里我们先来演示下从AttributeSet中挑选属性:

TypedArray a = obtainStyledAttributes(attributeSet,new int[] { android.R.attr.layout_width, android.R.attr.layout_height});
float width = a.getDimension(0, 0f); //第一个参数表示在int数组中的索引,第二个参数为默认值
Log.d(TAG, "typedarray layout_width: " + width);
float height = a.getDimension(1, 0f); //第一个参数表示在int数组中的索引,第二个参数为默认值
Log.d(TAG, "typedarray layout_width: " + height);

可以得到对应的值:

typedarray layout_width: 150.0
typedarray layout_width: 150.0

TypedArray提供了各种Api,如getIntegergetStringgetDimension等方法来获取属性值,这些方法都需要传入对应属性名在obtainStyledAttributes中的int数组的位置索引。

对于TypedArray的分析,这里就只讲从AttributeSet中挑选属性的用法,从defStyleAttr和defStyleRes中挑选属性的用法详见[View绘制体系(四)——TypedArray与自定义属性]。

ps:对于AttributeSet与TypedArray的分析就到这里,后续将会介绍TypedArray与自定义属性的相关内容,敬请关注!


http://chatgpt.dhexx.cn/article/FEw0WgIL.shtml

相关文章

Android自定义View(三)自定义属性AttributeSet

自定义View的时候通常需要提供一些自定义属性&#xff0c;自定义属性非常简单&#xff0c;只需要在res资源目录的values目录下创建一个attrs.xml的属性定义文件&#xff0c;然后在该文件中定义相应的属性&#xff0c;并在自定义View的构造函数中获取并设置自定义属性的默认值即…

web搜索框的制作(必应)

前两天没事突然对搜索来了兴趣&#xff0c;我一直在想搜索框中我们输入一些字或者字母&#xff0c;为何下面就会有一些自动补齐的相关搜索&#xff0c;比如我在搜索输入框中输入一个字母e&#xff0c;下面就会出现饿了么&#xff0c;e租宝&#xff0c;ems等相关的搜索链接。然后…

html怎么调搜索框宽高,百度站内搜索css:输入框宽度及样式自定义

近日网站使用了百度站内搜索api&#xff0c;目的是为了提高站内搜索的速度&#xff0c;减轻查询站内数据库带来的服务器压力。 不过在使用百度站内搜索api(生效范围&#xff1a;*webkaka.com/*)后发现一个问题&#xff0c;不同的频道模版造成排版不合适的后果&#xff0c;如搜索…

织梦手机站站内搜索

今天在做手机网站发现一个问题&#xff0c;当在手机是使用搜索功能时马上就跳转到电脑端网站去了&#xff0c;在手机上无法使用。在网上找半天没有找到解决的办法&#xff0c;后来自己想通了&#xff0c;下面告诉大家怎么样简单的实现这个功能&#xff01;我的手机站是在m/这个…

基于 Elasticsearch 的站内搜索引擎实战

站内搜索&#xff0c;可以认为是针对一个网站特性内容的搜索功能。由于内容、格式可控&#xff0c;站内搜索比全网搜索的实现要简单很多。 简书这个网站本身自带一个搜索&#xff0c;但是缺乏针对个人文章的搜索&#xff0c;所以本文的实战内容是解决这个痛点。 代码在 https…

使用swiftype实现站内搜索

本人博客opiece.me&#xff0c;欢迎访问。 前言 首先&#xff0c;以下的内容是基于最新的swifytpe的教程&#xff0c;应该是2.0.0。 站内搜索顾名思义就是将范围限定在你的网站内&#xff0c;以此范围进行关键字搜索。 常见的站内搜索是google和baidu的&#xff0c;但是现在…

Compass实战 站内搜索

今天早上打算对这两天学习的Lucene以及Compass总结一下,想来想去,还是写个小项目来验证最好了。于是就有了今天的这篇文章。难易程度适合对于Compass或者Lucene刚入门的童鞋,大牛看到后望轻喷 :-) 项目预览项目需求项目目录核心处理 发帖部分查询部分总结项目预览 项目需求 …

html中的搜索

目录 hello&#x1f604; form表单&#x1f349; form的语法&#x1f34a; from的属性&#x1f34a; 提交&#xff1f;重置&#xff1f;&#x1f34a; 表单按钮&#xff08;html&#xff09;&#x1f50d; JavaScript提交表单&#x1f50d; JavaScript重置表单&#x1f…

必应(Bing)的站内搜索 site:<域名> <搜索内容>

最近在备考OCP&#xff0c;发现有一个网站的题库很好&#xff0c;就是www.examtopics.com&#xff0c;有很多Oracle的考题&#xff0c;都是在这里面搜到的&#xff0c;而且每道题都有人讨论。 为了加快搜索速度&#xff0c;提高精度&#xff0c;可以用Bing在这个网站内搜索&am…

百度站内搜索使用教程

最近做了一个博客CMS网站&#xff0c;用到了百度站内搜索&#xff0c;做一些必要的笔记&#xff0c;一来是对自己学习的知识的巩固&#xff0c;二来对有同样问题的人有参考作用 文章目录 一 使自己的网站被百度收录二 获取百度站内搜索代码三 总结 声明一下&#xff0c;我本人很…

利用免费的必应 Bing 自定义搜索打造站内全文搜索

简介 百度的站内搜索不做了&#xff0c;唉&#xff0c;果然免费的不永久。我们看看 Bing 的&#xff0c;每个月有 1000 次免费的调用 bing search api 的次数。不同客户可以多申请几个就行了。 申请入口&#xff1a; https://www.customsearch.ai&#xff0c;官方简介页面官方…

html百度站内搜索代码,网站添加百度站内搜索的教程

zblog博客程序中可以在侧边栏中添加搜索功能&#xff0c;但是让人郁闷的是如果没针对搜索使用搜索插件&#xff0c;那情况简直让人抓狂&#xff0c;还好我们可以使用百度的站内搜索功能&#xff0c;一方面可以节省网站的资源&#xff0c;另一方面可以增加百度的收率几率。 关于…

站内搜索

使用“site:”或者“domain:”来实现站内搜索 如果你想在一个特定的网站上来进行搜索&#xff0c;在众多庞大的信息流中找到你想要的信息&#xff0c; 在上篇中(http://blog.csdn.net/liunian02050328/article/details/8220379)介绍在java编程的环境下实现站内搜索&#xff0c;…

计算机网络中的ping什么意思,PING命令是什么?PING使用方法和参数详解

PING命令是用来检查本机于网络上的电脑是否正常通信的一个命令&#xff0c;作为一个网站的管理员、单位的网管这也是一个必会的命令。 因为网络中所有的电脑都有一个单独不会重复的IP地址&#xff0c;我们使用PING命令给目标IP地址发送一个数据包&#xff0c;对方就要返回一个同…

常见的ping命令

1.ping 延时和丢包 开始--运行---输入cmd---输入ping IP&#xff08;IP为所要ping的服务器的IP&#xff09; 常与 -t 选项结合使用 ctrlc结束 延时主要看时间列 看时间得数值和波动 丢包 ---出现请求超时 2.追踪路由 tracert IP 注意&#xff1a; 追路由 --一般追3次 …

ping命令常见参数使用详解

winR 输入cmd 回车 进入命令窗口 输入ping baidu.com 回车可以查看网络连接。 ping [-t]参数是用来不断的ping对方主机&#xff0c;直到手动停止&#xff0c;使用ctrlc。Windows默认是四次停止。 [-l]&#xff08;-L&#xff09;参数用来设定数据包的大小的&#xff0c;在默认的…

Linux 常用ping命令详解

一、用法 Usage: ping [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface][-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos][-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option][-w deadline] [-W timeout] [hop1 ...] destination二…

CentOS7里ping命令详解

ping 功能简述&#xff1a;Linux系统的ping命令是常用的网络命令&#xff0c;它通常用来测试与目标主机的连通性&#xff0c;我们经常会说“ping一下某机器&#xff0c;看是不是开着”、不能打开网页时会说“你先ping网关地址192.168.1.1试试”。它通过发送ICMPECHO_REQUEST数…

ping命令

在网络中ping是一个十分强大的TCP/IP工具。它的作用主要为&#xff1a; &#xff08;1&#xff09;用来检测网络的连通情况和分析网络速度&#xff1b;&#xff08;2&#xff09;根据域名得到服务器IP&#xff1b;&#xff08;3&#xff09;根据ping返回的TTL值来判断对方所使…

Ping命令的用法

ping基本使用详解 在网络中ping是一个十分强大的TCP/IP工具。它的作用主要为&#xff1a; &#xff08;1&#xff09;用来检测网络的连通情况和分析网络速度&#xff1b; &#xff08;2&#xff09;根据域名得到服务器IP&#xff1b; &#xff08;3&#xff09;根据ping返回…