第一部分:attrs.xml
<!-- 这里我们要创建自定义view的属性 -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="relation">
<enum name="icon_left" value="0"/>
<enum name="icon_right" value="1"/>
<enum name="icon_above" value="2"/>
<enum name="icon_below" value="3"/>
</attr>
下面这里讲一下skip这个东西,顾名思义是跳过什么东西,如果在里面设置了一些内容,在解析xml文件的时候就会跳过一些设置的内容(纯粹自己理解,如果有人知道<span style="font-family: Arial, Helvetica, sans-serif;">请告诉下,谢谢!)。是按照.Net中有个System.Xml.Skip()理解的。</span>
<skip />
<!-- 在这里创建需要的几种属性,并且指明属性需要的几种值。
其中属性relation是固定好的四种枚举值;另外这里还有一个
注意的点是name="IconText"这个命名空间前缀 -->
<declare-styleable name="IconText">
<attr name="relation"/>
<attr name="icon" format="reference"/>
<attr name="text" format="string"/>
<attr name="text_size" format="dimension"/>
<attr name="text_color" format="integer"/>
<attr name="space" format="dimension"/>
</declare-styleable>
</resources>
第二部分:IconTextView.java
创建好自定义view属性后,我们就需要去创建自定义view类,并且处理该view类
布局后的初始化操作。下面这个view包含一个TextView和一个ImageView。
public class IconTextView extends LinearLayout {
private final static String TAG = "IconTextView";
private final int ICON_LEFT = 0;
private final int ICON_RIGHT = 1;
private final int ICON_ABOVE = 2;
private final int ICON_BELOW = 3;
private TextView mTextView;
private ImageView mImageView;
private int mRelation = ICON_LEFT;
private String mText = "";
private int mIconId;
private float mTextSize;
private int mSpace;
//当我们在xml文件中布局该view的时候,会调用构造函数做初始化。
public IconTextView(Context context, AttributeSet attrs) {
super(context, attrs);
//获取xml文件中的名字为IconText的所有属性
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IconText);
mRelation = a.getInt(R.styleable.IconText_relation, ICON_LEFT);
Log.d(TAG,"mRelation = " + mRelation);
mText = a.getString(R.styleable.IconText_text);
Log.d(TAG,"mText = " + mText);
mTextSize = a.getDimensionPixelSize(R.styleable.IconText_text_size, 12);
Log.d(TAG, "mTextSize = " + mTextSize);
mSpace = a.getDimensionPixelSize(R.styleable.IconText_space, 5);
Log.d(TAG, "mSpace = " + mSpace);
mIconId = a.getResourceId(R.styleable.IconText_icon, R.drawable.ic_launcher);
Log.d(TAG, "mIconId = " + mIconId);
a.recycle();
//属性完成后,把这些属性设置进TextView和ImageView
mTextView = new TextView(context);
mTextView.setText(mText);
mTextView.setTextSize(mTextSize);
mImageView = new ImageView(context);
mImageView.setImageResource(mIconId);
//根据mRelation的值,设置整个view的布局排列以及ImageView的边距。
int left = 0, top = 0, right = 0, bottom = 0;
int orientation = HORIZONTAL;
int textViewIndex = 0;
switch (mRelation) {
case ICON_ABOVE:
orientation = VERTICAL;
bottom = mSpace;
textViewIndex = 1;
break;
case ICON_BELOW:
orientation = VERTICAL;
top = mSpace;
break;
case ICON_LEFT:
right = mSpace;
textViewIndex = 1;
break;
case ICON_RIGHT:
left = mSpace;
break;
}
this.setOrientation(orientation);
this.addView(mImageView);//把子ImageView加入自定View
mImageView.setPadding(left, top, right, bottom);
this.addView(mTextView, textViewIndex);//把子TextView加入自定View
}
}
第三部分:activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
在布局中使用自定义的view,然后系统就会调用第二部分的代码去解析下面的属性,初始化IconTextView
<com.example.selfviewdemo.IconTextView
android:id="@+id/icontext_01"
xmlns:android="http://schemas.android.com/apk/res/android"
下面这句是自定义View的命名空间,icontext对应attrs.xml中的IconText,然后把android的包名改成自己的包名就好了
xmlns:icontext="http://schemas.android.com/apk/res/com.example.selfviewdemo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
icontext:relation="icon_right"
icontext:text="@string/icon_text"
icontext:text_size="12sp"/>
</RelativeLayout>
第四部分:MainActivity.java
在这里直接setContentView,你就能看到自定义的view啦!
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}