如何从java代码中读取自定义维度属性

pio*_*rpo 32 android android-layout android-resources

我制作了自定义组件,只是将几个TextView放在一起.现在我希望能够直接从代码启动我的自定义控件,为每个电视独立传递文本大小

我的属性定义:

<resources>
    <declare-styleable name="BasicGauge">
        <attr name="valueTextSize" format="dimension" />
        <attr name="titleTextSize" format="dimension" />
        <attr name="unitsTextSize" format="dimension" />
    </declare-styleable>
</resources>
Run Code Online (Sandbox Code Playgroud)

组件的示例初始化:

<pl.com.digita.BikeComputerUi.customviews.BasicGauge
    android:id="@+id/basicGauge1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:padding="10dp"
    valueTextSize="40sp">

</pl.com.digita.BikeComputerUi.customviews.BasicGauge>
Run Code Online (Sandbox Code Playgroud)

我如何尝试在组件的构造函数中读取这些属性:

final int N = typedArray.getIndexCount();
for (int i = 0; i < N; i++) {
    int attribute = typedArray.getIndex(i);
    switch (attribute) {
        case R.styleable.BasicGauge_valueTextSize:
            valueTextSize = typedArray.getString(attribute);
            break;
        case R.styleable.BasicGauge_titleTextSize:
            titleTextSize = typedArray.getString(attribute);
            break;
        case R.styleable.BasicGauge_unitsTextSize:
            unitsTextSize = typedArray.getString(attribute);
            break;
    }
    typedArray.recycle();
}
Run Code Online (Sandbox Code Playgroud)

问题: 创建后,我的所有值仍为空.40sp正是我想要的值.

Sni*_*las 60

有几点要说:

  • 首先,您需要在xml顶部使用xml名称空间声明行,与android xmlns完全相同:xmlns:foo ="http://schemas.android.com/apk/res-auto"
  • 那么你需要在valueMxtSize前加上你的xmlns:foo:valueTextSize ="40sp"

在那之后,获得一个字符串并不是一个好主意,android提供了更强大的解决方案来处理维度:

int unitsTextSize = typedArray.getDimensionPixelSize(R.styleable.BasicGauge_unitsTextSize, textSize);
Run Code Online (Sandbox Code Playgroud)

然后有一些潜意识:

  • 对于paint或textpaint,你可以这样的值: paint.setTextSize(unitTextSize):
  • 对于textview,上面的方法会失败,你必须使用setText的重载来获得正确的结果: textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, unitTextSize);

不同之处来自于所谓的"原始像素"(根据密度而非缩放,只是原始)和"缩放像素"(相反).


Sur*_*gch 26

对于接受的答案的更多背景:

attrs.xml

使用dimension格式设置自定义属性.

<resources>
    <declare-styleable name="CustomView">
        <attr name="valueTextSize" format="dimension" />
        <attr name="titleTextSize" format="dimension" />
        <attr name="unitsTextSize" format="dimension" />
    </declare-styleable>
</resources>
Run Code Online (Sandbox Code Playgroud)

activity.xml

引用你的属性xmlns:app=...并在你的xml中设置它们app:....

<RelativeLayout 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.example.myproject.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:valueTextSize="40sp"
        app:titleTextSize="20sp"
        app:unitsTextSize="24sp" /> 

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

CustomView.java

使用TypedArray获取值getDimensionPixelSize.在自定义视图中,只需使用像素.如果您需要转换为其他维度,请参阅此答案.

public class CustomView extends View {

    private float mValueTextSize; // pixels
    private float mTitleTextSize; // pixels
    private float mUnitsTextSize; // pixels

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs, R.styleable.CustomView, 0, 0);
        try {
            mValueTextSize = a.getDimensionPixelSize(R.styleable.CustomView_valueTextSize, 0);
            mTitleTextSize = a.getDimensionPixelSize(R.styleable.CustomView_titleTextSize, 0);
            mUnitsTextSize = a.getDimensionPixelSize(R.styleable.CustomView_unitsTextSize, 0);
        } finally {
            a.recycle();
        }
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)