控件属性想必大家都知道如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.customview.CustomView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#000000" /> </RelativeLayout>
上面的xml文件中 android:layout_width,android:layout_height就是系统的控件属性,加入我把xmlns:android这个改成xmlns:androidtag呢?
发现它下面使用到的属性就会报错, ‘layout_height‘ attribute should be definedless...意思是说你layout_height这个属性没有被定义,首先要明白xmlns是什么意思
xmlns是XML Namespaces的缩写,中文名称是XML命名空间。使用的规则为,首先定义命名空间xmlns:namespaceprefix="namespaceURI"。Android中xml中的使用是:
xmlns:前缀=http://schemas.android.com/apk/res/应用程序包路径;然后使用的时候按格式:namespaceprefix(缀):属性
如果使用xmlns,则xmlns的定义必须放在最外层开始的的标记中
当命名空间被定义之后,所有带有相同前缀的子元素都会与同一个命名空间相关联。避免XML解析器对xml解析时的发送名字冲突,这就是使用xmlns的必要性。当自定义的View有自己的属性的时候,就用到xmlns来定义一个命名空间
所以我们把xmlns:android改成了xmlns:androidtag为什么导致报错,然后为什么我们创建一个布局xml文件就会自动给我们这些数据呢?比如android:layout_width,这是因为系统给我们定义好了这些属性,如何查看系统给的属性呢?E:\soft\Android-SDK\platforms\android-19\data\res
这是我的sdk放在e盘的,
这些都是系统给我们自带好的一些资源,比如弹一个toast,它的背景资源就是在drawable目录下,哪我们自定义控件属性要放在哪呢?我们在res目录下有个attrs文件:
这里面定义了很多关于文字,颜色,id,尺寸等资源,而系统自定义的属性就是存放在attrs文件里,打开看一眼,
我们看下它怎么定义的,首先<declare-styleable name="View"> 这其中有二个属性名称,
declare-styleable属性是声明表示你要自定义控件属性,
name表示你要自定义控件属性的名称,如上面的name="View"表示给控件View要定义属性
attr
表示定义属性的名称
format表示改属性名称对应的值,而且format对应的值有二个如
<attr
name="background" format="reference|color" /> 这个是给view设置背景的属性,取值为reference|color,其中reference表示可以引用res下的资源,比如可以是colors.xml文件中定义的一个颜色值,也可以是一个图片,也可以是drawable文件夹下的一个定义的背景xml文件,color表示是直接写的值
比如“#ffffff”就是给背景设置白色,
哪我们根据系统自己模仿也在res/values下创建一个attrs文件,
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CustomView"> <attr name="text" format="reference|string"></attr> </declare-styleable> </resources>
这个是表示你给CustomView控件设置了一个text属性,但是如何在xml布局文件中使用呢?它不是我们系统给定的属性直接使用android:text即可,
在xml要使用自定义的属性必须要先声明命名空间,系统的命名空间是:
xmlns:android="http://schemas.android.com/apk/res/android"
android这个前缀被系统使用了,我们就不能再使用android作为前缀了,比如前缀为customview,还有就是要导入自定义的属性集,一般有二种做法
1:
xmlns:android="http://schemas.android.com/apk/res/com.example.customview"
我们看到res/后面不在是android 而是我们自己应用的包名,
2:
xmlns:android="http://schemas.android.com/apk/res-auto"
这二种方法都行,
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:customview="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.customview.CustomView android:layout_width="wrap_content" android:layout_height="wrap_content" customview:text="美丽新世界" /> </RelativeLayout>
现在问题是这些属性不是系统的属性,我们如何通过代码获取呢?
使用代码获取某个属性用户所定义的值,主要是使用TypedArray类,这个类担供了所有的获取某个属性值的方法,如下所示,但需要注意的是,在使用完以后必须调用TypedArray的recycle()方法,用来释放资源
我们在CustomView类的构造函数中来获取自定义的属性值并绘制显示在屏幕上:
package com.example.customview; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.View; /** * Created by admin on 2016/5/9. */ public class CustomView extends View { private static final String TAG ="CustomView" ; private Paint mPaint = null; String content ; public CustomView(Context context) { super(context); } public CustomView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.CustomView); content = typedArray.getString(R.styleable.CustomView_text); typedArray.recycle();//释放资源 } public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setTextSize(60);//设置文字大小 canvas.drawText(content,100,100,mPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
如图:
我们可以看下系统是怎么获取系统的属性值的:
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { this(context); final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); if (mDebugViewAttributes) { saveAttributeData(attrs, a); } Drawable background = null; int leftPadding = -1; int topPadding = -1; int rightPadding = -1; int bottomPadding = -1; int startPadding = UNDEFINED_PADDING; int endPadding = UNDEFINED_PADDING; int padding = -1; int viewFlagValues = 0; int viewFlagMasks = 0; boolean setScrollContainer = false; int x = 0; int y = 0; float tx = 0; float ty = 0; float tz = 0; float elevation = 0; float rotation = 0; float rotationX = 0; float rotationY = 0; float sx = 1f; float sy = 1f; boolean transformSet = false; int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; int overScrollMode = mOverScrollMode; boolean initializeScrollbars = false; boolean initializeScrollIndicators = false; boolean startPaddingDefined = false; boolean endPaddingDefined = false; boolean leftPaddingDefined = false; boolean rightPaddingDefined = false; final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; final int N = a.getIndexCount(); for (int i = 0; i < N; i++) { int attr = a.getIndex(i); switch (attr) { case com.android.internal.R.styleable.View_background: background = a.getDrawable(attr); break; case com.android.internal.R.styleable.View_padding: padding = a.getDimensionPixelSize(attr, -1); mUserPaddingLeftInitial = padding; mUserPaddingRightInitial = padding; leftPaddingDefined = true; rightPaddingDefined = true; break; case com.android.internal.R.styleable.View_paddingLeft: leftPadding = a.getDimensionPixelSize(attr, -1); mUserPaddingLeftInitial = leftPadding; leftPaddingDefined = true; break; case com.android.internal.R.styleable.View_paddingTop: topPadding = a.getDimensionPixelSize(attr, -1); break; case com.android.internal.R.styleable.View_paddingRight: rightPadding = a.getDimensionPixelSize(attr, -1); mUserPaddingRightInitial = rightPadding; rightPaddingDefined = true; break;
这只是系统类View的一部分构造函数中的代码,它是如何获取属性值的,没事可以看看,
我们可以看下TypedArray类给我们提供了哪些方法可以获取属性值
declare-styleable标签其它属性用法
1、 reference:参考某一资源ID。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "名称">
- <attr name = "background" format = "reference" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <ImageView
- android:layout_width = "42dip"
- android:layout_height = "42dip"
- android:background = "@drawable/图片ID"/>
2. color:颜色值。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "名称">
- <attr name = "textColor" format = "color" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <TextView
- android:layout_width = "42dip"
- android:layout_height = "42dip"
- android:textColor = "#00FF00"/>
3. boolean:布尔值。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "名称">
- <attr name = "focusable" format = "boolean" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <Button
- android:layout_width = "42dip"
- android:layout_height = "42dip"
- android:focusable = "true"/>
4. dimension:尺寸值。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "名称">
- <attr name = "layout_width" format = "dimension" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <Button
- android:layout_width = "42dip"
- android:layout_height = "42dip"/>
5. float:浮点值。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "AlphaAnimation">
- <attr name = "fromAlpha" format = "float" />
- <attr name = "toAlpha" format = "float" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <alpha
- android:fromAlpha = "1.0"
- android:toAlpha = "0.7"/>
6. integer:整型值。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "AnimatedRotateDrawable">
- <attr name = "visible" />
- <attr name = "frameDuration" format="integer" />
- <attr name = "framesCount" format="integer" />
- <attr name = "pivotX" />
- <attr name = "pivotY" />
- <attr name = "drawable" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <animated-rotate
- xmlns:android = "http://schemas.android.com/apk/res/android"
- android:drawable = "@drawable/图片ID"
- android:pivotX = "50%"
- android:pivotY = "50%"
- android:framesCount = "12"
- android:frameDuration = "100"/>
7. string:字符串。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "MapView">
- <attr name = "apiKey" format = "string" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <com.google.android.maps.MapView
- android:layout_width = "fill_parent"
- android:layout_height = "fill_parent"
- android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g" />
8. fraction:百分数。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name="RotateDrawable">
- <attr name = "visible" />
- <attr name = "fromDegrees" format = "float" />
- <attr name = "toDegrees" format = "float" />
- <attr name = "pivotX" format = "fraction" />
- <attr name = "pivotY" format = "fraction" />
- <attr name = "drawable" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <rotate
- xmlns:android = "http://schemas.android.com/apk/res/android"
- android:interpolator = "@anim/动画ID"
- android:fromDegrees = "0"
- android:toDegrees = "360"
- android:pivotX = "200%"
- android:pivotY = "300%"
- android:duration = "5000"
- android:repeatMode = "restart"
- android:repeatCount = "infinite"/>
9. enum:枚举值。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name="名称">
- <attr name="orientation">
- <enum name="horizontal" value="0" />
- <enum name="vertical" value="1" />
- </attr>
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <LinearLayout
- xmlns:android = "http://schemas.android.com/apk/res/android"
- android:orientation = "vertical"
- android:layout_width = "fill_parent"
- android:layout_height = "fill_parent">
- </LinearLayout>
10. flag:位或运算。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name="名称">
- <attr name="windowSoftInputMode">
- <flag name = "stateUnspecified" value = "0" />
- <flag name = "stateUnchanged" value = "1" />
- <flag name = "stateHidden" value = "2" />
- <flag name = "stateAlwaysHidden" value = "3" />
- <flag name = "stateVisible" value = "4" />
- <flag name = "stateAlwaysVisible" value = "5" />
- <flag name = "adjustUnspecified" value = "0x00" />
- <flag name = "adjustResize" value = "0x10" />
- <flag name = "adjustPan" value = "0x20" />
- <flag name = "adjustNothing" value = "0x30" />
- </attr>
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <activity
- android:name = ".StyleAndThemeActivity"
- android:label = "@string/app_name"
- android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">
- <intent-filter>
- <action android:name = "android.intent.action.MAIN" />
- <category android:name = "android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
特别要注意:
属性定义时可以指定多种类型值。
(1)属性定义:
[html] view
plain copy
- <declare-styleable name = "名称">
- <attr name = "background" format = "reference|color" />
- </declare-styleable>
(2)属性使用:
[html] view
plain copy
- <ImageView
- android:layout_width = "42dip"
- android:layout_height = "42dip"
- android:background = "@drawable/图片ID|#00FF00"/>
注:最后这些属性这么使用来自http://blog.csdn.net/harvic880925/article/details/46537767,因为写起来实在太费时间,感谢博主!