xml里怎么使用这个自定义view xmleditview

Android UI设计之&三&自定义EditText,实现带清除功能的输入框
最近公司的产品在陆续做升级,上级领导给的任务是优化代码结构以及项目架构,力争把项目写的精巧简练,于是我们满工程找冗余...
我们都知道每一个项目基本上都是有登陆页的,在登陆页中肯定是少不了输入框了,当我们在输入框中输入数据后如果输入的内容不正确或者是错误的或者是想重新输入,如果嗯键盘上的删除键就得一个一个的去删除,这时候我们或许就想要是能有一个标记当点击了这个标记能把我们刚刚输入的内容清空就好了。这样可以极大的提升用户体验,就拿QQ的登陆来说吧,效果如下:
当点击密码框右侧的小×图标时输入的内容就都清空了,真的很方便,我之前在项目中也自定义过这种效果的输入框并且在项目中一直使用它,在此期间并没有发现什么Bug,之前的自定义结构如下:
实现方式是使用一个RelativeLayout,它包含了三个控件,两边是ImageView控件,中间是EditText控件,当点击右侧清除按钮后就可以清除输入框的内容了,但是最近在做产品优化的时候感觉之前写的这个自定义控件在代码量上来说有点浪费,明明Android的EditText有drawableLeft和drawableRight属性,为什么不去直接使用呢?于是用笔在草稿纸上画了画,花点时间又重新写了一个具有同样效果的输入框,并且在代码量上来说简化了不少。
好了,还是老规矩,先来看看项目结构吧:
工程中ClearEditText就是我又从新定义的带清除功能的输入框,主要是继承了EditText为了利用它的drawableLeft和drawableRight属性,那么赶紧看看它的实现吧
public class ClearEditText extends EditText implements TextWatcher,
OnFocusChangeListener {
* 左右两侧图片资源
private Drawable left,
* 是否获取焦点,默认没有焦点
private boolean hasFocus =
* 手指抬起时的X坐标
private int xUp = 0;
public ClearEditText(Context context) {
this(context, null);
public ClearEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.editTextStyle);
public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initWedgits();
* 初始化各组件
* @param attrs
private void initWedgits() {
// 获取drawableLeft图片,如果在布局文件中没有定义drawableLeft属性,则此值为空
left = getCompoundDrawables()[0];
// 获取drawableRight图片,如果在布局文件中没有定义drawableRight属性,则此值为空
right = getCompoundDrawables()[2];
initDatas();
} catch (Exception e) {
e.printStackTrace();
* 初始化数据
private void initDatas() {
// 第一次显示,隐藏删除图标
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
addListeners();
} catch (Exception e) {
e.printStackTrace();
* 添加事件监听
private void addListeners() {
setOnFocusChangeListener(this);
addTextChangedListener(this);
} catch (Exception e) {
e.printStackTrace();
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
public void onTextChanged(CharSequence s, int start, int before, int after) {
if (hasFocus) {
if (TextUtils.isEmpty(s)) {
// 如果为空,则不显示删除图标
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
// 如果非空,则要显示删除图标
if (null == right) {
right = getCompoundDrawables()[2];
setCompoundDrawablesWithIntrinsicBounds(left, null, right, null);
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 获取点击时手指抬起的X坐标
xUp = (int) event.getX();
// 当点击的坐标到当前输入框右侧的距离小于等于getCompoundPaddingRight()的距离时,则认为是点击了删除图标
// getCompoundPaddingRight()的说明:Returns the right padding of the view, plus space for the right Drawable if any.
if ((getWidth() - xUp) &= getCompoundPaddingRight()) {
if (!TextUtils.isEmpty(getText().toString())) {
setText(&&);
} catch (Exception e) {
e.printStackTrace();
return super.onTouchEvent(event);
public void afterTextChanged(Editable s) {
public void onFocusChange(View v, boolean hasFocus) {
this.hasFocus = hasF
} catch (Exception e) {
e.printStackTrace();
解释一下ClearEditText的执行顺序,它首先继承了EditText也就是说具有了EditText的所有功能,然后又实现了TextWatcher和OnFocusChangeListener接口,其中接口OnFocusChangeListener是用来监听当前输入框是否获取到焦点的,我们把当前输入框获取到的焦点的状态值赋给hasFocus成员变量,如果获取到了焦点则hasFocus的值为true,当在输入框中输入内容的时候会触发TextWatcher监听器,就会顺序执行beforeTextChanged,onTextChanged和afterTextChanged方法,而我们仅仅需要在onTextChanged方法中对输入框的值进行判断就行了,如果输入框框的值非空就显示清空按钮小图标否则不显示,设置图标隐藏和显示的方法就是直接调用setCompoundDrawablesWithIntrinsicBounds方法就行了,这个方法的具体使用就不详解了,大体就是说按照我们给定的图片尺寸把图片画到输入框的四个方向上,如果传入值为null就表示不绘制。
接下来就是对清空小图标进行监听了,我首先想到的是如果清空小图标是显示的,就给他设置事件监听比如onClickListener或者是onTouchListener,但是遗憾的是找了API并没有发现EditText提供对drawLeft或者是drawRight的事件监听,又来又打算自定义一个监听器但仔细想想又把代码复杂化了,其实EditText是间接继承View的而View中有个onTouchEvent方法,我们可以重写onTouchEvent方法并在它里边根据我们手指摁下或者是抬起的坐标进行判断,如果点击的位置到当前控件右侧的距离小于等于当前控件右侧小图标的宽度加上paddingRight的值,则我们可以直接认为是点击了清除小图标,就可以对当前控件进行清空操作了,幸好EditText给我们提供了一个我现在认为是非常实在的方法:getCompoundPaddingRight(),文档的解释就是:Returns
the right padding of the view, plus space for the right Drawable if any.它的值就是清空小图标的宽度加上paddingRight的值,呵呵,有了它就好办多了,(*^__^*) 嘻嘻……
好了,接下来我们来看看在布局文件中怎么使用它吧(其实很简单,就是和EditText的使用方法一样的,(*^__^*) 嘻嘻……)
&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout
xmlns:android=&http://schemas.android.com/apk/res/android&
android:orientation=&vertical&
android:layout_width=&fill_parent&
android:layout_height=&fill_parent&
android:background=&#ffffff&&
android:layout_width=&fill_parent&
android:layout_height=&wrap_content&
android:layout_margin=&10dip&
android:text=&@string/hello&
android:gravity=&center&
android:textSize=&20sp&
android:textColor=&#000000& /&
&com.llew.e.clear.view.wedgit.ClearEditText
android:id=&@+id/clearEditText&
android:layout_width=&fill_parent&
android:layout_height=&wrap_content&
android:layout_margin=&10dip&
android:paddingRight=&8dip&
android:paddingTop=&5dip&
android:paddingBottom=&5dip&
android:hint=&请输入QQ号码&
android:background=&@drawable/pay_widget_input&
android:drawableLeft=&@drawable/super_qq&
android:drawableRight=&@drawable/clear_normal_list& /&
&/LinearLayout&
就是写完整我们自定义的包名就行了,属性用的全是父类中的,再次感谢Java给我们提供的继承特性,呵呵,
在运行之前还是贴出来MainActivity代码吧,其实真的很简单:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
简单吧?创建工程的时候自动生成的,压根不用进行任何操作,呵呵
好了,我们运行一下,看看效果图吧O(∩_∩)O~
输入前:输入后:点击清除图标后:
呵呵,这种效果和之前自定义的一样,并且在代码量上来说却是比之前的减少了不少,高兴一下
好了,今天的自定义ClearEditText就讲到这里,感谢收看
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?随笔 - 10&
文章 - 5&评论 - 6&trackbacks - 0
作用:&1、对于一个没有被载入或者想要动态载入的界面, 都需要使用inflate来载入.&2、对于一个已经载入的Activity, 就可以使用实现了这个Activiyt的的findViewById方法来获得其中的界面元素.&
举例:定义了一个控件类CleanableEditText,实现在焦点变化时和输入内容发生变化时均要判断是否显示右边clean图标
   & 后台调用自定义控件的时候需要LayoutInflater来载入(见第三段代码)。
自定义控件:
package com.
import android.content.C
import android.graphics.drawable.D
import android.text.E
import android.text.TextW
import android.util.AttributeS
import android.view.MotionE
import android.view.V
import android.widget.EditT
* 在焦点变化时和输入内容发生变化时均要判断是否显示右边clean图标
public class CleanableEditText extends EditText {
private Drawable mRightD
private boolean isHasF
public CleanableEditText(Context context) {
super(context);
public CleanableEditText(Context context, AttributeSet attrs) {
super(context, attrs);
public CleanableEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
private void init(){
//getCompoundDrawables:
//Returns drawables for the left, top, right, and bottom borders.
Drawable [] drawables=this.getCompoundDrawables();
//取得right位置的Drawable
//即我们在布局文件中设置的android:drawableRight
mRightDrawable=drawables[2];
//设置焦点变化的监听
this.setOnFocusChangeListener(new FocusChangeListenerImpl());
//设置EditText文字变化的监听
this.addTextChangedListener(new TextWatcherImpl());
//初始化时让右边clean图标不可见
setClearDrawableVisible(false);
* 当手指抬起的位置在clean的图标的区域
* 我们将此视为进行清除操作
* getWidth():得到控件的宽度
* event.getX():抬起时的坐标(改坐标是相对于控件本身而言的)
* getTotalPaddingRight():clean的图标左边缘至控件右边缘的距离
* getPaddingRight():clean的图标右边缘至控件右边缘的距离
* getWidth() - getTotalPaddingRight()表示:
* 控件左边到clean的图标左边缘的区域
* getWidth() - getPaddingRight()表示:
* 控件左边到clean的图标右边缘的区域
* 所以这两者之间的区域刚好是clean的图标的区域
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
boolean isClean =(event.getX() & (getWidth() - getTotalPaddingRight()))&&
(event.getX() & (getWidth() - getPaddingRight()));
if (isClean) {
setText("");
return super.onTouchEvent(event);
private class FocusChangeListenerImpl implements OnFocusChangeListener{
public void onFocusChange(View v, boolean hasFocus) {
isHasFocus=hasF
if (isHasFocus) {
boolean isVisible=getText().toString().length()&=1;
setClearDrawableVisible(isVisible);
setClearDrawableVisible(false);
//当输入结束后判断是否显示右边clean的图标
private class TextWatcherImpl implements TextWatcher{
public void afterTextChanged(Editable s) {
boolean isVisible=getText().toString().length()&=1;
setClearDrawableVisible(isVisible);
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
public void onTextChanged(CharSequence s, int start, int before,int count) {
//隐藏或者显示右边clean的图标
protected void setClearDrawableVisible(boolean isVisible) {
Drawable rightD
if (isVisible) {
rightDrawable = mRightD
rightDrawable = null;
//使用代码设置该控件left, top, right, and bottom处的图标
setCompoundDrawables(getCompoundDrawables()[0],getCompoundDrawables()[1],
rightDrawable,getCompoundDrawables()[3]);
&com.utils.CleanableEditText
android:id="@+id/login_name"
android:layout_width="match_parent"
android:layout_height="@dimen/logineditview_hight"
android:layout_marginLeft="16dp"
android:hint="@string/user_name"
android:layout_toRightOf="@id/img_login_name"
android:background="@null"
android:singleLine="true"
android:imeOptions="actionNext"
android:drawableRight="@drawable/clean"
后台调用:
final View getView = LayoutInflater.from(this.getContext()).inflate(R.layout.login, null);
ed_loginCode = (CleanableEditText) getView.findViewById(R.id.login_name);
阅读(...) 评论()Posts - 162,
Articles - 0,
Comments - 1343
20:40 by Terry_龙, ... 阅读,
Android 自定义View 己经不是什么新鲜话题,Android Api提供了一大堆基础组件给我们,需要什么特定功能还需要我们继承它们然后定制更加丰富的功能。前面有篇文章也说过为自定义VIEW添加属性,但只是一笔带过,这里就拿这点来说说吧。
第一种添加属性的方法,之前我也是经常使用这种写法,代码如下:
package&com.terry.import&android.content.Cimport&android.util.AttributeSimport&android.widget.EditTimport&android.widget.LinearLimport&android.widget.TextVpublic&class&EditTextExt1&extends&LinearLayout&{&&&&private&String&Text&=&"";&&&&public&EditTextExt1(Context&context)&{&&&&&&&&this(context,&null);&&&&&&&&//&TODO&Auto-generated&constructor&stub&&&&}&&&&public&EditTextExt1(Context&context,&AttributeSet&attrs)&{&&&&&&&&super(context,&attrs);&&&&&&&&//&TODO&Auto-generated&constructor&stub&&&&&&&&int&resouceId&=&-<span style="color: #;&&&&&&&&TextView&tv&=&new&TextView(context);&&&&&&&&&EditText&et&=&new&EditText(context);&&&&&&&&resouceId&=&attrs.getAttributeResourceValue(null,&"Text",&<span style="color: #);&&&&&&&&if&(resouceId&&&<span style="color: #)&{&&&&&&&&&&&&Text&=&context.getResources().getText(resouceId).toString();&&&&&&&&}&else&{&&&&&&&&&&&&Text&=&"";&&&&&&&&}&&&&&&&&tv.setText(Text);&&&&&&&&addView(tv);&&&&&&&&addView(et,&new&LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,&&&&&&&&&&&&&&&&LayoutParams.WRAP_CONTENT));&&&&&&&&this.setGravity(LinearLayout.VERTICAL);&&&&}}
这种写法,简单明了,不需要额外XML的配置,就可以在我们的VIEW文件下使用。
以上代码通过构造函数中引入的AttributeSet 去查找XML布局的属性名称,然后找到它对应引用的资源ID去找值。使用也时分方便。所以一直以来我也是很喜欢这种写法。
如上,自定好VIEW文件就可以在XML布局下如此使用:
&com.terry.attrs.EditTextExt1&android:id="@+id/ss3"&&&&&&&&android:layout_width="wrap_content"&android:layout_height="wrap_content"&&&&&&&&Text="@string/app_name"&&&/com.terry.attrs.EditTextExt1&
&好了,这是第一种为VIEW注册属性的写法,比较简单就不多介绍。
下面是第二为VIEW注册属性的写法,这里也要重点说说第二种注册 属性的写法和使用要点,先看一下JAVA代码要如何编写:
package&com.terry.import&android.content.Cimport&android.content.res.TypedAimport&android.util.AttributeSimport&android.widget.EditTimport&android.widget.LinearLimport&android.widget.TextVpublic&class&EditTextExt&extends&LinearLayout&{&&&&public&EditTextExt(Context&context)&{&&&&&&&&this(context,&null);&&&&&&&&//&TODO&Auto-generated&constructor&stub&&&&}&&&&public&EditTextExt(Context&context,&AttributeSet&attrs)&{&&&&&&&&super(context,&attrs);&&&&&&&&//&TODO&Auto-generated&constructor&stub&&&&&&&&int&resouceId&=&-<span style="color: #;&&&&&&&&TypedArray&typeArray&=&context.obtainStyledAttributes(attrs,&&&&&&&&&&&&&&&&R.styleable.EditTextExt);&&&&&&&&TextView&tv&=&new&TextView(context);&&&&&&&&EditText&et&=&new&EditText(context);&&&&&&&&&&&&&&&&int&N&=&typeArray.getIndexCount();&&&&&&&&for&(int&i&=&<span style="color: #;&i&&&N;&i++)&{&&&&&&&&&&&&int&attr&=&typeArray.getIndex(i);&&&&&&&&&&&&switch&(attr)&{&&&&&&&&&&&&case&R.styleable.EditTextExt_Oriental:&&&&&&&&&&&&&&&&resouceId&=&typeArray.getInt(R.styleable.EditTextExt_Oriental,&&&&&&&&&&&&&&&&&&&&&&&&<span style="color: #);&&&&&&&&&&&&&&&&this.setOrientation(resouceId&==&<span style="color: #&?&LinearLayout.HORIZONTAL&&&&&&&&&&&&&&&&&&&&&&&&:&LinearLayout.VERTICAL);&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&case&R.styleable.EditTextExt_Text:&&&&&&&&&&&&&&&&resouceId&=&typeArray.getResourceId(&&&&&&&&&&&&&&&&&&&&&&&&R.styleable.EditTextExt_Text,&<span style="color: #);&&&&&&&&&&&&&&&&tv.setText(resouceId&&&<span style="color: #&?&typeArray.getResources().getText(&&&&&&&&&&&&&&&&&&&&&&&&resouceId)&:&typeArray&&&&&&&&&&&&&&&&&&&&&&&&.getString(R.styleable.EditTextExt_Text));&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&addView(tv);&&&&&&&&addView(et);&&&&&&&&typeArray.recycle();&&&&}}
如上代码,跟前面代码一样。还是用的一个EDITTEXT和TEXTVIEW做基础组件。下面我们一步步分析上面的代码:
&R.styleable.EditTextExt 代码的是一个attrs指向的一个declare-styleable 的标签,如下代码:
&?xml&version="1.0"&encoding="UTF-8"?&&resources&&&&&&declare-styleable&name="EditTextExt"&&&&&&&&&&attr&name="Text"&format="reference|string"&&/attr&&&&&&&&&&attr&name="Oriental"&&&&&&&&&&&&&&enum&name="Horizontal"&value="1"&&/enum&&&&&&&&&&&&&&enum&name="Vertical"&value="0"&&/enum&&&&&&&&&&/attr&&&&&&/declare-styleable&&/resources&
这个文件位于,values下的attrs.xml目录下面,我比较喜欢一个自定义View 对应一个declare-styleable标签。
Tip:一个自定义View 第一部分的代码,
TypedArray&typeArray&=&context.obtainStyledAttributes(attrs,&&&&&&&&&&&&&&&&R.styleable.EditTextExt);
指定为一个declare-styleable,而在declare-styleable 下的attr (即各属性)Android 的ADT 将会自动生成为declare-styleable的name 名字加上&#8220;_&#8221;加上对应attr(即属性名称)的名称,如上(EditTextExt_Text)我们要得到Text 就需要R.styleable.EditTextExt_Text,这一点的话可以看看R.java生成文件:
public&static&final&class&styleable&{&&&&&&&&/**&Attributes&that&can&be&used&with&a&EditTextExt.&&&&&&&&&&&&p&Includes&the&following&attributes:&/p&&&&&&&&&&&&&table&&&&&&&&&&&&&colgroup&align="left"&/&&&&&&&&&&&&&colgroup&align="left"&/&&&&&&&&&&&&&tr&&th&Attribute&/th&&th&Description&/th&&/tr&&&&&&&&&&&&&tr&&td&&code&{@link&#EditTextExt_Oriental&com.terry.attrs:Oriental}&/code&&/td&&td&&/td&&/tr&&&&&&&&&&&&&tr&&td&&code&{@link&#EditTextExt_Text&com.terry.attrs:Text}&/code&&/td&&td&&/td&&/tr&&&&&&&&&&&&&/table&&&&&&&&&&&&@see&#EditTextExt_Oriental&&&&&&&&&&&@see&#EditTextExt_Text&&&&&&&&&*/&&&&&&&&public&static&final&int[]&EditTextExt&=&{&&&&&&&&&&&&<span style="color: #x7f010000,&<span style="color: #x7f010001&&&&&&&&};&&&&&&&&/**&&&&&&&&&&&p&This&symbol&is&the&offset&where&the&{@link&com.terry.attrs.R.attr#Oriental}&&&&&&&&&&attribute's&value&can&be&found&in&the&{@link&#EditTextExt}&array.&&&&&&&&&&&p&Must&be&one&of&the&following&constant&values.&/p&&table&&colgroup&align="left"&/&&colgroup&align="left"&/&&colgroup&align="left"&/&&tr&&th&Constant&/th&&th&Value&/th&&th&Description&/th&&/tr&&tr&&td&&code&Horizontal&/code&&/td&&td&1&/td&&td&&/td&&/tr&&tr&&td&&code&Vertical&/code&&/td&&td&0&/td&&td&&/td&&/tr&&/table&&&&&&&&&&&@attr&name&android:Oriental&&&&&&&&*/&&&&&&&&public&static&final&int&EditTextExt_Oriental&=&<span style="color: #;&&&&&&&&/**&&&&&&&&&&&p&This&symbol&is&the&offset&where&the&{@link&com.terry.attrs.R.attr#Text}&&&&&&&&&&attribute's&value&can&be&found&in&the&{@link&#EditTextExt}&array.&&&&&&&&&&&p&May&be&a&reference&to&another&resource,&in&the&form&"&code&@[+][&i&package&/i&:]&i&type&/i&:&i&name&/i&&/code&"or&to&a&theme&attribute&in&the&form&"&code&?[&i&package&/i&:][&i&type&/i&:]&i&name&/i&&/code&".&p&May&be&a&string&value,&using&'\\;'&to&escape&characters&such&as&'\\n'&or&'\\uxxxx'&for&a&unicode&character.&&&&&&&&&&@attr&name&android:Text&&&&&&&&*/&&&&&&&&public&static&final&int&EditTextExt_Text&=&<span style="color: #;&&&&};
好了,上述的代码写完,我们要在XML布局如何使用呢?这个会跟Android 提供的基础组件的使用方法是一致的。首先,我们要为其提供一个引用包名如下:
xmlns:android="http://schemas.android.com/apk/res/android"&&&&xmlns:terry="http://schemas.android.com/apk/res/com.terry.attrs"
上面提供的是android 基础组件的包名,和我们自己组件的包名。
写好了包名。就可以像使用andriod 基础组件一样使用了,如下全部XML布局源码:
&?xml&version="1.0"&encoding="utf-8"?&&LinearLayout&xmlns:android="http://schemas.android.com/apk/res/android"&&&&xmlns:terry="http://schemas.android.com/apk/res/com.terry.attrs"&&&&android:orientation="vertical"&android:layout_width="fill_parent"&&&&android:layout_height="fill_parent"&&&&&&TextView&android:layout_width="fill_parent"&&&&&&&&android:layout_height="wrap_content"&android:text="@string/hello"&/&&&&&&com.terry.attrs.EditTextExt&android:id="@+id/ss"&&&&&&&&android:layout_width="fill_parent"&android:layout_height="wrap_content"&&&&&&&&terry:Text="fdsafda"&terry:Oriental="Vertical"&&/com.terry.attrs.EditTextExt&&&&&&com.terry.attrs.EditTextExt1&android:id="@+id/ss3"&&&&&&&&android:layout_width="wrap_content"&android:layout_height="wrap_content"&&&&&&&&Text="@string/app_name"&&&&/com.terry.attrs.EditTextExt1&&/LinearLayout&
运行效果如下:
这是这两种为Android 注册 属性的使用方法,那么两者有什么区别呢?
在这里我认为起码有五点,大家可以找找看还有什么区别:
第二种可以编译时报错,如果编程人员随便输入什么第一种是不会报错的,第二种可以支持代码检测功能。第二种写法,跟Android 属性标准写法是一致的,而且可以统一书法规则。第二种写法,可以支持数据格式的验证,比如我们在attrs上注明只支持integer 那么就不可以使用字符串,这是第一种达不到的。第二种写法,可以为VIEW提供选择操作,比如如上我们使用的ENUM让VIEW对应的属性支持ENUM列表,或者为其提供BOOL等只有双项选择的操作。第一种写法,所有的属性必须是引用自资源(不大确定,如果朋友有什么好的DEMO麻烦共享),第二种写法,可以即支持引用资源又可以直接输入做操作,为编程带来更多的方便性。
种种都说明,第二种写法更具规范性,功能更性,代码编写 也更优雅,但个人有个人的使用习惯,我两种都喜欢用,具体看需求吧。呵呵。。。
源码下载:
由于自己见解可能有误,而且太久没写BLOG了,编排和中文语法都落步了,晕死。。都是IPAD搞的。。呵呵。需要看者要抱有评判的心来批判一下我。多多给我提意见。谢谢。

我要回帖

更多关于 xml 自定义标签 的文章

 

随机推荐