关于带布局的自定义View(自定义TitleView)

问题:多一层外套的组合自定义View

当自定义View需要引入R.layout.view_xxx时,在R.layout.view_xxx尽量使用merge标签,这样可以减少一层ViewGroup的嵌套。

引用一个网上看到的例子:

组合自定义View在日常开发中的引用场景应该还是相对比较多的,下面我粘上一个简单的组合自定义View的实现:

/**
 * 简单的一个组合自定义View,在它的中央会显示一个TextView文本
 * 此案例的布局填充方式也是目前网上包括一些书籍描述的填充方式
 */
public class GroupNormalView extends RelativeLayout {
    
    public GroupNormalView(Context context) {
        this(context, null);
    }

    public GroupNormalView(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.group_normal_view, this, true);
    }
}

xml布局:




    

然后,我在MainActivity的布局中引入这个自定义View。




    

运行demo,当页面打开后,我们使用AS自带的Layout Inspector工具来查看当前页面的布局组成。如下图:


关于带布局的自定义View(自定义TitleView)_第1张图片
在这里插入图片描述

Layout Inspector工具的位置


关于带布局的自定义View(自定义TitleView)_第2张图片
在这里插入图片描述

当前页面的布局内容中仅含一个GroupNormalView,在它的里面包含一层相对布局,然后还有一个TextView。看最初定义GroupNormalView的时候我直接让它继承了RelativeLayout,也就是说GroupNormalView本身就含有RelativeLayout的全部布局属性了,那么现在有没有觉着上图中第二个箭头所指的RelativeLayout有些多余呢?事实证明,真的很多余。下面就让我们把这多余的一层布局给干掉。

解决方式

取个简单的例子:
当我们自己封装TitleBar的时候往往会引入一个R.layout.layout_title布局。
R.layout.layout_title:





    

    

    

    

    


    

tips:这里我们根布局选用ConstraintLayout布局,铺布局时可以先放一个ConstraintLayout当做根布局。在布局完成后把ConstraintLayout替换成merge标签,在merge中加入如下代码来让preview正常显示布局样式。

xmlns:tools="http://schemas.android.com/tools"
tools:parentTag="android.support.constraint.ConstraintLayout"

如图:


关于带布局的自定义View(自定义TitleView)_第3张图片
在这里插入图片描述

下面是TitleView:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.constraint.ConstraintLayout;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;

import com.base.lib.R;

public class TitleView extends ConstraintLayout {
    private TextView tvBack;
    private TextView tvRight;
    private TextView tvTitle;
    private TextView tvClose;
    //背景颜色
    private View v_bg;
    //分割栏
    private View barLine;

    private String titleText;
    private int titleTextColor;

    private Drawable backIcon;

    private String rightText;
    private int rightTextColor;

    private int backColor;
    private boolean dividerHide;
    private boolean backHide;
    private boolean closeHide;


    public TitleView(Context context) {
        this(context, null);
    }

    public TitleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TitleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(attrs);
    }

    private void initAttrs(AttributeSet attrs) {

        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.TitleView);
        titleText = typedArray.getString(R.styleable.TitleView_titleText);
        titleTextColor = typedArray.getColor(R.styleable.TitleView_titleColor, ContextCompat.getColor(getContext(), R.color.black));

        backColor = typedArray.getColor(R.styleable.TitleView_backColor, ContextCompat.getColor(getContext(), R.color.white));

        rightText = typedArray.getString(R.styleable.TitleView_rightText);
        rightTextColor = typedArray.getColor(R.styleable.TitleView_rightTextColor, ContextCompat.getColor(getContext(), R.color.black));

        backIcon = typedArray.getDrawable(R.styleable.TitleView_backIcon);
        dividerHide = typedArray.getBoolean(R.styleable.TitleView_dividerHide, false);
        backHide = typedArray.getBoolean(R.styleable.TitleView_backHide, false);
        closeHide = typedArray.getBoolean(R.styleable.TitleView_closeHide, false);

        typedArray.recycle();


    }

    /**
     * 初始化文字标题栏
     */
    private void initView(AttributeSet attrs) {

        initAttrs(attrs);
        View view = View.inflate(getContext(), R.layout.layout_title, this);

        v_bg = view.findViewById(R.id.v_bg);

        tvTitle = view.findViewById(R.id.title_bar_name);
        tvBack = view.findViewById(R.id.title_bar_back);
        tvRight = view.findViewById(R.id.title_bar_right);
        tvClose = view.findViewById(R.id.title_bar_close);

        barLine = view.findViewById(R.id.v_divider_line);

        setTitleColor(titleTextColor);
        setTitleText(titleText);
        setBackgroundColor(backColor);
        setBarLineHide(dividerHide);
        setRightColor(rightTextColor);
        if (null == backIcon) {
            backIcon = ContextCompat.getDrawable(getContext(), R.mipmap.title_bar_back);
            setBackDrawable(backIcon);
        } else {
            setBackDrawable(backIcon);
        }
        setBackHide(backHide);
        setCloseHide(closeHide);

        if (!TextUtils.isEmpty(rightText)) {
            setRightText(rightText);
        }

    }


    /**
     * 设置背景颜色
     *
     * @param color
     */
    public void setBackgroundColor(int color) {
        this.backColor = color;
        if (null != v_bg) {
            v_bg.setBackgroundColor(color);
        }
    }


    /**
     * 设置标题
     *
     * @param title
     */
    public void setTitleText(String title) {
        this.titleText = title;
        if (null != tvTitle) {
            tvTitle.setText(title);
        }
        ;
    }

    /**
     * 设置标题
     */
    public String getTitleText() {
        return titleText;
    }

    /**
     * 设置标题字体颜色
     *
     * @param color
     */
    public void setTitleColor(int color) {
        this.titleTextColor = color;
        tvTitle.setTextColor(color);
    }


    /**
     * 分割线隐藏
     *
     * @param isHide
     */
    public void setBarLineHide(boolean isHide) {
        this.dividerHide = isHide;

        if (isHide) {
            if (barLine.getVisibility() == View.VISIBLE) {
                barLine.setVisibility(View.GONE);
            }
        } else {
            if (barLine.getVisibility() == View.GONE) {
                barLine.setVisibility(View.VISIBLE);
            }
        }

    }

    /**
     * 返回键隐藏
     *
     * @param isHide
     */
    public void setBackHide(boolean isHide) {
        this.backHide = isHide;
        if (null != tvBack) {
            if (isHide) {
                if (tvBack.getVisibility() == View.VISIBLE) {
                    tvBack.setVisibility(View.GONE);
                }
            } else {
                if (tvBack.getVisibility() == View.GONE) {
                    tvBack.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    /**
     * 关闭键隐藏
     *
     * @param isHide
     */
    public void setCloseHide(boolean isHide) {
        this.closeHide = isHide;
        if (null != tvClose) {
            if (isHide) {
                if (tvClose.getVisibility() == View.VISIBLE) {
                    tvClose.setVisibility(View.GONE);
                }
            } else {
                if (tvClose.getVisibility() == View.GONE) {
                    tvClose.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    /**
     * 设置返回键图标
     *
     * @param drawable
     */
    public void setBackDrawable(Drawable drawable) {
        this.backIcon = drawable;
        if (tvBack != null) {
            tvBack.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
        }
    }

    /**
     * 设置返回键监听事件
     */
    public void setOnBackListener(View.OnClickListener clickListener) {

        if (null != tvBack) {
            if (clickListener != null) {
                tvBack.setOnClickListener(clickListener);
            }
        }
    }

    /**
     * 设置右边功能颜色
     */
    public void setRightColor(int color) {
        this.rightTextColor = color;
        if (null != tvRight) {
            tvRight.setTextColor(color);
        }
    }

    /**
     * 设置右边标题文字
     */
    public void setRightText(String title) {
        this.rightText = title;
        if (null != tvRight) {
            tvRight.setText(title);
        }
    }

    /**
     * 设置右边功能监听事件
     */
    public void setOnRightListener(View.OnClickListener clickListener) {
        if (null != tvRight) {
            if (clickListener != null) {
                tvRight.setOnClickListener(clickListener);
            }
        }

    }
}

TitleView继承自ConstraintLayout,加载布局时因为merge的关系 View view = View.inflate(getContext(), R.layout.layout_title, this);这个this一定不能为空。

再贴上attr代码:


        
        
        
        
        
        
        
        
        
        

drawable代码:




    

布局检测:


关于带布局的自定义View(自定义TitleView)_第4张图片
在这里插入图片描述

可以清晰的看到TitleView中没有额外的父布局。

源码

https://github.com/alinainai/Base/blob/master/commonlib/src/main/java/com/base/lib/view/TitleView.java

参考:

https://www.jianshu.com/p/3c6e763d48fc?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weixin-friends
https://www.jianshu.com/p/69e1a3743960

你可能感兴趣的:(关于带布局的自定义View(自定义TitleView))