当前位置: 首页 > 工具软件 > TitleBar > 使用案例 >

自定义Android TitleBar以及开发过程中遇见的问题

康恩
2023-12-01

最近写了好几个小项目,每个title的设计都是大同小异,左边返回按钮中间标题使用文字或者图片,右边也是文字或者图片。大体都是这样的设计,但是每个界面都要画一遍title说实话真的很烦。

1.先画一个titlebar的布局文件 titlebar.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bar_layout"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:background="#51AFF9">
    <TextView
        android:id="@+id/tv_left_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="16dp"
        android:textColor="@android:color/white" />
    <TextView
        android:id="@+id/tv_middle_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:gravity="center"
        android:textColor="@android:color/white" />
    <TextView
        android:id="@+id/tv_right_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="16dp"
        android:gravity="center"
        android:textColor="@android:color/white"
        android:visibility="visible" />
</RelativeLayout>

 2.由于在titlebar中不仅存在文字而且还存在图片,因此我们需要通过TextView的setDrawableLeft去给TextView设置图片,当TextView的Text为空的时候只显示图片

3.在attrs文件中给titlebar定义需要设置参数的一些属性

<declare-styleable name="TitleBar">
        <attr name="leftTitle" format="string" />
        <attr name="middleTitle" format="string" />
        <attr name="rightTitle" format="string" />
        <attr name="leftTextSize" format="dimension" />
        <attr name="middleTextSize" format="dimension" />
        <attr name="rightTextSize" format="dimension" />
        <attr name="leftTextColor" format="color" />
        <attr name="middleTextColor" format="color" />
        <attr name="rightTextColor" format="color" />
        <attr name="leftImage" format="integer" />
        <attr name="rightImage" format="integer" />
        <attr name="tilteBg" format="integer"/>
    </declare-styleable>

 4.通过继承Relativelayout来实现自定义控件,给Titlebar设置属性

public class Titlebar extends RelativeLayout implements View.OnClickListener {
    private String leftTitle;
    private String middleTitle;
    private String rightTitle;

    private int leftTextColor;
    private int middleTextColor;
    private int rightTextColor;
    private int bgColor;

    private float leftTextSize;
    private float rightTextSize;
    private float middleTextSize;

    private TextView tvLeft;
    private TextView tvMiddle;
    private TextView tvRight;
    private RelativeLayout rlBg;

    private int leftImage;
    private int rightImage;

    private TitleClickListener listener;




    public CustomerTitlebar(Context context) {
        super(context);
    }

    public CustomerTitlebar(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomTitleBar, 0, 0);
        initView(array);
        array.recycle();

    }

    public CustomerTitlebar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomTitleBar, defStyleAttr, 0);
        initView(array);
        array.recycle();
    }

    private void initView(TypedArray array) {
        LayoutInflater.from(getContext()).inflate(R.layout.titlebar_customer, this);
        tvLeft = findViewById(R.id.tv_left_title);
        tvLeft.setOnClickListener(this);
        tvMiddle = findViewById(R.id.tv_middle_title);
        tvMiddle.setOnClickListener(this);
        tvRight = findViewById(R.id.tv_right_title);
        tvRight.setOnClickListener(this);
        rlBg = findViewById(R.id.bar_layout);
        leftTitle = array.getString(R.styleable.CustomTitleBar_leftTitle);
        middleTitle = array.getString(R.styleable.CustomTitleBar_middleTitle);
        rightTitle = array.getString(R.styleable.CustomTitleBar_rightTitle);
        leftTextColor = array.getColor(R.styleable.CustomTitleBar_leftTextColor, Color.GRAY);
        middleTextColor = array.getColor(R.styleable.CustomTitleBar_middleTextColor, Color.TRANSPARENT);
        rightTextColor = array.getColor(R.styleable.CustomTitleBar_rightTextColor, Color.GRAY);
        bgColor = array.getColor(R.styleable.CustomTitleBar_tilteBg,Color.GRAY);

        leftImage = array.getResourceId(R.styleable.CustomTitleBar_leftImage, 0);
        rightImage = array.getResourceId(R.styleable.CustomTitleBar_rightImage, 0);
        leftTextSize = array.getDimension(R.styleable.CustomTitleBar_leftTextSize, DensityUtil.dip2px(getContext(), 15));
        rightTextSize = array.getDimension(R.styleable.CustomTitleBar_rightTextSize, DensityUtil.dip2px(getContext(), 17));
        middleTextSize = array.getDimension(R.styleable.CustomTitleBar_middleTextSize, DensityUtil.dip2px(getContext(), 15));
        if (leftImage > 0) {
            setLeftImage(leftImage);
        } else {
            setLeftTitle(leftTitle);
        }
        if (rightImage > 0) {
            setRightImage(rightImage);
        } else {
            setRightTitle(rightTitle);
        }
        tvLeft.setTextSize(TypedValue.COMPLEX_UNIT_PX, leftTextSize);
        tvRight.setTextSize(TypedValue.COMPLEX_UNIT_PX, rightTextSize);
        tvMiddle.setTextSize(TypedValue.COMPLEX_UNIT_PX, middleTextSize);

        setMiddleTitle(middleTitle);
        setLeftTextColor(leftTextColor);
        setMiddleTextColor(middleTextColor);
        setRightTextColor(rightTextColor);
        setTitleBarColor(bgColor);
    }
    public void setTitleBarColor(int color){
        rlBg.setBackgroundColor(color);
    }
    /**
     * @param size 单位sp
     */
    public void setLeftTextSize(float size) {
        tvLeft.setTextSize(size);
    }

    /**
     * @param size 单位sp
     */
    public void setMiddleTextSize(float size) {
        tvMiddle.setTextSize(size);
    }

    /**
     * @param size 单位sp
     */
    public void setRightTextSize(float size) {
        tvRight.setTextSize(size);
    }

    public void setLeftTextColor(int color) {
        tvLeft.setTextColor(color);
    }

    public void setMiddleTextColor(int color) {
        tvMiddle.setTextColor(color);
    }

    public void setRightTextColor(int color) {
        tvRight.setTextColor(color);
    }

    public void setLeftTitle(String title) {
        tvLeft.setText(title);
    }

    public void setRightTitle(String title) {
        tvRight.setText(title);
    }

    public void setMiddleTitle(String title) {
        tvMiddle.setText(title);
    }

    public void setLeftImage(int leftImage) {
        setLeftTitle(leftTitle);
        Drawable drawable = getResources().getDrawable(leftImage);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        tvLeft.setCompoundDrawablePadding(DensityUtil.dip2px(getContext(), 8));
        tvLeft.setCompoundDrawables(drawable, null, null, null);
    }

    public void setRightImage(int rightImage) {
        setRightTitle(rightTitle);
        Drawable drawable = getResources().getDrawable(rightImage);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        tvRight.setCompoundDrawablePadding(DensityUtil.dip2px(getContext(), 8));
        tvRight.setCompoundDrawables(null, null, drawable, null);
    }




    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.tvLeftTitle) {
            if (listener != null) {
                listener.onLeftClick();
            }
        } else if (id == R.id.tvRightTitle) {
            if (listener != null) {
                listener.onRightClick();
            }

        }
    }
    public void setTitleClickListener(TitleClickListener listener) {
        this.listener = listener;
    }
    public interface TitleClickListener {
        void onLeftClick();
        void onRightClick();
    }
}

5.写到这边基本上自定义的titleBar就可以投入使用了,然后就是在使用的layout布局中引用了

<com.victorfactory.commonui.titlebar.Titlebar
        android:id="@+id/tablelayout_title_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tilteBg = "@color/bg_51AFF9"
        app:leftImage="@mipmap/ic_arrow_left"
        app:middleTitle= "tablelayout"
        app:rightTitle="关闭"
        app:middleTextSize = "16sp"
        app:rightTextSize = "14sp"
        app:middleTextColor = "@color/white"
        app:rightTextColor = "@color/white" />

6.在开发的过程中遇到的问题

(1).在自定义titlebar的时候,在写构造函数的时候,把titlebar所有的属性设置都放在了三个参数的的构造函数里面,然后界面一直显示不出来,后面看了资料才清楚原来自定义控件如果设置style的话,会使用三个参数的构造函数,如果只是使用attrs,那么只使就是用两个参数的构造函数

(2).在设置字体大小的时候把COMPLEX_UNIT_PX换成COMPLEX_UNIT_SP的话,整个字体会放大两倍。

/**
     * Converts an unpacked complex data value holding a dimension to its final floating 
     * point value. The two parameters <var>unit</var> and <var>value</var>
     * are as in {@link #TYPE_DIMENSION}.
     *  
     * @param unit The unit to convert from.
     * @param value The value to apply the unit to.
     * @param metrics Current display metrics to use in the conversion -- 
     *                supplies display density and scaling information.
     * 
     * @return The complex floating point value multiplied by the appropriate 
     * metrics depending on its unit. 
     */
    public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }
参考了一下源代码,大概意思是根据不同厂商设备,不同分辨率的手机去适配字体的大小。不知道理解的对不对。但是最后还是换回了COMPLEX_NUIT_PX。因为COMPLEX_UNIT_PX在我的手机上显示的字体太大了!

 

 类似资料: