Android自定义属性以及组合View

来源:互联网 发布:手机mac怎么改 编辑:程序博客网 时间:2024/05/21 12:02

概念

自定义组合View是指android给我们提供的View本身功能不够用,但是可以把几个View粘合起来形成一个独立的类,对外部提供统一的职能,内部View之间的逻辑实现可以隐藏,使之整体看起来就像是一个新的View。另外,还可以通过自定义属性功能,使得我们的组合View直接在XML布局文件中方便的使用

实现

  • 定义一个基类,之后的组合View都继承自它
public abstract class BaseCustomView extends RelativeLayout {    /**     * 自定义view属性命名空间     */    private static final String NAMESPACE = "http://schemas.android.com/apk/res-auto";    //重载构造函数 通过new构建对象时会调用此处    //View.java中原文:Simple constructor to use when creating a view from code    public BaseCustomView(Context context) {        super(context);        initView();    }    //在XML中构建时会调用此处,也是我们自定义属性的构造函数,style默认用app的主题    //View.java中原文:Constructor that is called when inflating a view from XML    //...This version uses a default style of 0, so the only attribute values     //applie are those in the Context's Theme and the given AttributeSet    public BaseCustomView(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray a = context.obtainStyledAttributes(attrs, getStyleable());        initAttributes(a);        initView();        a.recycle();    }    public BaseCustomView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView();    }    /**     * 初始化布局     */    private void initView() {        View view = View.inflate(getContext(), getLayout(), this);        ButterKnife.bind(this, view);        initData(view);    }    //返回 R.styleable.xxx styleable是自定义的一组declare-styleable    protected abstract int[] getStyleable();    //根据获取到的属性数组在代码中初始化属性值    protected abstract void initAttributes(TypedArray a);    //获取自定义组合View的布局 R.layout.xxx    protected abstract int getLayout();    //初始化一些默认数据    protected abstract void initData(View view);}


  • 一个简单的例子

一般我们在应用中会有很多类似的View,比如设置界面的View都可以抽取出来独立成章,简化代码方便维护下边是一个简单的例子,实现了一个比较通用的设置条目,XML中没有设置相关资源的时候就隐藏相应内部View,否之显示出来。一个空的效果显示如下:
这里写图片描述

public class SettingItemView extends BaseCustomView {    private String mLeftString;    private String mEndString;    private Drawable mLeftImage;    private Drawable mEndImage;    private int mLeftColor;    public SettingItemView(Context context) {        super(context);    }    public SettingItemView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public SettingItemView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    @Override    protected int[] getStyleable() {        return R.styleable.SettingItemView;    }    @Override    protected void initAttributes(TypedArray a) {        mLeftString = a.getString(R.styleable.SettingItemView_textLeft);        mEndString = a.getString(R.styleable.SettingItemView_textEnd);        mLeftImage = a.getDrawable(R.styleable.SettingItemView_imageLeft);        mEndImage = a.getDrawable(R.styleable.SettingItemView_imageEnd);        mLeftColor = a.getColor(R.styleable.SettingItemView_colorLeft, getResources().getColor(R                .color.text_color));    }    @Override    protected int getLayout() {        return R.layout.ui_setting_item;    }    @Override    protected void initData(View view) {        setLeftText(mLeftString);        setEndText(mEndString);        setLeftImage(mLeftImage);        setEndImage(mEndImage);        tv_left.setTextColor(mLeftColor);    }    public void setLeftImage(Drawable image) {        iv_left.setImageDrawable(image);    }    /**     * 当没有设置图片资源时隐藏之     *     * @param image     */    public void setEndImage(Drawable image) {        if (image != null) {            iv_end.setVisibility(VISIBLE);            iv_end.setImageDrawable(image);        }    }    public void setLeftText(String text) {        tv_left.setText(text);    }    /**     * 当没有设置文字时隐藏之     *     * @param text     */    public void setEndText(String text) {        if (!TextUtils.isEmpty(text)) {            tv_end.setVisibility(VISIBLE);            tv_end.setText(text);        }     }}

-可以新建一个属性文件attrs.xml

添加以下自定义属性(一些通用的可以抽取出来供其它使用):

<!--common-->    <attr name="textLeft" format="string"/>    <attr name="textEnd" format="string"/>    <attr name="imageLeft" format="reference"/>    <attr name="imageEnd" format="reference"/><!--SettingItemView--><declare-styleable name="SettingItemView">    <attr name="textLeft"/>    <attr name="textEnd"/>    <attr name="imageLeft"/>    <attr name="imageEnd"/>    <attr name="colorLeft" format="color"/></declare-styleable>

关于styleable属性类型可以搜索一下有很多资料,就不展开说了~

  • 布局文件如下:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout    android:id="@+id/rl_root"    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="@dimen/item_height">    <View        android:id="@+id/line"        android:layout_width="match_parent"        android:layout_height="0.1dp"        android:background="#ffd2d2d2"        android:layout_alignParentBottom="true"/>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="@dimen/item_height"        android:orientation="horizontal"        android:layout_above="@id/line">        <ImageView            android:id="@+id/iv_left"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:scaleType="centerInside"            android:visibility="gone"/>        <TextView            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center_vertical"            android:layout_weight="1"            android:visibility="gone"/>        <ImageView            android:id="@+id/iv_end"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:scaleType="centerInside"            android:visibility="gone"/>        <TextView            android:id="@+id/tv_end"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:gravity="center_vertical"            android:visibility="gone"/>    </LinearLayout></RelativeLayout>

以上布局可以自己看着调就好了~


  • 应用

在布局中应用刚才写的组合View就像普通View一样就好了,别忘了在跟布局中添加一行

xmlns:item="http://schemas.android.com/apk/res-auto"

这样新属性就可以以item的命名空间调用了

<所在包名.SettingItemViewandroid:id="@+id/siv_test"android:layout_width="match_parent"android:layout_height="wrap_content"item:imageLeft="@drawable/xxx"item:textLeft="test"/>
0 0
原创粉丝点击