web-dev-qa-db-ja.com

カスタムコンポーネントのAttributeSetの属性へのアクセス

カスタムサイズ設定メソッドがオンになっている2つのTextViewを含むカスタムコンポーネントがあります(2つのテキストビューは約1:2の比率で比例しています)。これはRelativeLayoutのサブクラスであるため、textSize属性はありませんが、このコンポーネントのXMLインスタンス化で_Android:textSize_属性を設定してから、textSizeを取得できるかどうか疑問に思っています。コンストラクターのカスタムsetSize()メソッドで使用するAttributeSetの属性。

カスタム属性を使用してこれを行う手法を見てきましたが、すでにAndroidレキシコンにある属性を取得したい場合はどうなりますか?

20
Josh Kovach

はい、可能です。

(xml内の)RelativeLayout宣言に14spで定義されたtextSizeがあると仮定しましょう:

Android:textSize="14sp"

カスタムビュー(AttributeSetを取り込むもの)のコンストラクターでは、Androidの名前空間から属性を次のように取得できます。

String xmlProvidedSize = attrs.getAttributeValue("http://schemas.Android.com/apk/res/Android", "textSize");

XmlProvidedSizeの値は、この「14.0sp」のようなものになります。文字列を少し編集するだけで、数値を抽出できます。


独自の属性セットを宣言する別のオプションは少し長くなりますが、それも可能です。

したがって、カスタムビューがあり、TextViewsは次のようなものを宣言しています。

public class MyCustomView extends RelativeLayout{

    private TextView myTextView1;
    private TextView myTextView2;

// rest of your class here

すごい...

次に、カスタムビューが次のようにAttributeSetを取り込むコンストラクターをオーバーライドすることも確認する必要があります。

public MyCustomView(Context context, AttributeSet attrs){   
    super(context, attrs);
    init(attrs, context);  //Nice, clean method to instantiate your TextViews// 
}

では、init()メソッドを見てみましょう。

private void init(AttributeSet attrs, Context context){
    // do your other View related stuff here //


    TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyCustomView);
    int xmlProvidedText1Size = a.int(R.styleable.MyCustomView_text1Size);
    int xmlProvidedText2Size = a.int(R.styleable.MyCustomView_text2Size);

    myTextView1.setTextSize(xmlProvidedText1Size);
    myTextView2.setTextSize(xmlProvidedText2Size);

    // and other stuff here //
}

R.styleable.MyCustomView、R.styleable.MyCustomView_text1Size、およびR.styleable.MyCustomView_text2Sizeはどこから来ているのか疑問に思われるかもしれません。それらについて詳しく説明させてください。

Attrs.xmlファイル(valuesディレクトリの下)で属性名を宣言して、カスタムビューを使用するときはいつでも、これらの属性から収集された値がコンストラクターに渡されるようにする必要があります。

それで、あなたが尋ねたようにこれらのカスタム属性をどのように宣言するか見てみましょう:これが私のattrs.xml全体です

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomView">
        <attr name="text1Size" format="integer"/>
        <attr name="text2Size" format="integer"/>
    </declare-styleable>
</resources>

これで、XMLでTextViewのサイズを設定できますが、レイアウトで名前空間を宣言せずに設定することはできません。方法は次のとおりです。

<com.my.app.package.MyCustomView
    xmlns:josh="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/my_custom_view_id"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    josh:text1Size="15"
    josh:text2Size="30"     
    />

CustomViewの属性セットの最初の行として名前空間を「josh」として宣言した方法に注意してください。

これがジョシュに役立つことを願っています、

70
serkanozel

受け入れられた答えは少し長いです。これは私が簡単に理解できることを願っている要約版です。 textSize属性(またはdp/spを使用するもの)をカスタムビューに追加するには、次の手順を実行します。

1.カスタム属性を作成します

attrs.xmlに作成(または次のセクションを追加)します。 dimension 形式に注意してください。

<resources>
    <declare-styleable name="CustomView">
        <attr name="textSize" format="dimension" />
    </declare-styleable>
</resources>

2.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:textSize="20sp" /> 

</RelativeLayout>

3.カスタムビューで属性値を取得します

getDimensionPixelSizeの使用に注意してください。カスタムビュー内では、ピクセルを操作するだけです。別の次元に変換する必要がある場合は、 この回答 を参照してください。

public class CustomView extends View {

    private float mTextSize; // pixels

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs, R.styleable.CustomView, 0, 0);
        try {
            mTextSize = a.getDimensionPixelSize(R.styleable.CustomView_textSize, 0);
        } finally {
            a.recycle();
        }
    }

    /**
     * @param size in SP units
     */
    public void setTextSize(int size) {
        mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                size, getResources().getDisplayMetrics());
        mTextPaint.setTextSize(mTextSize);
        invalidate();
        requestLayout();
    }

    // ...
}

ノート

1
Suragch