为什么要自己定义View
android开发中自己定义View的优点是显而易见的。比方说以下的这个顶部导航,它被设计出如今应用的每一个界面,但每次的内容却不尽同样。我们不能在每一个layout资源中都配置一组同样的View吧?假设使用<include layou="@layout/xxx"/>标签,尽管攻克了布局文件的重用性,可是相关View的初始化设置还是没可以重用(集中),须要每次都採用view.findViewById(id)来初始化他们。
有了对“可重用性”的考量,我们来完毕一次对自己定义View的探索。
第一步,创建自己定义View的布局文件
这里创建的布局文件和平日里为Activity或Fragment创建的布局文件没有差别,比如以下的xml创建了一个上面是图片,以下是文字的自己定义View布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@drawable/ic_launcher" /> <TextView android:id="@+id/txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="asdfasdf" /> </LinearLayout>
第二步,创建继承自View或其子类的自己定义View
package org.xiaom.customView.view; import org.xiaom.customView.R; public class MyView extends LinearLayout { private View root = null; //上面的img private ImageView imgView = null; //img以下的text private TextView txtView = null; public MyView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public MyView(Context context) { super(context); initView(context); } private void initView(Context context) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); root = inflater.inflate(R.layout.view_my_view, this,true); imgView = (ImageView) root.findViewById(R.id.img); txtView = (TextView) root.findViewById(R.id.txt); } }
第三步,在xml中配置、使用自己定义View
在完毕上面的自己定义操作后,接下来就能够像使用android原生组件那样使用我们的自己定义View了。须要注意的是,自己定义View在xml中声明使用时,必须採用全类名(类全名- -)。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- 类全名 --> <org.xiaom.customView.view.MyView android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="aasdfasdfasdfa" /> </LinearLayout>
接下来就非常easy了,我们直接使用Activity.this.setContentView(layouId)方法就可以。
第四步,配置declare-styleable以声明自己定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="myView"> <attr name="img" format="reference" /> <attr name="text" format="string"></attr> </declare-styleable> </resources>
package org.xiaom.customView.view; import org.xiaom.customView.R; public class MyView extends LinearLayout { private View root = null; // 上面的img private ImageView imgView = null; // img以下的text private TextView txtView = null; // 上面的图像资源Id Drawable img; // 文字内容 String text; public MyView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.myView); img = ta.getDrawable(R.styleable.myView_img); text = ta.getString(R.styleable.myView_text); initView(context); //记得此处要recycle(); ta.recycle(); } private void initView(Context context) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); root = inflater.inflate(R.layout.view_my_view, this, true); imgView = (ImageView) root.findViewById(R.id.img); txtView = (TextView) root.findViewById(R.id.txt); //将自己定义属性的值传递给相应View imgView.setBackgroundResource(R.drawable.icon_consultation); txtView.setText(text); } }以下的xml表明怎样在xml中配置自己定义属性:
<!-- 我的adt版本号是v22.6.2-1085508,它支持自己主动找寻和验证declare-styleable;假设你的adt不支持此功能,请换成 --> <!-- xmlns:myView="http://schemas.android.com/apk/org.xiaom.customView.myView",此处我没验证 --> <LinearLayout xmlns:myView="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- 类全名 --> <org.xiaom.customView.view.MyView android:layout_width="match_parent" android:layout_height="wrap_content" myView:img="@drawable/icon_consultation" myView:text="自己定义Text" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="aasdfasdfasdfa" /> </LinearLayout>