web-dev-qa-db-ja.com

Javaコードからカスタムディメンション属性を読み取る方法

いくつかのTextViewを組み合わせてカスタムコンポーネントを作成しました。これで、カスタムコントロールをコードから直接初期化して、各テレビのテキストサイズを個別に渡すことができます。

私の属性の定義:

<resources>
    <declare-styleable name="BasicGauge">
        <attr name="valueTextSize" format="dimension" />
        <attr name="titleTextSize" format="dimension" />
        <attr name="unitsTextSize" format="dimension" />
    </declare-styleable>
</resources>

コンポーネントのサンプル初期化:

<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>

コンポーネントのコンストラクターでこれらの属性を読み取る方法:

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();
}

問題:作成後、すべての値はまだnullです。 40spはまさに私の希望する値です。

31
piotrpo

言うべきいくつかのこと:

  • 最初に、Android xmlns:xmlns:foo = "http://schemas.Android。 com/apk/res-auto "
  • 次に、xmlnsをvalueTextSizeの前に付ける必要があります。foo:valueTextSize = "40sp"

その後、文字列を取得することはあまり良い考えではありません、Androidはディメンションを処理するためのより強力なソリューションを提供します:

_int unitsTextSize = typedArray.getDimensionPixelSize(R.styleable.BasicGauge_unitsTextSize, textSize);
_

その後、いくつかのサブティリティがあります:

  • ペイントまたはテキストペイントの場合、この値をそのまま使用できます:Paint.setTextSize(unitTextSize):
  • テキストビューの場合、上記のアプローチは失敗し、正しい結果を得るにはsetTextのオーバーロードを使用する必要があります:textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, unitTextSize);

違いは、「生のピクセル」(密度に応じて拡大縮小されていない、生)と「拡大されたピクセル」(反対)と呼ばれるものに由来します。

60
Snicolas

受け入れられた答えへのもう少しコンテキストのために:

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>

activity.xml

xmlns:app=...で属性を参照し、app:...でXMLに設定します。

<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>

CustomView.Java

getDimensionPixelSizeを使用してTypedArrayから値を取得します。カスタムビュー内では、ピクセルを操作するだけです。別のディメンションに変換する必要がある場合は、 この回答 を参照してください。

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();
        }
    }

    // ...
}
25
Suragch