自定义控件通过属性设置TextSize时遇到的一些问题

来源:互联网 发布:吴佩频道知乎 编辑:程序博客网 时间:2024/05/29 18:05

自定义控件组的时候如果遇到想通过自定义的属性设置TextView字体大小时如何圆满解决TypedArray.getDimension取到的不是你想要的值的问题。

1、这里我的需求是自定义一个TitleBar控件组,但过程中发现无法通过属性很好的去控制TextView的字体大小。

在这里还是先把自定义控件组的代码先贴一下,虽然百度一下很多很多。

attrs_title_bar.xml

<resources>    <declare-styleable name="TitleBar">        <attr name="centerString" format="string" />        <attr name="centerColor" format="color" />        <attr name="centerTextDimension" format="dimension" />        <attr name="centerTextSizeSp" format="integer" />        <attr name="leftImageDrawable" format="reference" />        <attr name="rightImageDrawable" format="reference" />    </declare-styleable></resources>

ids.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <item type="id" name="title_bar"/>    <item type="id" name="title_bar_main_layout"/>    <item type="id" name="title_bar_left_image"/>    <item type="id" name="title_bar_left_button"/>    <item type="id" name="title_bar_center_text"/>    <item type="id" name="title_bar_right_image"/>    <item type="id" name="title_bar_right_button"/></resources>

title_bar.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="56dp"    android:paddingLeft="10dp"    android:paddingRight="10dp">    <ImageView        android:id="@id/title_bar_left_image"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentLeft="true"        android:layout_centerVertical="true"        android:src="@mipmap/ic_launcher"        android:visibility="gone"/>    <TextView        android:id="@id/title_bar_center_text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:maxLines="1"        android:text="Msg"        android:layout_centerInParent="true"/>    <ImageView        android:id="@id/title_bar_right_image"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:layout_centerVertical="true"        android:src="@mipmap/ic_launcher"        android:visibility="gone"/>    <Button        android:id="@id/title_bar_right_button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:layout_centerVertical="true"        android:visibility="gone"/></RelativeLayout>

使用自定义View的地方

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent">    <com.*******.view.TitleBar        android:layout_width="300dp"        android:layout_height="300dp"        android:background="#ccc"        android:paddingBottom="40dp"        android:paddingLeft="20dp"        app:centerColor="#33b5e5"        app:centerTextDimension="24sp"        app:centerTextSizeSp="18"        app:centerString="Hello, TitleBar" /></FrameLayout>

自定义TitleBar控件代码

package com.******.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.LayoutInflater;import android.widget.Button;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.TextView;import com.******.R;/** * @author linboliu */public class TitleBar extends RelativeLayout {    private ImageView mLeftImage;    private ImageView mRightImage;    private TextView mCenterTextView;    private Button mRightButton;    private String mCenterString; // TODO: use a default from R.string...    private int mCenterColor = Color.RED; // TODO: use a default from R.color...    private float mCenterDimension = 0; // TODO: use a default from R.dimen...    private int mCenterTextSizeSp = 0;    private Drawable mLeftDrawable;    public TitleBar(Context context) {        super(context);        init(context, null, 0);    }    public TitleBar(Context context, AttributeSet attrs) {        super(context, attrs);        init(context, attrs, 0);    }    public TitleBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context, attrs, defStyle);    }    private void init(Context context, AttributeSet attrs, int defStyle) {        LayoutInflater.from(context).inflate(R.layout.title_bar, this, true);        mLeftImage = (ImageView) findViewById(R.id.title_bar_left_image);        mRightImage = (ImageView) findViewById(R.id.title_bar_right_image);        mRightButton = (Button) findViewById(R.id.title_bar_right_button);        mCenterTextView = (TextView) findViewById(R.id.title_bar_center_text);        // Load attributes        final TypedArray a = getContext().obtainStyledAttributes(                attrs, R.styleable.TitleBar, defStyle, 0);        mCenterString = a.getString(                R.styleable.TitleBar_centerString);        mCenterColor = a.getColor(                R.styleable.TitleBar_centerColor,                mCenterColor);        // Use getDimensionPixelSize or getDimensionPixelOffset when dealing with        // values that should fall on pixel boundaries.        mCenterDimension = a.getDimensionPixelSize(                R.styleable.TitleBar_centerTextDimension, 0);        mCenterTextSizeSp = a.getInteger(R.styleable.TitleBar_centerTextSizeSp, 0);        if (a.hasValue(R.styleable.TitleBar_leftImageDrawable)) {            mLeftDrawable = a.getDrawable(                    R.styleable.TitleBar_leftImageDrawable);            mLeftDrawable.setCallback(this);        }        a.recycle();        setValues();    }    private void setValues() {        if (mCenterTextView != null) {            mCenterTextView.setText(mCenterString);            mCenterTextView.setTextColor(mCenterColor);            Log.d("TitleBar", "mCenterDimension:" + mCenterDimension);            Log.d("TitleBar", "mCenterTextSizeSp:" + mCenterTextSizeSp);            if (mCenterTextSizeSp > 0) {                mCenterTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mCenterTextSizeSp);            } else {                mCenterTextView.setTextSize(mCenterDimension);            }        }    }}

由于 TypedArray.getDimension 这个方法取到的值并不是我们在属性中设置的值

        app:centerColor="#33b5e5"        app:centerTextDimension="24sp"        app:centerTextSizeSp="18"        app:centerString="Hello, TitleBar"

这里如果在代码中getDimension 去获取app:centerTextDimension这个属性的话并不能得到24,而是根据不同手机分辨率和dpi的到的

Attribute dimension value multiplied by the appropriate metric

为了能方便的使用sp去设置控件组中TextView的字体大小,这里重新定义了一个属性

<attr name="centerTextSizeSp" format="integer" />

这个属性参数格式为integer类型
在代码中通过 getInteger 就能得到我们想要的确定的值

mCenterTextSizeSp = a.getInteger(R.styleable.TitleBar_centerTextSizeSp, 0);

然后设置字体大小的时候带上 TypedValue.COMPLEX_UNIT_SP 参数,就能解决前面的问题了

mCenterTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mCenterTextSizeSp);

不用在纠结getDimension、getDimensionPixelSize、getDimensionPixelOffset到底哪个值才对,都不是我想要的,再见!

如果是自绘View的话还是可以用getDimension,不赘述了!

0 0