从学习styleable自定义view属性到一点儿更有意思的尝试

《代码里的世界》 —UI篇

用文字札记描绘自己 android学习之路

转载请保留出处 by Qiao

【导航】 – 多行文本折叠展开 自定义布局View实现多行文本折叠和展开

1.概述

  前面封装view的时候用到了自定义属性,觉得有必要单独讲一下这部分,但是呢,又不想向其他文章一样千篇一律地写这些东西。所以呢,后便会加一些临时的发散思维,引用点有意思的东西。分享东西嘛,随性点儿。   回归正题,我们想在view中使用自定义属性要怎么做呢?   其实有如下几点:

declare-styleable 在res/values目录下新建xml文件 自定义你的属性AttributeSet和TypedArray 在view中获取这些属性对应的值,设置绑定到view上

xmlns申明与引用 在你要使用的地方引入命名空间并使用这些属性,赋值

  然后我们来尝试通过这些步骤做些自定义view,同时呢,我期望能方便快捷的绑定一些事件,执行相应操作。尝试来做一下。   xml直接定义view和点击事件的demo   

2.实践

  其实自定义view的属性算是比较常见的,想来想去却没想到什么比较好写的view。就拿最常见的设置选项来说吧,我希望直接通过简单的xml配置就可以设置其字体大小颜色内容,图标和点击触发的事件。

2.1定义属性

  在res/values目录下新建一个attrs.xml的文件,利用declare-styleable定义我们的属性样式。

=======>======>=></resources>

简单讲解下其中,

标签declare-styleable的name属性 :代表了接下来定义的属性的所属控件(只是用来区分不同declare-styleable的代号而且,不一定非要和属性相关的控件的名称一致)

标签attr就是用来的定义具体的属性,name代表属性名,format代表属性的类型。

Attrs.xml文件中属性类型format值的格式

引用型reference

定义: < attr name = “background” format = “reference” /> 使用: tools:background = “@drawable/图片ID”

颜色型color

定义: < attr name = “textColor” format = “color” /> 使用: tools:textColor = “#ffffff”

布尔型boolean

定义: < attr name = “focusable” format = “boolean” /> 使用:tools: focusable = “true”

尺寸型dimension

定义: < attr name = “layout_width” format = “dimension” /> 使用: tools: layout_width = “42dip”

浮点型float

定义: < attr name = “fromAlpha” format = “float” /> 使用:tools: fromAlpha = “1.0”

整型integer

定义: < attr name = “frameDuration” format = “integer” /> 使用: tools: frameDuration = “100”

字符串string

定义: < attr name = “apiKey” format = “string” /> 使用: tools: apiKey = “dsegergegasefwg”

百分数fraction

定义: < attr name = “pivotX” format = “fraction” /> 使用: tools: pivotx = “200%”

枚举型enum:

定义: < attr name=”orientation”>   < enum name=”horizontal” value=”0” />   < enum name=”vertical” value=”1” /> < /attr> 使用: android:orientation = “vertical”

标志位、位或运算,格式如下:

定义: < attr name=”windowSoftInputMode”>   < flag name = “stateUnspecified” value = “0” />   < flag name = “stateUnchanged” value = “1” />   < flag name = “adjustUnspecified” value = “0x00” />   < flag name = “adjustResize” value = “0x10” /> < /attr> 使用: android:windowSoftInputMode = “stateUnspecified | stateUnchanged | stateHidden”>

属性定义可以指定多种类型:

定义: < attr name = “background” format = “reference|color” /> 使用: android:background = “@drawable/图片ID|#00FF00”

2.2 View中使用自定义属性

  View的默认构造方法里有 XXX(Context context, AttributeSet attrs) ,而这个 AttributeSet 参数即为属性集合,我们可以利用 TypedArray 来获取我们想要的属性。   可以看我这里自定义的View类RowItem,它获取自定义属性的方法为initWithAttrs。它通过这个方法获取最终的属性值的过程:

(Context context, AttributeSet attrs) {TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.RowItem);textColor = a.getColor(R.styleable.RowItem_textColor,defaultTextColor);textStyle = a.getColor(R.styleable.RowItem_textStyle,-1);textSize = a.getDimensionPixelSize(R.styleable.RowItem_textSize, defaultTextSize);text = a.getString(R.styleable.RowItem_text);icon = a.getDrawable(R.styleable.RowItem_icon);position = a.getInt(R.styleable.RowItem_position, defaultPosition);if(icon == null){icon = getResources().getDrawable(defaultIconId);}action = a.getString(R.styleable.RowItem_action);a.recycle();initViews();//利用属性值设置绑定View}

  先通过context.obtainStyledAttributes()方法将attrs.xml中定义的属性与AttributeSet 关联起来并映射到 TypedArray a,然后通过 a.getXXX()来获取相应属性,第二个参数为取不到时的默认值。最后用a.recycle()来回收释放。   详细讲下怎个自定义View。转回我们的自定义RowItem内部,来看一下View的实现。先定义了一个ImageVIew和TextView,然后定义对应的属性和默认值:

{protected ImageView iconView;protected TextView contentView;/***对应自定义属性*/protected int textColor;protected int textStyle;protected float textSize;protected String text;protected int position;protected Drawable icon;protected String action;/***默认属性属性*/public int defaultTextColor = Color.BLACK;public int defaultTextSize = 12;public int defaultPosition = -1;private int defaultIconId = R.drawable.ic_launcher;(Context context) {super(context);initWithAttrs(context,null);//null则用默认属性值初始化}(Context context, AttributeSet attrs) {super(context, attrs);initWithAttrs(context,attrs);//初始化自定义属性bindListener();}//…其他代码可以看到,两个构造方法都使用了initWithAttrs()方法,设置绑定属性值,第一个构造方法中attrs为null则意味着使用默认值。在初始化了view的属性值之后,在方法最后一段,调用了initViews()来初始化view:(){View root = LayoutInflater.from(getContext()).inflate(R.layout.row_item, RowItem.this);iconView = (ImageView) findViewById(R.id.item_image);contentView = (TextView) findViewById(R.id.item_tv);iconView.setImageDrawable(icon);if(!TextUtils.isEmpty(text))contentView.setText(text);contentView.setTextSize(TypedValue.COMPLEX_UNIT_PX,textSize);contentView.setTextColor(textColor);contentView.setTypeface(null, textStyle);root.setBackgroundResource(getBackGroundResource(position));}/***根据当前rowItem位置来返回相应的背景(其实我们可以直接在xml中设置rowitem背景,这里只是用于演示使用枚举型常量定义的属性)*/(int position2) {switch(position){case 0:return R.drawable.top_item_click_bg;case 1:return R.drawable.middle_item_click_bg;case 2:return R.drawable.bottom_item_click_bg;default:return R.drawable.single_item_click_bg;}}于千万年之中,于千万人之中,在时间无涯的荒野中,

从学习styleable自定义view属性到一点儿更有意思的尝试

相关文章:

你感兴趣的文章:

标签云: