转载请注明出处:http://www.cnblogs.com/kross/p/3458068.html

最近在做一些UI,很蠢很蠢的重复写了很多代码,比如一个自定义的UI Tab,由一个ImageView和一个TextView构成,如果不自定义属性的话,就需要单独new出几个Tab,然后分别给它们设置Drawable和Text。如果能使用XML属性的话,就直接在XML文件中就可以给Tab设置好Drawable和Text。Java中就可以少些几行代码。

网上看了好多例子,大部分内容都是大同小异,(可能是因为各种转载的原因吧)。有很多细节都没有提及到。自己也是琢磨了半天才弄通。

自定义XML属性,就是可以方便的给自己定义的控件,添加自定义的属性,能快捷的给控件赋状态,赋属性。

关于自定义控件,请参考我的这篇博客:《探究Android中通过继承ViewGroup自定义控件的原理》http://www.cnblogs.com/kross/p/3378395.html

自定义控件需要如下几步:

1.自定义控件

2.自定义属性

3.在布局文件中使用自定义控件和自定义属性

自定义控件,就直接写一个现在主流的Tab控件,上面一个图片,下面一行Text组成的控件,通过继承LinearLayout来实现。代码如下:

/res/layout/tab.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageview_tab_icon"
android:layout_width="match_parent"
android:layout_height="48dp"
android:src="@drawable/ic_launcher"/>
<TextView
android:id="@+id/textview_tab_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="KKKKKKKK"/>
</LinearLayout>

/src/view/MyTab.java  //注意这里的包名是view

package view;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import com.kross.customattr.R; public class MyTab extends LinearLayout { private static final String TAG = "MyTab"; private ImageView iv = null;
private TextView tv = null; public MyTab(Context context, AttributeSet attrs) {
super(context, attrs); LayoutInflater.from(context).inflate(R.layout.tab, this, true);
iv = (ImageView)this.findViewById(R.id.imageview_tab_icon);
tv = (TextView)this.findViewById(R.id.textview_tab_text); iv.setImageResource(R.drawable.home);
tv.setText("aaaaa"); }
}

OK,这样自定义控件就完成了,需要注意的是,看好这个MyTab的包名是view。

接下来,我们要自定义XML属性

/res/values目录下建一个attr.xml文件。里面写如下代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTab">
<attr name="tab_icon" format="reference"/>
<attr name="tab_name" format="reference"/>
</declare-styleable>
</resources>

这里需要注意的是:

declare-styleable的name要和自定义的类名一样,(刚刚我们建了一个MyTab类,这里也必须是MyTab)

里面的attr name就是属性的名字了,跟layout_width一样,format有好几种不同的值:string , integer , dimension , reference , color , enum.

当format是enum,枚举类型的时候,里面的要写成这个样子:

<attr name="testEnum">
<enum name="fill_parent" value="-1"/>
<enum name="wrap_content" value="-2"/>
</attr>

自定义属性完成后,可以看看R.java文件的变化。

然后,我们需要给MyTab类中添加一些处理自定义属性的代码,代码更新为如下:

package view;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import com.kross.customattr.R; public class MyTab extends LinearLayout { private static final String TAG = "MyTab"; private ImageView iv = null;
private TextView tv = null; public MyTab(Context context, AttributeSet attrs) {
super(context, attrs); LayoutInflater.from(context).inflate(R.layout.tab, this, true);
iv = (ImageView)this.findViewById(R.id.imageview_tab_icon);
tv = (TextView)this.findViewById(R.id.textview_tab_text); iv.setImageResource(R.drawable.home);
tv.setText("aaaaa"); TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.MyTab);
int count = attrArray.getIndexCount();
for (int i = 0; i < count; i++) {
int attrName = attrArray.getIndex(i);
switch (attrName) {
case R.styleable.MyTab_tab_icon:
iv.setImageResource(attrArray.getResourceId(R.styleable.MyTab_tab_icon, R.drawable.ic_launcher));
break;
case R.styleable.MyTab_tab_name:
tv.setText(attrArray.getString(R.styleable.MyTab_tab_name));
break;
}
}
attrArray.recycle(); }
}

最后一步,我们就是在布局文件中使用它

看如下代码:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" /> <view.MyTab
android:layout_width="match_parent"
android:layout_height="wrap_content"
tab_icon="@drawable/ic_launcher"
/>
</LinearLayout>

这样写是不起作用的,网上很多地方都说,要加上命名空间注意LinearLayout里面新增的命名空间

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:kross="http://schemas.android.com/apk/res/view"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" /> <view.MyTab
android:layout_width="match_parent"
android:layout_height="wrap_content"
kross:tab_icon="@drawable/ic_launcher"
/>
</LinearLayout>

给LinearLayout加上命名空间,并给tab_icon属性前也加上命名空间,但eclipse就报错了:error: No resource identifier found for attribute 'tab_icon' in package 'view'

在下研究了半天,终于发现问题所在,这个命名空间必须要和manifest文件中的package属性是一样的值,这也就意味着:自定义控件的类必须要放到项目自动创建的包里面,比如我这个例子,manifest文件中package的值是com.kross.customattr,MainActivity所在的位置就是com.kross.customattr,我们需要把MyTab类,放到com.kross.customattr中,然后吧activity_main.xml里面的命名空间改成如下就OK了:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:kross="http://schemas.android.com/apk/res/com.kross.customattr"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" /> <com.kross.customattr.MyTab
android:layout_width="match_parent"
android:layout_height="wrap_content"
kross:tab_icon="@drawable/ic_launcher"
/>
</LinearLayout>

这样就可以运行了,但把自定义控件放到activity一起会觉得很蛋疼,貌似这是一个bug,请参考这里http://code.google.com/p/android/issues/detail?id=9656

貌似2010年就提出了,但现在也没有修复。

转载请注明出处:http://www.cnblogs.com/kross/p/3458068.html

Android自定义XML属性以及遇到的命名空间的问题的更多相关文章

  1. Android自定义XML属性

    <?xml version="1.0" encoding="utf-8"?> <resources> <declare-style ...

  2. Android--应用开发3(Android layout XML属性)

    Android layout XML属性 转载:http://www.cnblogs.com/playing/archive/2011/04/07/2008620.html Layout对于迅速的搭建 ...

  3. android自定义视图属性(atts.xml,TypedArray)学习

    是一个用于存放恢复obtainStyledAttributes(AttributeSet, int[], int, int)或 obtainAttributes(AttributeSet, int[] ...

  4. android 自定义View属性

    在android开发过程中,用到系统的View时候可以通过XML来定义一些View的属性.比如ImageView:   android:src  和android:scaleType为ImageVie ...

  5. android AndroidManifest.xml 属性详细解析

    一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了package中暴露的组件(activiti ...

  6. android自定义view属性

    第一种 /MainActivity/res/values/attrs.xml <?xml version="1.0" encoding="utf-8"?& ...

  7. 【Android UI】Android Layout XML属性

    Layout对于迅速的搭建界面和提高界面在不同分辨率的屏幕上的适应性具有很大的作用.这里简要介绍Android的Layout和研究一下它的实现. Android有Layout:FrameLayout, ...

  8. Android Layout XML属性

    转载自并做少量添加:http://www.cnblogs.com/playing/archive/2011/04/07/2008620.html Layout对于迅速的搭建界面和提高界面在不同分辨率的 ...

  9. android shape.xml 属性详解

    转载源:http://blog.csdn.net/harvic880925/article/details/41850723 一.简单使用 刚开始,就先不讲一堆标签的意义及用法,先简单看看shape标 ...

随机推荐

  1. hive错误排查一:hive中执行 drop table命令卡住,删除表不成功

    起因 公司用的AWS EMR上的hive,突然不能删除表了. 经过 分析来看,估计是元数据那块出了问题.从元数据入手,元数据存在mysql的hive数据库中 直接使用hive配置文件hive-site ...

  2. python学习笔记(三):numpy基础

    Counter函数可以对列表中数据进行统计每一个有多少种 most_common(10)可以提取前十位 from collections import Counter a = ['q','q','w' ...

  3. 20155202 《Java程序设计》实验三(敏捷开发与XP实践)实验报告

    20155202 <Java程序设计>实验三(敏捷开发与XP实践)实验报告 代码托管 实验内容 XP基础 XP核心实践 相关工具 实验要求 1.没有Linux基础的同学建议先学习<L ...

  4. [BZOJ4444][SCOI2015]国旗计划-[ST表]

    Description 传送门 Solution 说真的这道题在场上没做出来的我必定是脑子有洞.. 我们用st表记录以某个位置开始,派了1<<j个战士能到达的最远位置. 由于边境线是一圈, ...

  5. 质造未来,首届腾讯WeTest技术交流开放日成功举办

    WeTest 导读 北京时间12月21日下午1点整,2018年度腾讯WeTest技术交流开放日在上海举办.盛大.巨人.电魂.bilibili.方趣等十余家来自不同优秀企业的测试技术负责人均来到现场,共 ...

  6. Python中的解决中文字符编码的问题

    python3中str默认为Unicode的编码格式 python2中str默认为bytes类型的编码格式 Unicode是一32位编码格式,不适合用来传输和存储,所以必须转换成utf-8,gbk等等 ...

  7. oss上传文件0字节

    最近使用oss上传文件,不同项目中使用的版本也不同,之前的都能正常上传,最近因需要添加ObjectMetaData属性,扩展了一个方法,发现上传的文件始终是0字节的,最终跟源码发现conntentLe ...

  8. python 的入门

    时光匆匆,大一的时间过的很快,从大一上学期学的c开始,就感觉出c的结构很复杂,但是不可否认,学习c和汇编等涉及到系统底层知识才会有可能开发出属于自己知识产权的东西,然而,python以其简约性,丰富的 ...

  9. 第一篇:一天学会MongoDB数据库之Python操作

    本文仅仅学习使用,转自:https://www.cnblogs.com/suoning/p/6759367.html#3682005 里面新增了如果用用Python代码进行增删改查 什么是MongoD ...

  10. jquery on函数和prop与attr区别

    一.jquery on()方法 1.语法 2.例子 $(document).ready(function(){ $("p").on("click",functi ...