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而已:

SoftShellWeb:台湾(台北)VPS年付49美元起,荷兰VPS年付24美元起

SoftShellWeb是一家2019年成立的国外主机商,商家在英格兰注册,提供的产品包括虚拟主机和VPS,其中VPS基于KVM架构,采用SSD硬盘,提供IPv4+IPv6,可选美国(圣何塞)、荷兰(阿姆斯特丹)和台湾(台北)等机房。商家近期推出台湾和荷兰年付特价VPS主机,其中台湾VPS最低年付49美元,荷兰VPS年付24美元起。台湾VPSCPU:1core内存:2GB硬盘:20GB SSD流量...

美国cera机房 2核4G 19.9元/月 宿主机 E5 2696v2x2 512G

美国特价云服务器 2核4G 19.9元杭州王小玉网络科技有限公司成立于2020是拥有IDC ISP资质的正规公司,这次推荐的美国云服务器也是商家主打产品,有点在于稳定 速度 数据安全。企业级数据安全保障,支持异地灾备,数据安全系数达到了100%安全级别,是国内唯一一家美国云服务器拥有这个安全级别的商家。E5 2696v2x2 2核 4G内存 20G系统盘 10G数据盘 20M带宽 100G流量 1...

PQ.hosting全线9折,1Gbps带宽不限流量VPS/€3/月,全球11大机房可选

Hostadvice主机目录对我们的服务进行了测试,然后给PQ.hosting颁发了十大WordPress托管奖。为此,宣布PQ.Hosting将在一周内进行折扣优惠,购买和续订虚拟服务器使用优惠码:Hostadvice ,全部优惠10%。PQ.hosting,国外商家,成天于2019年,正规公司,是全球互联网注册商协会 RIPE 的成员。主要是因为提供1Gbps带宽、不限流量的基于KVM虚拟的V...

declare styleable为你推荐
免费qq号谁有免费的QQ号和密码可以用的?cs躲猫猫CS1.6捉迷藏具体的玩法?密码设置怎么设置开机密码?vrrp配置我准备做一个关于MSTP的配置,但是不知道如何去做,拓扑如下武汉教育云平台武汉天喻教育科技有限公司怎么样?传奇私服教程怎样开传奇SF?我要具体详细的步骤印度it印度的IT业刷荣誉怎么刷荣誉啊cad2012序列号和密钥autocad 2012激活码pscs5序列号PS AI CS5 每次登陆都要填写序列号,有什么方法可以解决?
免费com域名申请 dreamhost 全球付 国外服务器网站 idc评测网 xen 网站实时监控 中国电信测网速 免费网页空间 东莞idc 视频服务器是什么 丽萨 ebay注册 永久免费空间 电信宽带测速软件 如何登陆阿里云邮箱 1美元 免备案cdn加速 云销售系统 accountsuspended 更多