Bagaimana cara mendeklarasikan elemen Android UI menggunakan XML?
Bagaimana cara mendeklarasikan elemen Android UI menggunakan XML?
Jawaban:
Panduan Pengembang Android memiliki bagian yang disebut Membangun Komponen Kustom . Sayangnya, pembahasan atribut XML hanya mencakup mendeklarasikan kontrol di dalam file layout dan tidak benar-benar menangani nilai-nilai di dalam inisialisasi kelas. Langkah-langkahnya adalah sebagai berikut:
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>
Perhatikan penggunaan nama yang tidak berkualitas dalam declare-styleable
tag. Atribut android non-standar seperti extraInformation
harus dideklarasikan. Tag yang dideklarasikan dalam superclass akan tersedia dalam subclass tanpa harus dideklarasikan ulang.
Karena ada dua konstruktor yang menggunakan AttributeSet
inisialisasi untuk, lebih mudah untuk membuat metode inisialisasi terpisah untuk memanggil konstruktor.
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
adalah int[]
sumber daya yang dibuat secara otomatis di mana setiap elemen adalah ID dari suatu atribut. Atribut dihasilkan untuk setiap properti dalam XML dengan menambahkan nama atribut ke nama elemen. Misalnya, R.styleable.MyCustomView_android_text
berisi android_text
atribut untuk MyCustomView
. Atribut kemudian dapat diambil dari TypedArray
menggunakan berbagai get
fungsi. Jika atribut tidak didefinisikan dalam XML yang didefinisikan, maka null
dikembalikan. Kecuali, tentu saja, jika jenis kembali adalah primitif, dalam hal ini argumen kedua dikembalikan.
Jika Anda tidak ingin mengambil semua atribut, dimungkinkan untuk membuat larik ini secara manual. ID untuk atribut android standar disertakan android.R.attr
, sementara atribut untuk proyek ini ada di R.attr
.
int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};
Harap dicatat bahwa Anda tidak boleh menggunakan apa pun di android.R.styleable
, karena utas ini dapat berubah di masa mendatang. Masih dalam dokumentasi sebagai melihat semua konstanta ini di satu tempat berguna.
layout\main.xml
Sertakan deklarasi namespace xmlns:app="http://schemas.android.com/apk/res-auto"
di elemen xml tingkat atas. Namespaces menyediakan metode untuk menghindari konflik yang terkadang terjadi ketika skema berbeda menggunakan nama elemen yang sama (lihat artikel ini untuk info lebih lanjut). URL hanyalah cara mengidentifikasi skema unik - tidak ada yang perlu di-host di URL itu . Jika ini tampaknya tidak melakukan apa-apa, itu karena Anda sebenarnya tidak perlu menambahkan awalan namespace kecuali Anda perlu menyelesaikan konflik.
<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"
/>
Referensi tampilan khusus menggunakan nama yang memenuhi syarat.
Jika Anda ingin contoh lengkap, lihat contoh tampilan label android.
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"/>
Ini terkandung dalam LinearLayout
dengan atribut namespace:xmlns:app="http://schemas.android.com/apk/res-auto"
Referensi yang bagus. Terima kasih! Tambahan untuk itu:
Jika Anda kebetulan memiliki proyek perpustakaan termasuk yang telah menyatakan atribut khusus untuk tampilan kustom, Anda harus mendeklarasikan namespace proyek Anda, bukan yang perpustakaan. Misalnya:
Mengingat bahwa perpustakaan memiliki paket "com.example.library.customview" dan proyek yang bekerja memiliki paket "com.example.customview", maka:
Tidak akan berfungsi (menunjukkan kesalahan "kesalahan: Tidak ditemukan pengidentifikasi sumber daya untuk atribut 'newAttr' dalam paket 'com.example.library.customview'"):
<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" />
Akan bekerja:
<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"
Lihat komentar 57 di code.google.com/p/android/issues/detail?id=9656
Suspicious namespace: Did you mean http://schemas.android.com/apk/res-auto
res-auto
karena kami menggunakan Android Studio dan Gradle. Kalau tidak (misalnya beberapa versi Eclipse) biasanya akan berakhir dengan lib/[your package name]
. yaituhttp://schemas.android.com/apk/lib/[your package name]
Selain jawaban yang paling banyak dipilih.
Saya ingin menambahkan beberapa kata tentang penggunaan diperolehStyledAttributes (), ketika kita membuat tampilan khusus menggunakan atribut android: xxx prdefined. Terutama ketika kita menggunakan TextAppearance.
Seperti yang disebutkan dalam "2. Membuat konstruktor", tampilan kustom mendapat AttributeSet pada pembuatannya. Penggunaan utama dapat kita lihat dalam kode sumber TextView (API 16).
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();
Apa yang bisa kita lihat di sini?
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
Set atribut diproses berdasarkan tema sesuai dengan dokumentasi. Nilai atribut dikompilasi langkah demi langkah. Atribut pertama diisi dari tema, lalu nilai-nilai digantikan oleh nilai-nilai dari gaya, dan akhirnya nilai yang tepat dari XML untuk tampilan contoh khusus menggantikan yang lain.
Array atribut yang diminta - com.android.internal.R.styleable.TextView
Ini adalah array konstanta biasa. Jika kami meminta atribut standar, kami dapat membuat array ini secara manual.
Apa yang tidak disebutkan dalam dokumentasi - urutan elemen TypedArray hasil.
Ketika tampilan kustom dideklarasikan di attrs.xml, konstanta khusus untuk indeks atribut dihasilkan. Dan kita dapat mengekstrak nilai-nilai seperti ini: a.getString(R.styleable.MyCustomView_android_text)
. Tetapi untuk manual int[]
tidak ada konstanta. Saya kira, bahwa getXXXValue (arrayIndex) akan berfungsi dengan baik.
Dan pertanyaan lain adalah: "Bagaimana kita bisa mengganti konstanta internal, dan meminta atribut standar?" Kita bisa menggunakan nilai android.R.attr. *.
Jadi jika kita ingin menggunakan atribut TextAppearance standar dalam tampilan kustom dan membaca nilainya dalam konstruktor, kita dapat memodifikasi kode dari TextView dengan cara ini:
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();
}
Di mana CustomLabel didefinisikan:
<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>
Mungkin, saya keliru dalam beberapa hal, tetapi dokumentasi Android tentang memperolehStyledAttributes () sangat buruk.
Pada saat yang sama kita dapat memperluas komponen UI standar, menggunakan semua atribut yang dideklarasikan. Pendekatan ini tidak begitu baik, karena TextView misalnya menyatakan banyak properti. Dan tidak mungkin untuk mengimplementasikan fungsionalitas penuh di override onMeasure () dan onDraw ().
Tetapi kita dapat mengorbankan penggunaan kembali yang luas secara teoritis dari komponen khusus. Katakan "Saya tahu persis fitur apa yang akan saya gunakan", dan jangan berbagi kode dengan siapa pun.
Kemudian kita dapat mengimplementasikan konstruktor CustomComponent(Context, AttributeSet, defStyle)
. Setelah memanggil super(...)
kita akan memiliki semua atribut diuraikan dan tersedia melalui metode pengambil.
Tampaknya Google telah memperbarui halaman pengembangnya dan menambahkan berbagai pelatihan di sana.
Salah satunya berkaitan dengan pembuatan tampilan khusus dan dapat ditemukan di sini
Terima kasih banyak atas jawaban pertama.
Sedangkan saya, saya hanya punya satu masalah dengan itu. Ketika menggembungkan pandangan saya, saya memiliki bug: java.lang.NoSuchMethodException: MyView (Konteks, Atribut)
Saya mengatasinya dengan membuat konstruktor baru:
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// some code
}
Semoga ini bisa membantu!
Anda dapat memasukkan file tata letak apa pun di file tata letak lainnya sebagai-
<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>
di sini file layout di tag include adalah file layout .xml lainnya di folder res yang sama.