Nasıl yapılır: Özel widget için tema (stil) öğesini tanımlama


88

Uygulamamız genelinde yaygın olarak kullandığımız bir denetim için özel bir pencere öğesi yazdım. Widget sınıfı, ImageButtonbirkaç basit yoldan türetilir ve onu genişletir. Widget kullanılırken uygulayabileceğim bir stil tanımladım, ancak bunu bir tema aracılığıyla ayarlamayı tercih ederim. İçinde ve R.styleablegibi widget stili nitelikleri görüyorum . Yazdığım özel pencere öğesi için böyle bir şey oluşturmanın bir yolu var mı?imageButtonStyletextViewStyle

Yanıtlar:


211

Evet, bir yol var:

Widget'ınız (in attrs.xml) için bir öznitelik beyanınız olduğunu varsayalım :

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

Bir stil referansı (in attrs.xml) için kullanacağınız bir özniteliği bildirin :

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

Widget (in styles.xml) için bir dizi varsayılan öznitelik değeri bildirin :

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

Özel bir tema bildirin (içinde themes.xml):

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

Bu özniteliği, pencere aracınızın yapıcısındaki (in CustomImageButton.java) üçüncü argüman olarak kullanın :

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

Şimdi Theme.Customkullanan tüm etkinliklere başvurmanız gerekir CustomImageButton(AndroidManifest.xml'de):

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

Bu kadar. Şimdi CustomImageButtonvarsayılan öznitelik değerlerini şuradan yüklemeye çalışıyor:customImageButtonStyle , mevcut temanın özniteliğinden . Temada veya özniteliğin değerinde böyle bir öznitelik bulunmazsa , bu durumda kullanılacak @nullson bağımsız değişken obtainStyledAttributeskullanılır: Widget.ImageButton.Custombu durumda.

Tüm örneklerin ve tüm dosyaların (hariç AndroidManifest.xml) adlarını değiştirebilirsiniz, ancak Android adlandırma kuralını kullanmak daha iyi olacaktır.


4
Bir tema kullanmadan aynı şeyi yapmanın bir yolu var mı? Bazı özel widget'larım var, ancak kullanıcıların bu widget'ları istedikleri herhangi bir temayla kullanabilmesini istiyorum. Yayınladığınız şekilde yapmak, kullanıcıların temamı kullanmasını gerektirir.
theDazzler

3
@theDazzler: Geliştiricilerin kullanabileceği bir kitaplığı kastediyorsanız, kendi temalarını oluşturabilecek ve temadaki bir stil niteliğini kullanarak widget için stili belirleyebilecekler ( customImageButtonStylebu cevapta). Android'de eylem çubuğu bu şekilde özelleştirilir. Ve çalışma zamanında bir temayı değiştirmeyi kastediyorsanız, bu yaklaşımla bu mümkün değildir.
Michael

@Michael, Evet, geliştiricilerin kullanabileceği bir kitaplığı kastetmiştim. Yorumunuz sorunumu çözdü. Teşekkürler!
theDazzler

32
Tüm bunlarla ilgili en şaşırtıcı şey, Google'dan birinin bunun uygun olduğunu düşünmesidir.
Glenn Maynard

1
Does name="CustomTheme"içinde declare-styleableherhangi bir amaca hizmet sarıcı öznitelik? Bu sadece organizasyon için mi, çünkü hiçbir yerde kullanıldığını görmüyorum. Çeşitli gereçler için tüm stil özelliklerimi tek bir sarmalayıcıya koyabilir miyim?
Tenfour04

4

Michael'ın mükemmel cevabına ek olarak bir başka husus, temalardaki özel nitelikleri geçersiz kılmaktır. Tümünün "custom_background" özel özniteliğine başvuran bir dizi özel görünümünüz olduğunu varsayalım.

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

Bir temada değerin ne olduğunu tanımlarsınız

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

veya

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

Özniteliğe bir stilde başvurabilirsiniz

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

Soru işaretine dikkat edin, aynı zamanda aşağıdaki gibi referans android özelliği için de kullanılır.

?android:attr/colorBackground

Çoğunuzun fark ettiği gibi, sabit kodlanmış renkler yerine @color referanslarını kullanabilirsiniz ve muhtemelen kullanmalısınız.

Öyleyse neden sadece yapmıyorsun

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

"My_background_color" tanımını çalışma zamanında değiştiremezsiniz, oysa temaları kolayca değiştirebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.