XML kullanarak özel bir android UI öğesi bildirme


Yanıtlar:


840

Android Geliştirici Kılavuzu'nda Özel Bileşenler Oluşturma adlı bir bölüm vardır . Ne yazık ki XML özniteliklerinin tartışılması, yalnızca mizanpaj dosyasının içindeki denetimin bildirilmesini kapsar ve sınıf başlatma içindeki değerleri işlemez. Adımlar aşağıdaki gibidir:

1. içindeki özellikleri values\attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomView">
        <attr name="android:text"/>
        <attr name="android:textColor"/>            
        <attr name="extraInformation" format="string" />
    </declare-styleable>
</resources>

declare-styleableEtikette niteliksiz bir ad kullanıldığına dikkat edin . Standart olmayan android özelliklerinin extraInformationtürlerinin bildirilmesi gerekir. Üst sınıfta bildirilen etiketler, yeniden sınıflandırılmak zorunda kalmadan alt sınıflarda bulunacaktır.

2. Oluşturucu oluşturma

AttributeSetBaşlatma için bir kullanan iki kurucu olduğundan , kurucuların çağırması için ayrı bir başlatma yöntemi oluşturmak uygundur.

private void init(AttributeSet attrs) { 
    TypedArray a=getContext().obtainStyledAttributes(
         attrs,
         R.styleable.MyCustomView);

    //Use a
    Log.i("test",a.getString(
         R.styleable.MyCustomView_android_text));
    Log.i("test",""+a.getColor(
         R.styleable.MyCustomView_android_textColor, Color.BLACK));
    Log.i("test",a.getString(
         R.styleable.MyCustomView_extraInformation));

    //Don't forget this
    a.recycle();
}

R.styleable.MyCustomViewint[]her öğenin bir özniteliğin kimliği olduğu otomatik olarak oluşturulmuş bir kaynaktır. Öznitelikler, öznitelik adı öğe adına eklenerek XML'deki her özellik için oluşturulur. Örneğin, R.styleable.MyCustomView_android_textiçin android_textözniteliği içerir MyCustomView. Öznitelikler daha sonra TypedArrayçeşitli getfonksiyonlar kullanılarak alınabilir . Öznitelik XML'de tanımlı olarak tanımlanmamışsa nulldöndürülür. Tabii ki, dönüş türü bir ilkel ise, bu durumda ikinci argüman döndürülür.

Eğer özelliklerin tümünü almak istemiyorsanız, içerdiği standart android özellik için bu diziyi manually.The kimliği oluşturmak mümkündür android.R.attr, bu proje için nitelikler içinde iken, R.attr.

int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};

Eğer gerektiğini lütfen not değil başka bir araç kullanmayı android.R.styleablegöre, bu iş parçacığı gelecekte değişebilir. Tüm bu sabitleri tek bir yerde görmek faydalı olmaya devam ediyor.

3. gibi bir düzen dosyalarında kullanın layout\main.xml

xmlns:app="http://schemas.android.com/apk/res-auto"Üst düzey xml öğesine ad alanı bildirimini ekleyin . Ad alanları, farklı şemalar aynı öğe adlarını kullandığında bazen oluşan çakışmalardan kaçınmak için bir yöntem sağlar ( daha fazla bilgi için bu makaleye bakın ). URL, şemaları benzersiz bir şekilde tanımlamanın bir yoludur - aslında bu URL'de hiçbir şeyin barındırılması gerekmez . Bu hiçbir şey yapmıyor gibi görünüyorsa, bunun nedeni, bir çakışmayı çözmeniz gerekmedikçe ad alanı önekini eklemeniz gerekmemesidir.

<com.mycompany.projectname.MyCustomView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:text="Test text"
    android:textColor="#FFFFFF"
    app:extraInformation="My extra information"
/> 

Tam adı kullanarak özel görünüme başvurun.

Android LabelView Örneği

Tam bir örnek istiyorsanız, android etiket görünümü örneğine bakın.

LabelView.java

 TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
 CharSequences=a.getString(R.styleable.LabelView_text);

attrs.xml

<declare-styleable name="LabelView">
    <attr name="text"format="string"/>
    <attr name="textColor"format="color"/>
    <attr name="textSize"format="dimension"/>
</declare-styleable>

custom_view_1.xml

<com.example.android.apis.view.LabelView
    android:background="@drawable/blue"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    app:text="Blue" app:textSize="20dp"/>

Bu, LinearLayoutbir ad alanı özniteliğine sahip bir:xmlns:app="http://schemas.android.com/apk/res-auto"

Bağlantılar


14
Kök öğeniz özel ad alanınızı gerektiriyorsa, hem standart android ad alanını hem de kendi özel alanınızı eklemeniz gerekeceğini ya da derleme hatalarıyla karşılaşabileceğinizi eklemek isterim.
Chase

11
Bu cevap, bulabildiğim özel XML parametrelerinde Internet'teki en açık kaynaktır. Teşekkürler Casebash.
Artem Russakovskii

2
herhangi bir nedenle, görsel düzenleyici android için yazılı metin değerini kullanmayı reddediyor: metin, ancak cihaz bunu iyi kullanıyor. nasıl olur ?
android geliştirici

2
@androiddeveloper Eclipse editörünün tüm android: öznitelikleri için değerleri kullanmayı reddettiği anlaşılıyor. Bir özellik veya hata olup olmadığını bilmek istiyorum
deej

4
Xmlns'in amacı nedir: uygulama ad alanı ve res-auto?
IgorGanapolsky

91

Harika referans. Teşekkürler! Bir ek:

Özel bir görünüm için özel öznitelikler bildiren bir kütüphane projeniz varsa, kütüphane için değil, proje ad alanınızı bildirmeniz gerekir. Örneğin:

Kütüphanenin "com.example.library.customview" paketi ve çalışan projenin "com.example.customview" paketi olduğu göz önüne alındığında, o zaman:

Çalışmaz (hatayı gösterir "hatası: 'com.example.library.customview'" paketindeki 'newAttr' özelliği için kaynak tanımlayıcı bulunamadı):

<com.library.CustomView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
        android:id="@+id/myView"
        app:newAttr="value" />

Çalışacak:

<com.library.CustomView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.example.customview"
        android:id="@+id/myView"
        app:newAttr="value" />

47
Bu ADT 17 önizlemesinde düzeltildi. Kütüphane açıklamadan uygulamanın ad kullanmak için xmlns:app="http://schemas.android.com/apk/res-auto"de bakınız comment 57 code.google.com/p/android/issues/detail?id=9656
nmr

2
Özel ad alanınızı eklemek artık bir hata döndürüyorSuspicious namespace: Did you mean http://schemas.android.com/apk/res-auto
Ben Wilkinson

özel ad alanı res-auto ile bitiyor çünkü Android Studio ve Gradle kullanıyoruz. Aksi takdirde (örneğin bazı Eclipse sürümleri) genellikle lib / [paket adınız] ile biter
Universe

özel ad alanı sona eriyor res-autoçünkü Android Studio ve Gradle kullanıyoruz. Aksi takdirde (örneğin bazı Eclipse sürümleri) genellikle sona erer lib/[your package name]. iehttp://schemas.android.com/apk/lib/[your package name]
Evren

27

En çok oy verilen yanıta ekleme.

obtainStyledAttributes ()

Ben android: xxx prdefined öznitelikleri kullanarak özel görünüm oluştururken, acquStyledAttributes () kullanımı hakkında bazı kelimeler eklemek istiyorum. Özellikle TextAppearance kullandığımızda.
"2. Oluşturucular oluşturuluyor" bölümünde belirtildiği gibi, özel görünüm, AttributeSet'i oluştururken alır. TextView kaynak kodunda (API 16) görebildiğimiz temel kullanım.

final Resources.Theme theme = context.getTheme();

// TextAppearance is inspected first, but let observe it later

TypedArray a = theme.obtainStyledAttributes(
            attrs, com.android.internal.R.styleable.TextView, defStyle, 0);

int n = a.getIndexCount();
for (int i = 0; i < n; i++) 
{
    int attr = a.getIndex(i);
    // huge switch with pattern value=a.getXXX(attr) <=> a.getXXX(a.getIndex(i))
}
a.recycle();

Burada ne görebiliriz?
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
Özellik kümesi, belgelere göre tema ile işlenir. Özellik değerleri adım adım derlenir. İlk öznitelikler temadan doldurulur, daha sonra değerlerin biçemdeki değerlerle değiştirilir ve son olarak özel görünüm örneği için XML'den kesin değerler diğerlerinin yerine geçer.
İstenen nitelikler dizisi - com.android.internal.R.styleable.TextView
Sıradan bir sabitler dizisidir. Standart öznitelikler istiyorsak, bu diziyi manuel olarak oluşturabiliriz.

Belgelerde belirtilmeyenler - sonuç TypedArray öğelerinin sırası.
Özel görünüm attrs.xml dosyasında bildirildiğinde, öznitelik dizinleri için özel sabitler oluşturulur. Ve biz değerleri bu şekilde çıkarabilir: a.getString(R.styleable.MyCustomView_android_text). Ancak manuel olarakint[] sabit yoktur. Sanırım, getXXXValue (arrayIndex) iyi çalışır.

Ve başka bir soru: "Dahili sabitleri nasıl değiştirebilir ve standart nitelikleri nasıl isteyebiliriz?" Android.R.attr. * Değerlerini kullanabiliriz.

Bu nedenle, özel görünümde standart TextAppearance özniteliğini kullanmak ve değerlerini yapıcıda okumak istersek, kodu TextView'den şu şekilde değiştirebiliriz:

ColorStateList textColorApp = null;
int textSize = 15;
int typefaceIndex = -1;
int styleIndex = -1;

Resources.Theme theme = context.getTheme();

TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.CustomLabel, defStyle, 0);
TypedArray appearance = null;
int apResourceId = a.getResourceId(R.styleable.CustomLabel_android_textAppearance, -1);
a.recycle();
if (apResourceId != -1)
{
    appearance = 
        theme.obtainStyledAttributes(apResourceId, new int[] { android.R.attr.textColor, android.R.attr.textSize, 
            android.R.attr.typeface, android.R.attr.textStyle });
}
if (appearance != null)
{
    textColorApp = appearance.getColorStateList(0);
    textSize = appearance.getDimensionPixelSize(1, textSize);
    typefaceIndex = appearance.getInt(2, -1);
    styleIndex = appearance.getInt(3, -1);

    appearance.recycle();
}

CustomLabel tanımlandığında:

<declare-styleable name="CustomLabel">
    <!-- Label text. -->
    <attr name="android:text" />
    <!-- Label text color. -->
    <attr name="android:textColor" />
    <!-- Combined text appearance properties. -->
    <attr name="android:textAppearance" />
</declare-styleable>

Belki, bir şekilde yanılıyorum, ancak eldeStyledAttributes () ile ilgili Android belgeleri çok zayıf.

Standart UI bileşenini genişletme

Aynı zamanda, beyan edilen tüm özelliklerini kullanarak standart UI bileşenini genişletebiliriz. Örneğin TextView birçok özellik bildirdiği için bu yaklaşım o kadar iyi değil. Ve overMiden onMeasure () ve onDraw () üzerinde tam işlevsellik uygulamak imkansız olacaktır.

Ancak, özel bileşenin teorik geniş yeniden kullanımını feda edebiliriz. "Tam olarak hangi özellikleri kullanacağımı biliyorum" deyin ve kodu kimseyle paylaşmayın.

Sonra yapıcı uygulayabiliriz CustomComponent(Context, AttributeSet, defStyle). Aradıktan sonra super(...)tüm öznitelikler ayrıştırılır ve alıcı yöntemleri ile kullanılabilir olur.


android: xxx önceden tanımlanmış öznitelikler tutulma gui tasarımcısında çalışır?
deej

Bu nitelikler, mülk editöründe Eclipse ADT eklentisi tarafından tanınır. Bazı değerler tanımlanmamışsa, stilimdeki varsayılanları görebilirim. Ve sınıfınıza @RemoteView ek açıklaması eklemeyi unutmayın.
yuriy.weiss

İşe yaramaz. Eclipse, getText için boş değerler yüklemeyi ve android.content.res.Resources $ NotFourceExd'i getResourceId için atmaya devam ediyor, ancak uygulama bir cihazda iyi çalışıyor.
deej

Üzgünüm, sana yardım edemem. Olasılıkları test etmek için sadece demo proje oluşturdum ve bu tür hataları karşılamadım.
yuriy.weiss

Bu, özel bir görünümün özel niteliklerini, içerdiği yerleşik görünümlerin yerleşik nitelikleriyle eşlemekten çok daha iyidir.
samis

13

Google, geliştirici sayfasını güncelledi ve oraya çeşitli eğitimler ekledi.

Bunlardan biri özel görünümlerin oluşturulmasıyla ilgilenir ve burada bulunabilir


5

İlk cevap için çok teşekkürler.

Bana gelince, sadece bir sorunum vardı. Görüşümü şişirirken , bir hata vardı: java.lang.NoSuchMethodException: MyView (Bağlam, Nitelikler)

Yeni bir kurucu oluşturarak çözdüm:

public MyView(Context context, AttributeSet attrs) {
     super(context, attrs);
     // some code
}

Umarım bu yardımcı olur!


0

Herhangi bir düzen dosyasını diğer düzen dosyasına dahil edebilirsiniz.

             <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="30dp" >

                <include
                    android:id="@+id/frnd_img_file"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    layout="@layout/include_imagefile"/>

                <include
                    android:id="@+id/frnd_video_file"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    layout="@layout/include_video_lay" />

                <ImageView
                    android:id="@+id/downloadbtn"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/plus"/>
            </RelativeLayout>

burada include etiketindeki düzen dosyaları aynı res klasöründeki diğer .xml düzen dosyalarıdır.


Bunu denedim, sahip olduğum sorun dahil edilen düzen 'uyarlanamıyor', jenerikler yaratamaz. Örneğin, benzer şekilde bir düğme eklediğimde, metni xml'de ayarlamaya çalışırsam çalışır.
cfl
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.