Domanda

Ho bisogno di implementare il proprio attributi come in com.android.R.attr

Trovato niente nella documentazione ufficiale, quindi ho bisogno di informazioni su come definire gli attributi e il loro utilizzo da il mio codice.

È stato utile?

Soluzione

Al momento la documentazione migliore è la fonte. Si può dare un'occhiata a questo qui (attrs. xml) .

È possibile definire gli attributi nell'elemento superiore <resources> o all'interno di un elemento <declare-styleable>. Se ho intenzione di utilizzare un attr in più di un posto ho messo nel l'elemento radice. Nota, tutti gli attributi condividono lo stesso spazio dei nomi globale. Ciò significa che anche se si crea un nuovo attributo all'interno di un elemento <declare-styleable> può essere al di fuori di esso utilizzato e non è possibile creare un altro attributo con lo stesso nome di un tipo diverso.

Un elemento <attr> ha due attributi XML name e format. name ti permette di chiamare qualcosa e questo è come si finisce riferendosi ad esso nel codice, ad esempio, R.attr.my_attribute. L'attributo format può avere valori diversi a seconda del 'tipo' di attributo che si desidera.

  • di riferimento - se fa riferimento a un altro ID di risorsa (per esempio, "@ colore / my_color", "@ Layout / my_layout")
  • color
  • booleano
  • dimensione
  • float
  • integer
  • stringa
  • frazione
  • enum - normalmente definito implicitamente
  • Bandiera - normalmente definito implicitamente

È possibile impostare il formato a più tipi utilizzando |, per esempio, format="reference|color".

attributi enum possono essere definiti come segue:

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

attributi flag sono simili, tranne i valori devono essere definite in modo che possano essere po ORed insieme:

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

In aggiunta agli attributi v'è l'elemento <declare-styleable>. Ciò consente di definire gli attributi di una visualizzazione personalizzata può utilizzare. A tale scopo, specificando un elemento <attr>, se è stato precedentemente definito non si specifica il format. Se si desidera riutilizzare un attr Android, per esempio, Android:. Gravità, allora si può fare che nel name, come segue

Un esempio di <declare-styleable> visualizzazione personalizzata:

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

Quando si definisce tuoi attributi personalizzati in XML sul vostro visualizzazione personalizzata è necessario fare alcune cose. In primo luogo è necessario dichiarare uno spazio dei nomi per trovare i tuoi attributi. A tale scopo, sull'elemento di layout radice. Normalmente c'è solo xmlns:android="http://schemas.android.com/apk/res/android". È necessario ora anche aggiungere xmlns:whatever="http://schemas.android.com/apk/res-auto".

Esempio:

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

Infine, per l'accesso quell'attributo personalizzato normalmente farlo nel costruttore della vostra visualizzazione personalizzata come segue.

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

La fine. :)

Altri suggerimenti

La risposta di Qberticus è buona, ma un dettaglio utile è mancante. Se si implementa questi in una libreria di sostituzione:

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

con:

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

In caso contrario, l'applicazione che utilizza la libreria avrà errori di runtime.

La risposta di cui sopra copre tutto con dovizia di particolari, a parte un paio di cose.

In primo luogo, se non ci sono gli stili, allora il metodo firma (Context context, AttributeSet attrs) verrà utilizzato per creare un'istanza la preferenza. In questo caso basta usare context.obtainStyledAttributes(attrs, R.styleable.MyCustomView) per ottenere il TypedArray.

In secondo luogo, non copre come trattare con plaurals risorse (stringhe quantità). Questi non possono essere affrontate utilizzando TypedArray. Ecco un frammento di codice dal mio SeekBarPreference che imposta la sintesi della preferenza formattazione suo valore in base al valore della preferenza. Se l'XML per il set di preferenze android: sintesi di una stringa di testo o di una stringa resouce il valore della preferenza è formattato nella stringa (che dovrebbe avere% d in esso, far salire il valore). Se Android:. Sintesi è impostato su una risorsa plaurals, che poi viene utilizzato per formattare il risultato

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

  • Questo è solo a titolo di esempio, tuttavia, se si vuole sono tentati di impostare la sintesi sulla schermata delle preferenze, allora avete bisogno di chiamare notifyChanged() nel metodo onDialogClosed della preferenza.

L'approccio tradizionale è pieno di codice standard, goffo e metodologie di gestione delle risorse.Ecco perché ho fatto la Spyglass quadro.Per dimostrare come funziona, ecco un esempio che mostra come creare una visualizzazione personalizzata che consente di visualizzare una Stringa del titolo.

Passaggio 1:Creare una classe personalizzata per la visualizzazione.

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

Passaggio 2:Definire un attributo stringa in values/attrs.xml il file di risorse:

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

Passo 3:Applicare il @StringHandler annotazione per il setTitle metodo per raccontare la Spyglass quadro per instradare il valore dell'attributo per questo metodo quando la vista è gonfiato.

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

Ora che la classe ha Canocchiale, annotazione, Spyglass quadro rileverà a tempo di compilazione e generare automaticamente il CustomView_SpyglassCompanion classe.

Passo 4:Utilizzare la classe generata nella visualizzazione personalizzata del init metodo:

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

Che è.Ora, quando si crea un'istanza della classe XML, Spyglass compagno interpreta gli attributi e rende necessaria la chiamata al metodo.Per esempio, se si gonfia il seguente layout quindi setTitle verrà chiamato con "Hello, World!" come argomento.

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

Il quadro non è limitato a risorse di tipo stringa ha un sacco di diverse annotazioni per la gestione di altri tipi di risorse.Ha anche le annotazioni per la definizione dei valori di default e per passare i valori segnaposto se i vostri metodi sono molteplici parametri.

Guarda il repo Github per ulteriori informazioni ed esempi.

se si omette l'attributo format dall'elemento attr, lo si può utilizzare per fare riferimento a una classe da schemi XML.

  • esempio da attrs.xml .
  • Android Studio capisce che la classe viene fatto riferimento da XML
    • vale a dire.
      • Refactor > Rename funziona
      • Find Usages funziona
      • e così via ...

non specificare un attributo format in ... / src / main / res / Valori / attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyCustomView">
        ....
        <attr name="give_me_a_class"/>
        ....
    </declare-styleable>

</resources>

usarlo in qualche file di layout ... / src / main / res / layout / activity__main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- make sure to use $ dollar signs for nested classes -->
    <MyCustomView
        app:give_me_a_class="class.type.name.Outer$Nested/>

    <MyCustomView
        app:give_me_a_class="class.type.name.AnotherClass/>

</SomeLayout>

analizzare la classe nel codice di inizializzazione visualizzazione ... / src / main / java /.../ MyCustomView.kt

class MyCustomView(
        context:Context,
        attrs:AttributeSet)
    :View(context,attrs)
{
    // parse XML attributes
    ....
    private val giveMeAClass:SomeCustomInterface
    init
    {
        context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
        {
            try
            {
                // very important to use the class loader from the passed-in context
                giveMeAClass = context::class.java.classLoader!!
                        .loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
                        .newInstance() // instantiate using 0-args constructor
                        .let {it as SomeCustomInterface}
            }
            finally
            {
                recycle()
            }
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top