美文网首页
Android自定义属性以及组合View

Android自定义属性以及组合View

作者: windrises | 来源:发表于2017-10-14 11:05 被阅读35次

    概念

    自定义组合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 
    
    • 一个简单的例子

    一般我们在应用中会有很多类似的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的命名空间调用了

    <所在包名.SettingItemView
    android:id="@+id/siv_test"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    item:imageLeft="@drawable/xxx"
    item:textLeft="test"/>
    

    迁移自CSDN
    2015年12月12日 11:02:33
    http://blog.csdn.net/u013262051/article/details/50273451

    相关文章

      网友评论

          本文标题:Android自定义属性以及组合View

          本文链接:https://www.haomeiwen.com/subject/ffsxuxtx.html