507

次のように独自の属性を実装する必要がありますcom.android.R.attr

公式ドキュメントには何も見つからなかったので、これらの属性を定義する方法とコードからそれらを使用する方法についての情報が必要です。

4

5 に答える 5

1033

現在、最良のドキュメントはソースです。ここ(attrs.xml)でそれを見ることができます。

<resources>最上位の要素または要素の内部で属性を定義できます<declare-styleable>。複数の場所でattrを使用する場合は、ルート要素に配置します。すべての属性が同じグローバル名前空間を共有することに注意してください。つまり、<declare-styleable>要素の内部で新しい属性を作成した場合でも、その属性は要素の外部で使用でき、同じ名前で異なるタイプの別の属性を作成することはできません。

要素には2つの<attr>xml属性nameとがありformatます。nameあなたはそれを何かと呼ぶことができます、そしてこれはあなたがコードでそれを参照することになる方法です、例えばR.attr.my_attribute。属性は、必要な属性のformat「タイプ」に応じて異なる値を持つことができます。

  • 参照-別のリソースIDを参照する場合(例: "@ color / my_color"、 "@ layout / my_layout")
  • ブール値
  • 寸法
  • 浮く
  • 整数
  • ストリング
  • 分数
  • enum-通常は暗黙的に定義されます
  • フラグ-通常は暗黙的に定義されます

|たとえば、を使用して、フォーマットを複数のタイプに設定できますformat="reference|color"

enum属性は次のように定義できます。

<attr name="my_enum_attr">
  <enum name="value1" value="1" />
  <enum name="value2" value="2" />
</attr>

flag属性は、値を一緒にビット化できるように定義する必要があることを除いて、類似しています。

<attr name="my_flag_attr">
  <flag name="fuzzy" value="0x01" />
  <flag name="cold" value="0x02" />
</attr>

属性に加えて、<declare-styleable>要素があります。これにより、カスタムビューが使用できる属性を定義できます。これを行うには、<attr>要素を指定します。以前に定義されている場合は、を指定しませんformat。android attr、たとえばandroid:gravityを再利用したい場合は、次のように、でそれを行うことができnameます。

カスタムビューの例<declare-styleable>

<declare-styleable name="MyCustomView">
  <attr name="my_custom_attribute" />
  <attr name="android:gravity" />
</declare-styleable>

カスタムビューでXMLでカスタム属性を定義するときは、いくつかのことを行う必要があります。まず、属性を見つけるために名前空間を宣言する必要があります。これは、ルートレイアウト要素で行います。通常は。のみxmlns:android="http://schemas.android.com/apk/res/android"です。ここで、も追加する必要がありますxmlns:whatever="http://schemas.android.com/apk/res-auto"

例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:whatever="http://schemas.android.com/apk/res-auto"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">

    <org.example.mypackage.MyCustomView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:gravity="center"
      whatever:my_custom_attribute="Hello, world!" />
</LinearLayout>

最後に、そのカスタム属性にアクセスするには、通常、カスタムビューのコンストラクターで次のようにアクセスします。

public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);

  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);

  String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);

  //do something with str

  a.recycle();
}

終わり。:)

于 2010-08-09T16:11:24.477 に答える
89

Qberticus の回答は適切ですが、役立つ詳細が 1 つ欠けています。これらをライブラリに実装する場合は、次を置き換えます。

xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"

と:

xmlns:whatever="http://schemas.android.com/apk/res-auto"

そうしないと、ライブラリを使用するアプリケーションで実行時エラーが発生します。

于 2012-11-16T16:18:08.303 に答える
16

上記の回答は、いくつかのことを除いて、すべてを非常に詳細にカバーしています。

まず、スタイルがない場合は、(Context context, AttributeSet attrs)メソッド シグネチャを使用して設定をインスタンス化します。この場合context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)、TypedArray を取得するために使用します。

次に、複数のリソース (数量文字列) の処理方法については説明していません。これらは TypedArray では対応できません。これは、設定の値に従ってその値をフォーマットする設定の概要を設定する私の SeekBarPreference からのコード スニペットです。設定の xml が android:summary をテキスト文字列または文字列リソースに設定する場合、設定の値は文字列にフォーマットされます (値を取得するには、%d が含まれている必要があります)。android:summary が plaurals リソースに設定されている場合、それが結果の書式設定に使用されます。

// Use your own name space if not using an android resource.
final static private String ANDROID_NS = 
    "http://schemas.android.com/apk/res/android";
private int pluralResource;
private Resources resources;
private String summary;

public SeekBarPreference(Context context, AttributeSet attrs) {
    // ...
    TypedArray attributes = context.obtainStyledAttributes(
        attrs, R.styleable.SeekBarPreference);
    pluralResource =  attrs.getAttributeResourceValue(ANDROID_NS, "summary", 0);
    if (pluralResource !=  0) {
        if (! resources.getResourceTypeName(pluralResource).equals("plurals")) {
            pluralResource = 0;
        }
    }
    if (pluralResource ==  0) {
        summary = attributes.getString(
            R.styleable.SeekBarPreference_android_summary);
    }
    attributes.recycle();
}

@Override
public CharSequence getSummary() {
    int value = getPersistedInt(defaultValue);
    if (pluralResource != 0) {
        return resources.getQuantityString(pluralResource, value, value);
    }
    return (summary == null) ? null : String.format(summary, value);
}

  • これは単なる例ですが、設定画面で概要を設定したい場合はnotifyChanged()、設定のonDialogClosedメソッドを呼び出す必要があります。
于 2014-09-03T15:33:47.257 に答える
5

従来のアプローチは定型コードとぎこちないリソース処理でいっぱいです。それが、 Spyglass フレームワークを作成した理由です。どのように機能するかを示すために、文字列タイトルを表示するカスタム ビューを作成する方法を示す例を次に示します。

ステップ 1: カスタム ビュー クラスを作成します。

public class CustomView extends FrameLayout {
    private TextView titleView;

    public CustomView(Context context) {
        super(context);
        init(null, 0, 0);
    }

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

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr, 0);
    }

    @RequiresApi(21)
    public CustomView(
            Context context, 
            AttributeSet attrs,
            int defStyleAttr,
            int defStyleRes) {

        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs, defStyleAttr, defStyleRes);
    }

    public void setTitle(String title) {
        titleView.setText(title);
    }

    private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        inflate(getContext(), R.layout.custom_view, this);

        titleView = findViewById(R.id.title_view);
    }
}

values/attrs.xmlステップ 2:リソース ファイルで文字列属性を定義します。

<resources>
    <declare-styleable name="CustomView">
        <attr name="title" format="string"/>
    </declare-styleable>
</resources>

ステップ 3:メソッドに@StringHandler注釈を適用setTitleして、Spyglass フレームワークに、ビューが膨張したときに属性値をこのメソッドにルーティングするように指示します。

@HandlesString(attributeId = R.styleable.CustomView_title)
public void setTitle(String title) {
    titleView.setText(title);
}

クラスに Spyglass アノテーションが追加されたので、Spyglass フレームワークはコンパイル時にそれを検出し、自動的にCustomView_SpyglassCompanionクラスを生成します。

ステップ 4: カスタム ビューのinitメソッドで生成されたクラスを使用します。

private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    inflate(getContext(), R.layout.custom_view, this);

    titleView = findViewById(R.id.title_view);

    CustomView_SpyglassCompanion
            .builder()
            .withTarget(this)
            .withContext(getContext())
            .withAttributeSet(attrs)
            .withDefaultStyleAttribute(defStyleAttr)
            .withDefaultStyleResource(defStyleRes)
            .build()
            .callTargetMethodsNow();
}

それでおしまい。XML からクラスをインスタンス化すると、Spyglass コンパニオンは属性を解釈し、必要なメソッド呼び出しを行います。たとえば、次のレイアウトをインフレートすると、 が引数としてsetTitle呼び出され"Hello, World!"ます。

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:width="match_parent"
    android:height="match_parent">

    <com.example.CustomView
        android:width="match_parent"
        android:height="match_parent"
        app:title="Hello, World!"/>
</FrameLayout>

フレームワークは文字列リソースに限定されません。他のリソース タイプを処理するためのさまざまな注釈が多数あります。また、デフォルト値を定義するための注釈と、メソッドに複数のパラメーターがある場合にプレースホルダー値を渡すための注釈もあります。

詳細と例については、Github リポジトリをご覧ください。

于 2017-11-20T12:30:36.333 に答える