XML kullanarak bir Android UI öğesini nasıl bildirebilirim?
XML kullanarak bir Android UI öğesini nasıl bildirebilirim?
Yanıtlar:
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:
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-styleable
Etikette niteliksiz bir ad kullanıldığına dikkat edin . Standart olmayan android özelliklerinin extraInformation
türlerinin bildirilmesi gerekir. Üst sınıfta bildirilen etiketler, yeniden sınıflandırılmak zorunda kalmadan alt sınıflarda bulunacaktır.
AttributeSet
Baş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.MyCustomView
int[]
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_text
için android_text
özniteliği içerir MyCustomView
. Öznitelikler daha sonra TypedArray
çeşitli get
fonksiyonlar kullanılarak alınabilir . Öznitelik XML'de tanımlı olarak tanımlanmamışsa null
dö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.styleable
göre, bu iş parçacığı gelecekte değişebilir. Tüm bu sabitleri tek bir yerde görmek faydalı olmaya devam ediyor.
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.
Tam bir örnek istiyorsanız, android etiket görünümü örneğine bakın.
TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequences=a.getString(R.styleable.LabelView_text);
<declare-styleable name="LabelView">
<attr name="text"format="string"/>
<attr name="textColor"format="color"/>
<attr name="textSize"format="dimension"/>
</declare-styleable>
<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, LinearLayout
bir ad alanı özniteliğine sahip bir:xmlns:app="http://schemas.android.com/apk/res-auto"
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" />
xmlns:app="http://schemas.android.com/apk/res-auto"
de bakınız comment 57 code.google.com/p/android/issues/detail?id=9656
Suspicious namespace: Did you mean http://schemas.android.com/apk/res-auto
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]
En çok oy verilen yanıta ekleme.
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.
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.
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
İ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!
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.