为什么在通过自定义视图属性传递样式时文本不是粗体?

Why text is not bold when passing the style through custom view attributes?

假设我有 .xml 风格:

<style name="MaterialPreviewDetailsTextSmall">
    <item name="android:layout_marginLeft">@dimen/material_margin</item>
    <item name="android:textColor">@color/material_preview_backgroud</item>
    <item name="android:textSize">@dimen/material_normal_smal_text</item>
    <item name="android:textStyle">bold</item>
</style>

我想通过属性将其传递给自定义视图:

<pl.valueadd.ledoc.view.ViewPreviewRow                            
     ...
     app:view_title="@string/equipment_overview_id_label"         
     app:view_title_style="@style/MaterialPreviewDetailsTextSmall"/>

在自定义视图中,我获取样式属性并将其应用于 TextView:

public class ViewPreviewRow extends RelativeLayout {
    TextView tvTitle;

    public ViewPreviewRow(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        initView(context);
        obtainStyledAttributes(context, attrs);
    }

    private void obtainStyledAttributes(Context context, AttributeSet attrs)  {
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.ViewPreviewRow);
        CharSequence text = attributes.getString(R.styleable.ViewPreviewRow_view_title);
        if (text != null) {
            tvTitle.setText(text);
        } else {
            throw new NullPointerException("Attribute view_title cannot be null");
        }
        int appearance = attributes.getResourceId(R.styleable.ViewPreviewRow_view_title_style, 0);
        if (appearance != 0) {
            setTextViewAppearance(tvTitle, appearance);
            tvTitle.requestLayout();
        }
        ...
        attributes.recycle();
    }

问题是:

Why the text has appropriate color, size, marginLeft however is not bold?

我找到了答案。

期待的样式属性可以一一应用:

int appearance = attributes.getResourceId(R.styleable.ViewPreviewRow_view_title_style, 0);
applyBold(context, attrs, appearance, tvTitle);
applyTextSize(context, attrs, appearance, tvTitle);
applyTextColor(context, attrs, appearance, tvTitle);


private void applyBold(Context context, AttributeSet attrs, int style, TextView textView) {
    int[] textStyleAttr = new int[]{android.R.attr.textStyle};
    int indexOfAttrTextStyle = 0;
    TypedArray a = context.obtainStyledAttributes(style, textStyleAttr);
    int styleIndex = a.getInt(indexOfAttrTextStyle, -1);
    a.recycle();
    setTypefaceFromAttrs(textView, styleIndex);
}

private void applyTextSize(Context context, AttributeSet attrs, int style, TextView textView) {
    int[] textStyleAttr = new int[]{android.R.attr.textSize};
    int indexOfAttrTextStyle = 0;
    TypedArray a = context.obtainStyledAttributes(style, textStyleAttr);
    int size = a.getDimensionPixelSize(indexOfAttrTextStyle, -1);
    a.recycle();
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
}

private void applyTextColor(Context context, AttributeSet attrs, int style, TextView textView) {
    int[] textStyleAttr = new int[]{android.R.attr.textColor};
    int indexOfAttrTextStyle = 0;
    TypedArray a = context.obtainStyledAttributes(style, textStyleAttr);
    ColorStateList color = a.getColorStateList(indexOfAttrTextStyle);
    if (color == null) {
        color = ColorStateList.valueOf(a.getColor(indexOfAttrTextStyle, -1));
    }
    a.recycle();
    textView.setTextColor(color);
}

private void setTypefaceFromAttrs(TextView textView, int styleIndex) {
    textView.setTypeface(Typeface.DEFAULT);
    if (styleIndex == 1) {
        textView.setTypeface(null, Typeface.BOLD);
    } else {
        textView.setTypeface(null, Typeface.NORMAL);
    }
}

但是这个解决方案效率很低。它需要为每个预期属性初始化 TypedArray(初始化它是一项非常耗费内存和时间的任务)。但是...它有效。