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

Hostodo,美国独立日特价优惠,四款特价VPS云服务器7折,KVM虚拟架构,NVMe阵列,1核512M内存1Gbps带宽3T月流量,13.99美元/月,赠送DirectAdmin授权

Hostodo近日发布了美国独立日优惠促销活动,主要推送了四款特价优惠便宜的VPS云服务器产品,基于KVM虚拟架构,NVMe阵列,1Gbps带宽,默认分配一个IPv4+/64 IPv6,采用solusvm管理,赠送收费版DirectAdmin授权,服务有效期内均有效,大致约为7折优惠,独立日活动时间不定,活动机型售罄为止,有需要的朋友可以尝试一下。Hostodo怎么样?Hostodo服务器好不好?...

GigsGigsCloud(年付26美元)国际线路美国VPS主机

已经有一段时间没有听到Gigsgigscloud服务商的信息,这不今天看到商家有新增一款国际版线路的美国VPS主机,年付也是比较便宜的只需要26美元。线路上是接入Cogentco、NTT、AN2YIX以及其他亚洲Peering。这款方案的VPS主机默认的配置是1Gbps带宽,比较神奇的需要等待手工人工开通激活,不是立即开通的。我们看看这款服务器在哪里选择看到套餐。内存CPUSSD流量价格购买地址1...

95IDC香港特价物理机服务器月付299元起,5个ip/BGP+CN2线路;美国CERA服务器仅499元/月起

95idc是一家香港公司,主要产品香港GIA线路沙田CN2线路独服,美国CERA高防服务器,日本CN2直连服务器,即日起,购买香港/日本云主机,在今年3月份,95IDC推出来一款香港物理机/香港多ip站群服务器,BGP+CN2线路终身7折,月付350元起。不过今天,推荐一个价格更美的香港物理机,5个ip,BGP+CN2线路,月付299元起,有需要的,可以关注一下。95idc优惠码:优惠码:596J...

declare styleable为你推荐
we7俗称杨铁鹞子这种植物的学名wizardry霍格沃茨学校在哪里?mapsource怎么用mapsource制作地球化学航迹图系统登录界面今天电脑开机显示windows登录页面??要求用户名和密马?spinmaster谁发明的汪汪队立大功这个动画片tplink端口映射Tp-link路由器怎么设置端口映射 内网端口映射无线呼叫系统什么是无线呼叫器?网站维护收费网站建设及维护需要多少钱?网站维护收费网页制作与维护,费用从零开始学android从零开始学android需要多久
美国vps租用 linuxvps 火山主机 host1plus godaddy优惠券 服务器cpu性能排行 免费个人博客 debian源 网页背景图片 蜗牛魔方 腾讯云分析 刀片服务器是什么 卡巴斯基试用版 中国电信测速网 hkt 最漂亮的qq空间 空间登入 酸酸乳 双十二促销 开心online 更多