it-swarm.com.de

Gewusst wie: Definieren eines Designelements (Stilelements) für ein benutzerdefiniertes Widget

Ich habe ein benutzerdefiniertes Widget für ein Steuerelement geschrieben, das wir in unserer gesamten Anwendung häufig verwenden. Die Widget-Klasse leitet sich von ImageButton ab und erweitert sie auf einige einfache Arten. Ich habe einen Stil definiert, den ich auf das Widget anwenden kann, wenn es verwendet wird, aber ich würde es vorziehen, dies über ein Thema einzurichten. Im R.styleable Ich sehe Widget-Stilattribute wie imageButtonStyle und textViewStyle. Gibt es eine Möglichkeit, so etwas für das benutzerdefinierte Widget zu erstellen, das ich geschrieben habe?

81
jsmith

Ja, es gibt einen Weg:

Angenommen, Sie haben eine Attributdeklaration für Ihr Widget (in attrs.xml):

<declare-styleable name="CustomImageButton">
    <attr name="customAttr" format="string"/>
</declare-styleable>

Deklarieren Sie ein Attribut, das Sie als Stilreferenz verwenden möchten (in attrs.xml):

<declare-styleable name="CustomTheme">
    <attr name="customImageButtonStyle" format="reference"/>
</declare-styleable>

Deklarieren Sie eine Reihe von Standardattributwerten für das Widget (in styles.xml):

<style name="Widget.ImageButton.Custom" parent="Android:style/Widget.ImageButton">
    <item name="customAttr">some value</item>
</style>

Deklarieren Sie ein benutzerdefiniertes Thema (in themes.xml):

<style name="Theme.Custom" parent="@Android:style/Theme">
    <item name="customImageButtonStyle">@style/Widget.ImageButton.Custom</item>
</style>

Verwenden Sie dieses Attribut als drittes Argument im Konstruktor Ihres Widgets (in CustomImageButton.Java):

public class CustomImageButton extends ImageButton {
    private String customAttr;

    public CustomImageButton( Context context ) {
        this( context, null );
    }

    public CustomImageButton( Context context, AttributeSet attrs ) {
        this( context, attrs, R.attr.customImageButtonStyle );
    }

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

        final TypedArray array = context.obtainStyledAttributes( attrs,
            R.styleable.CustomImageButton, defStyle,
            R.style.Widget_ImageButton_Custom ); // see below
        this.customAttr =
            array.getString( R.styleable.CustomImageButton_customAttr, "" );
        array.recycle();
    }
}

Jetzt musst du dich bewerben Theme.Custom für alle Aktivitäten, die CustomImageButton verwenden (in AndroidManifest.xml):

<activity Android:name=".MyActivity" Android:theme="@style/Theme.Custom"/>

Das ist alles. Nun versucht CustomImageButton, die Standardattributwerte aus dem customImageButtonStyle Attribut des aktuellen Themas zu laden. Wenn im Design oder im Wert des Attributs kein solches Attribut gefunden wird, ist @null dann wird das letzte Argument für obtainStyledAttributes verwendet: Widget.ImageButton.Custom in diesem Fall.

Sie können die Namen aller Instanzen und aller Dateien ändern (außer AndroidManifest.xml) aber es wäre besser, Android Namenskonvention zu verwenden.

205
Michael

Ein weiterer Aspekt neben Michaels hervorragender Antwort ist das Überschreiben benutzerdefinierter Attribute in Themen. Angenommen, Sie haben eine Reihe von benutzerdefinierten Ansichten, die alle auf das benutzerdefinierte Attribut "custom_background" verweisen.

<declare-styleable name="MyCustomStylables">
    <attr name="custom_background" format="color"/>
</declare-styleable>

In einem Thema definieren Sie den Wert

<style name="MyColorfulTheme" parent="AppTheme">
    <item name="custom_background">#ff0000</item>
</style>

oder

<style name="MyBoringTheme" parent="AppTheme">
    <item name="custom_background">#ffffff</item>
</style>

Sie können in einem Stil auf das Attribut verweisen

<style name="MyDefaultLabelStyle" parent="AppTheme">
    <item name="Android:background">?background_label</item>
</style>

Beachten Sie das Fragezeichen, das auch als Referenz verwendet wird Android Attribut wie in

?android:attr/colorBackground

Wie die meisten von Ihnen bemerkt haben, können und sollten Sie @color-Referenzen anstelle von fest codierten Farben verwenden.

Warum also nicht einfach machen?

<item name="Android:background">@color/my_background_color</item>

Sie können die Definition von "my_background_color" zur Laufzeit nicht ändern, während Sie Themen einfach wechseln können.

4
mir