首页
登录 | 注册

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

自定义控件组的时候如果遇到想通过自定义的属性设置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的到的

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

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

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

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

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



2020 jeepxie.net webmaster#jeepxie.net
10 q. 0.009 s.
京ICP备10005923号