初次入门,笔尖寒酸。
以一个自定义带文字的图片控件为例:
自定义MyImageView继承LinearLayout
public class MyImageView extends LinearLayout {
public MyImageView(Context context) {
super(context);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
因为想实现带图片的文字(带文字的图片),初步想法是类似自定义ViewGroup然后添加入一个TextView和一个ImageView,只达到熟悉自定义组件提供xml属性即可。
在res文件夹新建资源文件attrs.xml,编写提供xml文件使用的属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyImageView">
<attr name="chanImageViewTitle" format="string|reference"></attr>
<attr name="chanImageViewSrc" format="reference"></attr>
<attr name="chanImageViewOrientation">
<enum name="Vertical" value="0"></enum>
<enum name="Horizontal" value="1"></enum>
</attr>
</declare-styleable>
</resources>
其中,attr标签内name表示提供的属性名,format表示填写这个属性要输入的值的格式,可以用”|”隔开,允许多种输入值格式,自定义chanImageViewOrientation只有两个值,水平或垂直,用emu标签枚举出所有的类型即可。
然后修改MyImageView代码:
使用TypedArray读取xml属性值
/** * Created by Administrator on 2016/4/14. * * 自定义带图片的TextView */
public class MyImageView extends LinearLayout {
public MyImageView(Context context) {
super(context);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
ImageView imageView = new ImageView(context);
TextView textView = new TextView(context);
//资源id,读取自定义属性的每一种属性时用这个值接收下
int resourceId;
//这里要填两个参数的方法,attrs如果不传入则控件无效
//获取属性数组
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.MyImageView);
//遍历属性数组,根据属性不同,进行不同操作
int n = typedArray.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = typedArray.getIndex(i);
switch (attr) {
// 处理文字
case R.styleable.MyImageView_chanImageViewTitle :
resourceId = typedArray.getResourceId(attr, 0);
Log.d ("title","---"+resourceId+"---");
if (resourceId > 0) {
// 如果是引用类型的
textView.setText(typedArray.getResources()
.getText(resourceId).toString());
} else {
// 如果是字符串类型的
textView.setText(typedArray.getString(attr));
}
break;
// 处理图片
case R.styleable.MyImageView_chanImageViewSrc :
resourceId = typedArray.getResourceId(attr, 0);
Log.d ("src","---"+resourceId+"---");
if (resourceId > 0) {
// 是引用类型
imageView.setImageResource(resourceId);
} else {
imageView.setImageResource(R.mipmap.ic_launcher);
}
break;
// 处理方向
case R.styleable.MyImageView_chanImageViewOrientation :
resourceId = typedArray.getInt (attr,1);
Log.d ("orentation","---"+resourceId+"---");
if (resourceId == 1) {
// 如果是水平
this.setOrientation(LinearLayout.HORIZONTAL);
} else {
// 如果是纵向
this.setOrientation(LinearLayout.VERTICAL);
}
break;
}
}
addView(textView);
addView(imageView);
typedArray.recycle();
}
}
使用完typedArray后记得要调用recycle( );
其中缘由有博客讲的很详细:
http://blog.csdn.net/Monicabg/article/details/45014327
然后在activity_main调用,记得加上命名空间;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:my="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.demo.mycustomview.MainActivity">
<com.demo.mycustomview.MyImageView android:layout_width="wrap_content" android:layout_height="wrap_content" my:chanImageViewTitle="chanImageViewTitle" my:chanImageViewOrientation="Vertical" my:chanImageViewSrc="@mipmap/ic_launcher">
</com.demo.mycustomview.MyImageView>
</LinearLayout>
完结~