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而已:
webhosting24决定从7月1日开始对日本机房的VPS进行NVMe和流量大升级,几乎是翻倍了硬盘和流量,当然前提是价格依旧不变。目前来看,国内过去走的是NTT直连,服务器托管机房应该是CDN77*(也就是datapacket.com),加上高性能平台(AMD Ryzen 9 3900X+NVMe),这样的日本VPS还是有相当大的性价比的。官方网站:https://www.webhosting...
提速啦的来历提速啦是 网站 本着“良心 便宜 稳定”的初衷 为小白用户避免被坑提速啦的市场定位提速啦主要代理市场稳定速度的云服务器产品,避免新手购买云服务器的时候众多商家不知道如何选择,妮妮云就帮你选择好了产品,无需承担购买风险,不用担心出现被跑路 被诈骗的情况。提速啦的售后保证提速啦退款 通过于合作商的友好协商,云服务器提供3天内全额退款,超过3天不退款 物理机部分支持当天全额退款提速啦提现 充...
酷锐云是一家2019年开业的国人主机商家,商家为企业运营,主要销售主VPS服务器,提供挂机宝和云服务器,机房有美国CERA、中国香港安畅和电信,CERA为CN2 GIA线路,提供单机10G+天机盾防御,提供美国原生IP,支持媒体流解锁,商家的套餐价格非常美丽,CERA机房月付20元起,香港安畅机房10M带宽月付25元,有需要的朋友可以入手试试。酷锐云自开业以来一直有着良好的产品稳定性及服务态度,支...
declare styleable为你推荐
sliderMFC中Slider Control 的使用RFI怎么下载rfi???qq实名注册请问手机QQ上实名认证怎么弄?aftereffectaftereffect和premiere这两种后期软件有什么区别对于熟悉PS的人那个更容易学习实数的定义什么是实数?实数的概念是什么赵锡成著名的美籍华人有哪些软件群发有谁用过微信能群发的软件吗?在哪买的?snoopy官网SNOOPY护肤品究竟是国内生产的吗?在哪生产的?3d规则福彩3d有几种玩法 详细介绍一下微信备份通讯录在哪微信6.3.6通讯录备份在哪
vps试用 怎样注册域名 到期域名查询 金万维动态域名 骨干网 sugarhosts hawkhost优惠码 java主机 便宜建站 php探针 彩虹ip 卡巴斯基试用版 双12 双11促销 iptables ddos是什么 电脑显示屏不亮但是主机已开机 国内云主机 56折扣网 灵动鬼影实录 更多