鸿洋大神博文Android(安卓)自定义View (一)中自定义属性所遇到的坑
原因是由于接触安卓也这么久了,但是自定义view这方面一直没怎么了解, 尤其是对于自定义属性的使用。
由于最近app上需要用到自定义View,于是决定把自定义View的坑填上(毕竟安卓中自定义View是重点也是难点),
可是没想到第一步就遇到了问题。写这博文主要是为了记录错误,也可以为同样遇到这问题的童鞋提供一个解决办法。
首先给出鸿洋大神此博文的传送门传送门。你们可以先过去看看。
由于要用到部分大神的文字才方便解释(不知算不算那啥,有问题联系我,立马删除)
1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。[html] view plain copy 在CODE上查看代码片派生到我的代码片<?xml version="1.0" encoding="utf-8"?> 我们定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;不清楚的可以google一把。然后在布局中声明我们的自定义View[objc] view plain copy 在CODE上查看代码片派生到我的代码片 一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我们的命名空间,后面的包路径指的是项目的package2、在View的构造方法中,获得我们的自定义的样式[java] view plain copy 在CODE上查看代码片派生到我的代码片/** * 文本 */ private String mTitleText; /** * 文本的颜色 */ private int mTitleTextColor; /** * 文本的大小 */ private int mTitleTextSize; /** * 绘制时控制文本绘制的范围 */ private Rect mBound; private Paint mPaint; public CustomTitleView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomTitleView(Context context) { this(context, null); } /** * 获得我自定义的样式属性 * * @param context * @param attrs * @param defStyle */ public CustomTitleView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /** * 获得我们所定义的自定义样式属性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.CustomTitleView_titleText: mTitleText = a.getString(attr); break; case R.styleable.CustomTitleView_titleTextColor: // 默认颜色设置为黑色 mTitleTextColor = a.getColor(attr, Color.BLACK); break; case R.styleable.CustomTitleView_titleTextSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } a.recycle(); /** * 获得绘制文本的宽和高 */ mPaint = new Paint(); mPaint.setTextSize(mTitleTextSize); // mPaint.setColor(mTitleTextColor); mBound = new Rect(); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); }
上文是这样的:
/** * 获得我们所定义的自定义样式属性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.CustomTitleView_titleText: mTitleText = a.getString(attr); break; case R.styleable.CustomTitleView_titleTextColor: // 默认颜色设置为黑色 mTitleTextColor = a.getColor(attr, Color.BLACK); break; case R.styleable.CustomTitleView_titleTextSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } a.recycle();
也就是先获取了自定义属性的目录索引值,然后通过switch进行与我们的attrs.xml相匹配,最后进行取值。
这样咋看没有什么问题,在这篇博文也没什么问题,
但是如果我们想偷点懒,不在xml中写出任何我们的自定义属性,这时会发生什么?
你肯定会说当然是取代码中你写的默认值啊,非也,非也。照这种写法是不能取到任何默认值!
为什么?看看变色的那句,理解到了吗?
context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);是通过查询我们使用自定义View的时候里面所写出的值,准确的说是保存所有我们写出的值,
比如上文中的:
android:layout_width="200dp" android:layout_height="100dp" custom:titleText="3712" custom:titleTextColor="#ff0000" custom:titleTextSize="40sp"
它就会找到,android:layout_width,android:layout_height,custom:titleText,custom:titleTextColor,custom:titleTextSize。这几组值,
但是如果我们自定义的属性不写上去呢?只是想控制个控件的大小(事实证明很多情况下你的确不太会去改变控件的其他属性,除非你需要),就会变成只找到android:layout_width,android:layout_height。这时候如果你再通过Switch()去匹配的话,除了android:layout_width,android:layout_height两个分支,其他的都不会被执行,既然没有执行,那么默认值如何取得出?
找到了问题所在,我们就要解决了,解决也很简单,去掉获取目录,不使用switch()语句
每个属性都这样获取:
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);
// 默认颜色设置为黑色 mTitleTextColor = a.getColor(attr, Color.BLACK);
这样就能保证每个想要设置默认值的能正确的被设置默认值了。
有问题欢迎指正,如引用的部分文字有侵权,请告知我,会立即处理、
更多相关文章
- 在Android中通过jni方式使用编译好的FFmpeg库-Android中使用FFmp
- Android(安卓)Q暗色模式适配踩坑—状态栏
- [Android(安卓)之美] 那些你不知道的APK 瘦身,让你的APK更小
- android/NDK开发assets资源中文名打包问题
- g1安装android软件详细攻略
- android重用layout-include标签的使用
- android 支付宝SDK集成
- J2me游戏如何快速移植到Android(安卓)(2)
- 在android的java代码中自定义log