android中如何获取xml界面里的非自定义属性
获取自定义属性大家都很熟悉了,就不多说了(定义declare-styleable,context.obtainStyledAttributes巴拉巴拉...)
下面我们说一下怎么获取非自定义的属性,比如android:entries,android:gravity等等,上面的方式照着套是行不通了,因为你无法取得android.R.styleable里面的东西,下面是我试出来的几种方法:
1. 遍历AttributeSet,基本可以把所有xml里的属性取出来,但是有一点,取出来的值要能使用,需要经过一定处理,具体代码如下:
//find entries
int count = attrs.getAttributeCount();
for (int i = 0; i < count; i++) {
if ("entries".equals(attrs.getAttributeName(i))) {
int resid = attrs.getAttributeResourceValue(i, 0);
if (resid > 0) {
String[] entries = context.getResources().getStringArray(resid);
if (entries != null) {
//get gravity
int g = -1;
for (int j = 0; j < count; j++) {
if ("gravity".equals(attrs.getAttributeName(j))) {
g = j;
break;
}
}
final int gravity = attrs.getAttributeIntValue(g, Gravity.CENTER);
//create adapter
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(context, R.layout.item_spinner_top, R.id.text, entries) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = ButterKnife.findById(view, R.id.text);
text.setTextColor(textColor);
text.setTextSize(DimenUtils.px2dp(textSize));
text.setGravity(gravity);
return view;
} @Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View dropDownView = super.getDropDownView(position, convertView, parent);
TextView text = ButterKnife.findById(dropDownView, R.id.text);
text.setTextColor(dropdownTextColor);
text.setTextSize(DimenUtils.px2dp(textSize));
text.setGravity(gravity);
return dropDownView;
}
};
adapter.setDropDownViewResource(R.layout.item_spinner_dropdown);
setAdapter(adapter);
}
}
break;
}
}
2. 还是使用context.obtainStyledAttributes,数组可以从android.R.attr里面取(不需要styleable了),处理起来跟以前差不多,很好用,推荐
private static final int[] RX_SPINNER_OVERRIDE_ATTRS = {
android.R.attr.entries,
android.R.attr.gravity
}; a = context.obtainStyledAttributes(attrs,RX_SPINNER_OVERRIDE_ATTRS);
if (a.hasValue(0)){
CharSequence[] entries = a.getTextArray(0);
final int gravity = a.getInt(1,Gravity.CENTER);
//create adapter
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(context, R.layout.item_spinner_top, R.id.text, entries) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = ButterKnife.findById(view, R.id.text);
text.setTextColor(textColor);
text.setTextSize(DimenUtils.px2dp(textSize));
text.setGravity(gravity);
return view;
} @Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View dropDownView = super.getDropDownView(position, convertView, parent);
TextView text = ButterKnife.findById(dropDownView, R.id.text);
text.setTextColor(dropdownTextColor);
text.setTextSize(DimenUtils.px2dp(textSize));
text.setGravity(gravity);
return dropDownView;
}
};
adapter.setDropDownViewResource(R.layout.item_spinner_dropdown);
setAdapter(adapter);
}
a.recycle();
在使用中无意发现另外一个问题,tint相关属性即使设置了,在5.0以下也是拿不到的,究其原因应该是这个是api level 21才引入的,低于这个的机器上被忽略了,那么要同时兼容高低版本的话,可以使用v7包里的tint属性,android.support.v7.appcompact.R.attr.backgroundTint等,使用的时候就不要用android:backgroundTint了,改用app:backgroundTint即可。
9月17日更新
抱歉,上面的代码没有经过详细测试,实际上只能拿到entries的值,拿不到gravity的值,我也很奇怪,百思不得其解,照理说应该是同样的模式,追踪代码追到最后是一个native方法...
然后我去stackoverflow上提了问题(http://stackoverflow.com/questions/32602982/can-get-entries-but-not-gravity/),尝试让国外大神帮我看下,然而并没有人回答,今天花了一天时间找了半天原因,总算是找到了,记录一下。
gravity不能获取的原因是,v7包里,它被重新定义了!
<declare-styleable name="Spinner"><attr format="reference" name="prompt"/><attr format="enum" name="spinnerMode"><enum name="dialog" value="0"/><enum name="dropdown" value="1"/></attr><attr name="android:dropDownSelector"/><attr name="android:popupBackground"/><attr name="android:dropDownVerticalOffset"/><attr name="android:dropDownHorizontalOffset"/><attr name="android:dropDownWidth"/><attr format="reference" name="popupPromptView"/><attr name="android:gravity"/><attr format="boolean" name="disableChildrenWhenDisabled"/><attr name="android:background"/></declare-styleable>
注意里面重新定义了一些属性(比如<attr name="android:gravity"/>),可能由于这个原因,上面的获取方法失效了.
解决办法也很简单,从v7包里取就可以了!v7包是可以访问styleable的,这样就能使用常规方法来取了!
a = context.obtainStyledAttributes(attrs,android.support.v7.appcompat.R.styleable.Spinner);
final int gravity = a.getInt(android.support.v7.appcompat.R.styleable.Spinner_android_gravity,Gravity.CENTER);
a.recycle();
ok,测试通过!
更进一步
通过v7兼容包里的写法,我们知道了,通过定义<attr name="android:gravity"/>是可以重定义android原生属性的(不知道重定义在这里用得准不准确,反正是这么个意思,大家理解就可以了)
那么假如你有个自定义组件,想使用类似android:gravity,android:xxx之类的属性,实现一些其他功能或者可定义性,那么完全可以自己在attr里面定义,只需要写上name就行了,不需要设置format,还有枚举什么的一大堆,全部是自动继承的!
然后xml里就还是跟以前一样设置,android:xxx=yyy,java里面可以跟自定义属性一样取,简单方便!下面上个例子
<declare-styleable name="RxSpinner">
<attr name="text_size" format="dimension"/>
<attr name="text_color" format="color" />
<attr name="dropdown_text_color" format="color"/>
<attr name="android:gravity" />
<attr name="android:entries" />
</declare-styleable>
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RxSpinner);
final int textColor = a.getColor(R.styleable.RxSpinner_text_color, context.getResources().getColor(R.color.gray_dark));
final float textSize = a.getDimension(R.styleable.RxSpinner_text_size, context.getResources().getDimension(R.dimen.text_normal));
final int dropdownTextColor = a.getColor(R.styleable.RxSpinner_dropdown_text_color, context.getResources().getColor(R.color.gray_dark));
final int gravity = a.getInt(R.styleable.RxSpinner_android_gravity,Gravity.CENTER); //get android:gravity
final CharSequence[] entries = a.getTextArray(R.styleable.RxSpinner_android_entries); //get android:entries
a.recycle();
怎么样,是不是很好用,蛤蛤。
折腾这么多天,总算弄清楚了,找到了一种简洁的写法。其实一开始我就在想,有没有什么办法,让自定义组件的属性直接继承,后面走了不少弯路,看了v7源码才知道,可以这么写,原来就是加一个android命名空间的事,源码还是很有参考价值的。
android中如何获取xml界面里的非自定义属性的更多相关文章
- Android开发之获取xml文件的输入流对象
介绍两种Android开发中获取xml文件的输入流对象 第一种:通过assets目录获取 1.首先是在Project下app/src/main目录下创建一个assets文件夹,将需要获取的xml文件放 ...
- Android中pull解析XML文件的简单使用
首先,android中解析XML文件有三种方式,dom,sax,pull 这里先讲pull,稍候会说SAX和DOM pull是一种事件驱动的xml解析方式,不需要解析整个文档,返回的值是数值型,是推荐 ...
- android中通过自定义xml实现你需要的shape效果 xml属性配置
在Android开发过程中,经常需要改变控件的默认样式, 那么通常会使用多个图片来解决.不过这种方式可能需要多个图片,比如一个按钮,需要点击时的式样图片,默认的式样图片,然后在写一个selector的 ...
- Android中写入读取XML
获取XML文件的基本思路是,通过getResources().getXml()获的XML原始文件,得到XmlResourceParser对象,通过该对象来判断是文档的开头还是结尾,是某个标签的开始还是 ...
- Android中如何取消调转界面后EditText默认获取聚焦问题
最近在做一个项目,当我点击跳转至一个带有EditText的界面后,模拟器中的软键盘会自动弹出,严重影响了用户体验.在网上找了资料,现总结如下. 我们知道,EditText有一个 android:foc ...
- 【Android】Android中如何取消调转界面后EditText默认获取聚焦问题
参考资料: https://www.cnblogs.com/dream-cichan/p/aaaa.html http://blog.csdn.net/u013703461/article/detai ...
- android中ContentProvider获取联系人 总结
35.内容提供者:ContentResolver 用内容提供者来获取联系人信息 35-1:权限 <!-- 对联系人的读.写权限 --> <uses-permission androi ...
- Android中Spanner获取选中内容和选中位置,根据位置选择对象
作为一名菜鸟,关于spanner获取选中的内容文字代码,网上后很多 但是根据给出的位置来自动选择对象,这个代码一直没找到 后来找人问了问,才知道就一句话的事,特意在这里记录下 array.xml X ...
- Android中findViewById()获取EditText 空指针问题
因为EditText editText = (EditText)layout.findViewById(R.id.input_content);是从Dialog对话框布局layout中寻找ID为inp ...
随机推荐
- ios 添加伪闪屏
self.window.rootViewController.view.alpha = ; UIImageView *splashImageView = [[UIImageView alloc]ini ...
- Python爬虫Scrapy框架入门(0)
想学习爬虫,又想了解python语言,有个python高手推荐我看看scrapy. scrapy是一个python爬虫框架,据说很灵活,网上介绍该框架的信息很多,此处不再赘述.专心记录我自己遇到的问题 ...
- MyBatis持久层框架使用总结
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis . 2 ...
- PHP探针
来自LNMP.org 探针p.php 代码: <?php error_reporting(0); //抑制所有错误信息 @header("content-Type: text/html ...
- Python 迭代器 & __iter__方法
转载来自: http://blog.csdn.net/bluebird_237/article/details/38894617 迭代器就是重复地做一些事情,可以简单的理解为循环,在python中实现 ...
- Asp.net导出Excel(HTML输出方法)
主要思路: 实例化Gridview,将值绑定后输出...(用烂了的方法) 贴上核心代码: public static void ExportToExcel(DataTable dataList, st ...
- C#中的Lambda表达式的演化过程
原文:http://www.cnblogs.com/zhaopei/p/5767631.html
- 浏览器-07 chromium 渲染1
Chromium 软件渲染 软件渲染就是利用CPU,根据一定的算法来计算生成网页的内容; Chromium都是用软件渲染的技术来完成页面的绘制工作(除非强行打开硬件加速绘制); 软件渲染基础和架构 R ...
- 浏览器-03 WebKit 渲染1
WebKit是一个渲染引擎,而不是一个浏览器; DOM是对HTML或者XML等文档的一种结构化表示方法,通过这种方式,用户可以通过提供标准的接口来访问页面中的任何元素的相关属性,并可对DOM进行相应的 ...
- 关于MFi认证你所必须要知道的事情
MFiLogo 前面我写了一篇文章<iOS App连接外设的几种方式>,其中EAP和NCM是都需要做MFi认证.对于苹果的MFI认证,对iOS开发的同学来说其实是一个比较陌生并且繁琐的to ...