declare styleable从源码中浅析Android中怎么利用attrs和styles定义控件

declare styleable  时间:2022-02-27  阅读:()

从源码中浅析Android中怎么利用attrs和styles定义控件

1.attrs.xml: 我们知道Android的源码中有attrs.xml这个文件,这个文件实际上定义了所有的控件的属性,就是我们在布局文件中设置的各类属性 你可以找到attrs.xml这个文件,打开它,全选,右键->Show In->OutLine。可以看到整个文件的解构 我们大概可以看出里面是Android中的各种属性的声明,比如textStyle这个属性是这样定义的: Java代码 那么现在你知道,我们在写android:textStyle的时候为什么会出现normal,bold和italic这3个东西了吧,就是定义在这个地方。 再看看textColor: Java代码 format的意思是说:这个textColor可以以两种方式设置,要么是关联一个值,要么是直接设置一个颜色的RGB值,这个不难理解,因为我们可以平时也这样做过。 也就是说我们平时在布局文件中所使用的各类控件的属性都定义在这里面,那么这个文件,除了定义这些属性外还定义了各种具体的组件,比如TextView,Button,SeekBar等所具有的各种特有的属性 比如SeekBar: Java代码 也许你会问SeekBar的background,等属性怎么没有看到?这是因为Android中几乎所有的组件都是从View中继承下来的,SeekBar自然也不例外,而background这个属性几乎每个控件都有,因此被定义到了View中,你可以在declare-styleable:View中找到它。 总结下,也就是说attrs.xml这个文件定义了布局文件中的各种属性attr:***,以及每种控件特有的属性declare-styleable:*** 2.styles.xml: 刚才的attrs.xml定义的是组件的属性,现在要说的style则是针对这些属性所设置的值,一些默认的值。 这个是SeekBar的样式,我们可以看到,这里面设置了一个SeekBar的默认的样式,即为attrs.xml文件中的各种属性设置初始值 Java代码 这个是Button的样式: Java代码 有了属性和值,但是这些东西是如何关联到一起的呢?它们如何被android的framework层所识别呢? 3.组件的源码 我们看下TextView的源码: Java代码 public TextView(Context context) { this(context, null); }//这个构造器用来给用户调用,比如new TextView(this); public TextView(Context context, AttributeSet attrs) { this(context, attrs,.android.internal.R.attr.textViewStyle); } public TextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle);//为用户自定义的TextView设置默认的style mText = ""; //设置画笔 mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); mTextPaint.density = getResources().getDisplayMetrics().density; mTextPaint.setCompatibilityScaling( getResources().getCompatibilityInfo().applicationScale); mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHighlightPaint.setCompatibilityScaling( getResources().getCompatibilityInfo().applicationScale); mMovement = getDefaultMovementMethod(); mTransformation = null; //attrs中包含了这个TextView控件在布局文件中定义的属性,比如android:background,android:layout_width等 /.android.internal.R.styleable.TextView中包含了TextView中的针对attrs中的属性的默认的值 //也就是说这个地方能够将布局文件中设置的属性获取出来,保存到一个TypeArray中,为这个控件初始化各个属性 TypedArray a = context.obtainStyledAttributes( attrs,.android.internal.R.styleable.TextView, defStyle, 0); int textColorHighlight = 0; ColorStateList textColor = null; ColorStateList textColorHint = null; ColorStateList textColorLink = null; int textSize = 15; int typefaceIndex = -1; int styleIndex = -1; /* * Look the appearance up without checking first if it exists because * almost every TextView has one and it greatly simplifies the logic * to be able to parse the appearance first and then let specific tags * for this View override it. */ TypedArray appearance = null; //TextView_textAppearance不太了解为什么要这样做?难道是为了设置TextView的一些默认的属性? int ap = .android.internal.R.styleable.TextView_textAppearance, -1); if (ap != -1) { appearance = context.obtainStyledAttributes(ap, .android.internal.R.styleable. TextAppearance); } if (appearance != null) { int n = appearance.getIndexCount(); for (int i = 0; i < n; i++) { int attr = appearance.getIndex(i); switch (attr) { .android.internal.R.styleable.TextAppearance_textColorHighlight: textColorHighlight = appearance.getColor(attr, textColorHighlight); break; .android.internal.R.styleable.TextAppearance_textColor: textColor = appearance.getColorStateList(attr); break; .android.internal.R.styleable.TextAppearance_textColorHint: textColorHint = appearance.getColorStateList(attr); break; .android.internal.R.styleable.TextAppearance_textColorLink: textColorLink = appearance.getColorStateList(attr); break; .android.internal.R.styleable.TextAppearance_textSize: textSize = appearance.getDimensionPixelSize(attr, textSize); break; .android.internal.R.styleable.TextAppearance_typeface: typefaceIndex = appearance.getInt(attr, -1); break; .android.internal.R.styleable.TextAppearance_textStyle: styleIndex = appearance.getInt(attr, -1); break; } } appearance.recycle(); } //各类属性 boolean editable = getDefaultEditable(); CharSequence inputMethod = null; int numeric = 0; CharSequence digits = null; boolean phone = false; boolean autotext = false; int autocap = -1; int buffertype = 0; boolean selectallonfocus = false; Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null; int drawablePadding = 0; int ellipsize = -1; boolean singleLine = false; int maxlength = -1; CharSequence text = ""; CharSequence hint = null; int shadowcolor = 0; float dx = 0, dy = 0, r = 0; boolean password = false; int inputType = EditorInfo.TYPE_NULL; int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); //通过switch语句将用户设置的,以及默认的属性读取出来并初始化 switch (attr) { .android.internal.R.styleable.TextView_editable: editable = a.getBoolean(attr, editable); break; .android.internal.R.styleable.TextView_inputMethod: inputMethod = a.getText(attr); break; .android.internal.R.styleable.TextView_numeric: numeric = a.getInt(attr, numeric); break; //更多的case语句... .android.internal.R.styleable.TextView_textSize: textSize = a.getDimensionPixelSize(attr, textSize);//设置当前用户所设置的字体大小 break; .android.internal.R.styleable.TextView_typeface: typefaceIndex = a.getInt(attr, typefaceIndex); break; //更多的case语句... } 通过上面的代码大概可以知道,每个组件基本都有3个构造器,其中只传递一个Context上下文的那个构造器一般用来在java代码中实例化使用。 比如你可以 Java代码 = new TextView(context); 来实例化一个组件。 最终调用的是第3个构造器 Java代码 public TextView(Context context, AttributeSet attrs, int defStyle) 在这个构造器中为你设置了默认的属性attrs和值styles。关键不在这里,而是后面通过使用下面的代码 Java代码 TypedArray a = context.obtainStyledAttributes( attrs,.android.internal.R.styleable.TextView, defStyle, 0); 来将属性和值获取出来,放到一个TypeArray中,然后再利用一个switch语句将里面的值取出来。再利用这些值来初始化各个属性。这个View最终利用这些属性将这个控件绘制出来。 如果你在布局文件中定义的一个View的话,那么你定义的值,会被传递给构造器中的attrs和styles。也是利用同样的方式来获取出你定义的值,并根据你定义的值来绘制你想要的控件。 再比如其实Button和EditText都是继承自TextView。看上去两个控件似乎差异很大,其实不然。Button的源码其实相比TextView变化的只是style而已:

搬瓦工香港 PCCW 机房已免费迁移升级至香港 CN2 GIA 机房

搬瓦工最新优惠码优惠码:BWH3HYATVBJW,节约6.58%,全场通用!搬瓦工关闭香港 PCCW 机房通知下面提炼一下邮件的关键信息,原文在最后面。香港 CN2 GIA 机房自从 2020 年上线以来,网络性能大幅提升,所有新订单都默认部署在香港 CN2 GIA 机房;目前可以免费迁移到香港 CN2 GIA 机房,在 KiwiVM 控制面板选择 HKHK_8 机房进行迁移即可,迁移会改变 IP...

BlueHost 周年庆典 - 美国/香港虚拟主机 美国SSD VPS低至月32元

我们对于BlueHost主机商还是比较熟悉的,早年我们还是全民使用虚拟主机的时候,大部分的外贸主机都会用到BlueHost无限虚拟主机方案,那时候他们商家只有一款虚拟主机方案。目前,商家国际款和国内款是有差异营销的,BlueHost国内有提供香港、美国、印度和欧洲机房。包括有提供虚拟主机、VPS和独立服务器。现在,BlueHost 商家周年活动,全场五折优惠。我们看看这次的活动有哪些值得选择的。 ...

3元/首月香港便宜vps究竟是什么货。

便宜的香港vps多少钱?现在国外VPS主机的价格已经很便宜了,美国VPS主机最低一个月只要十几元,但同样免备案的香港VPS价格贵不贵呢?或者说便宜的香港VPS多少钱?香港vps主机价格要比美国机房的贵一些,但比国内的又便宜不少,所以目前情况是同等配置下,美国VPS比香港的便宜,香港VPS比国内(指大陆地区)的便宜。目前,最便宜香港vps低至3元/首月、18元/月起,今天云服务器网(www.yunt...

declare styleable为你推荐
ripperRipper是个什么病毒blastpncbi blastp怎么设库战棋类有谁介绍几个战棋类的游戏?rbo在么?那个RBO出招表到底怎么回事 斩舰刀怎么用exe文件打不开所有exe文件不能打开scanf返回值scanf 的返回值密码设置开机密码怎么设定?torrent文件怎么打开BT下载后的文件怎么打开数据管理制度求一份工时定量管理制度团购网源码最近看到团购挺火的,我也想做一个,请大家推荐个稳定的团购网站源码?
budgetvm 堪萨斯服务器 hostgator 韩国俄罗斯 themeforest 圣迭戈 国外空间服务商 免费博客空间 论坛空间 最好看的qq空间 绍兴高防 什么是刀片服务器 hostker 网络空间租赁 四核服务器 卡巴斯基是免费的吗 cloudlink 域名与空间 空间登录首页 台湾google 更多