Benim gibi kendi niteliklerimi uygulamak gerekir com.android.R.attr
Bu belgelerin nasıl tanımlanacağı ve kodumdan nasıl kullanılacağı hakkında bilgiye ihtiyacım olduğu için resmi belgelerde hiçbir şey bulunamadı.
Benim gibi kendi niteliklerimi uygulamak gerekir com.android.R.attr
Bu belgelerin nasıl tanımlanacağı ve kodumdan nasıl kullanılacağı hakkında bilgiye ihtiyacım olduğu için resmi belgelerde hiçbir şey bulunamadı.
Yanıtlar:
Şu anda en iyi belgeler kaynaktır. Buradan bakabilirsiniz (attrs.xml) .
Nitelikleri, üst <resources>
öğede veya öğenin içinde tanımlayabilirsiniz <declare-styleable>
. Birden fazla yerde bir attr kullanacaksam, onu kök öğeye koyarım. Tüm özelliklerin aynı global ad alanını paylaştığını unutmayın. Bu, bir <declare-styleable>
öğenin içinde yeni bir özellik oluştursanız bile, bunun dışında kullanılabilir ve farklı türde aynı adla başka bir özellik oluşturamayacağınız anlamına gelir.
Bir <attr>
öğenin iki xml özelliği vardır name
ve format
. name
buna bir şey demenize izin verir ve bu şekilde kodda atıfta bulunma şekliniz budur, örn R.attr.my_attribute
. format
Nitelik istediğiniz özelliğin 'türü' bağlı olarak farklı değerlere sahip olabilir.
Kullanarak pek çok türde biçimini ayarlayabilirsiniz |
, örn format="reference|color"
.
enum
nitelikler aşağıdaki gibi tanımlanabilir:
<attr name="my_enum_attr">
<enum name="value1" value="1" />
<enum name="value2" value="2" />
</attr>
flag
öznitelikler benzerdir, ancak değerlerin birlikte bitlenmesi veya birleştirilmesi gerekir:
<attr name="my_flag_attr">
<flag name="fuzzy" value="0x01" />
<flag name="cold" value="0x02" />
</attr>
Özelliklere ek olarak <declare-styleable>
öğe var. Bu, özel bir görünümün kullanabileceği nitelikleri tanımlamanıza olanak tanır. Bunu bir <attr>
öğeyi belirterek yaparsınız , daha önce tanımlanmışsa format
. Bir android attr, örneğin android: gravity'yi yeniden kullanmak isterseniz, bunu name
aşağıdaki gibi yapabilirsiniz.
Özel görünüm örneği <declare-styleable>
:
<declare-styleable name="MyCustomView">
<attr name="my_custom_attribute" />
<attr name="android:gravity" />
</declare-styleable>
Özel görünümünüzde XML'deki özel niteliklerinizi tanımlarken birkaç şey yapmanız gerekir. Öncelikle niteliklerinizi bulmak için bir ad alanı bildirmelisiniz. Bunu kök düzen öğesinde yaparsınız. Normalde sadece vardır xmlns:android="http://schemas.android.com/apk/res/android"
. Şimdi de eklemelisiniz xmlns:whatever="http://schemas.android.com/apk/res-auto"
.
Misal:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:whatever="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<org.example.mypackage.MyCustomView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
whatever:my_custom_attribute="Hello, world!" />
</LinearLayout>
Son olarak, bu özel özelliğe erişmek için normalde bunu özel görünümünüzün yapıcısında aşağıdaki gibi yaparsınız.
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);
//do something with str
a.recycle();
}
Son. :)
View
: github.com/commonsguy/cw-advandroid/tree/master/Views/…
xmlns:my="http://schemas.android.com/apk/lib/my.namespace"
Kullandığınız gibi görünüyor - hiçbir kopyalama attrs.xml yok. Ad alanı URI yolunun / apk / res değil / apk / * lib * olması gerektiğini unutmayın.
apk/lib
bir kütüphane projesinden referans formatı olan özel özellikler üzerinde benim için çalışmadı. Ne işe yaradıapk/res-auto
, hemen aşağıda stackoverflow.com/a/13420366/22904'te ve ayrıca stackoverflow.com/a/10217752
enum
ve arasındaki temel farkı bir çeşit göstermekte flag
. Burada benzer bir soruya daha uzun bir cevap yazdım ve şimdi bu soruyu bulduğumda bununla bağlantı kuracağımı düşündüm.
a.recycle()
belleği boşaltmak için çok önemlidir
Qberticus'un cevabı iyidir, ancak yararlı bir ayrıntı eksik. Bunları bir kitaplıkta uyguluyorsanız:
xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"
ile:
xmlns:whatever="http://schemas.android.com/apk/res-auto"
Aksi takdirde kitaplığı kullanan uygulamada çalışma zamanı hataları olur.
Yukarıdaki cevap, birkaç şey dışında her şeyi ayrıntılı olarak ele almaktadır.
İlk olarak, stil yoksa (Context context, AttributeSet attrs)
, tercihi örneklemek için yöntem imzası kullanılacaktır. Bu durumda sadece context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)
TypedArray almak için kullanın .
İkincisi, plaurals kaynakları (miktar dizeleri) ile nasıl başa çıkılacağını kapsamaz. Bunlar TypedArray kullanılarak ele alınamaz. İşte SeekBarPreference'imden, tercihin değerini tercih değerine göre biçimlendiren tercihin özetini ayarlayan bir kod snippet'i. Tercih için xml, bir metin dizesine veya dizeye özetlenir: tercihin değeri dizeye biçimlendirilir (değeri almak için içinde% d olması gerekir). Android: özeti bir plaurals kaynağına ayarlanmışsa, sonucu biçimlendirmek için kullanılır.
// Use your own name space if not using an android resource.
final static private String ANDROID_NS =
"http://schemas.android.com/apk/res/android";
private int pluralResource;
private Resources resources;
private String summary;
public SeekBarPreference(Context context, AttributeSet attrs) {
// ...
TypedArray attributes = context.obtainStyledAttributes(
attrs, R.styleable.SeekBarPreference);
pluralResource = attrs.getAttributeResourceValue(ANDROID_NS, "summary", 0);
if (pluralResource != 0) {
if (! resources.getResourceTypeName(pluralResource).equals("plurals")) {
pluralResource = 0;
}
}
if (pluralResource == 0) {
summary = attributes.getString(
R.styleable.SeekBarPreference_android_summary);
}
attributes.recycle();
}
@Override
public CharSequence getSummary() {
int value = getPersistedInt(defaultValue);
if (pluralResource != 0) {
return resources.getQuantityString(pluralResource, value, value);
}
return (summary == null) ? null : String.format(summary, value);
}
notifyChanged()
, tercihin onDialogClosed
yöntemini çağırmanız gerekir .Geleneksel yaklaşım, kaynak plakası kodu ve beceriksiz kaynak kullanımı ile doludur. Bu yüzden Spyglass çerçevesini yaptım . Nasıl çalıştığını göstermek için, bir Dize başlığı görüntüleyen özel bir görünümün nasıl oluşturulacağını gösteren bir örnek.
1. Adım: Özel bir görünüm sınıfı oluşturun.
public class CustomView extends FrameLayout {
private TextView titleView;
public CustomView(Context context) {
super(context);
init(null, 0, 0);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr, 0);
}
@RequiresApi(21)
public CustomView(
Context context,
AttributeSet attrs,
int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs, defStyleAttr, defStyleRes);
}
public void setTitle(String title) {
titleView.setText(title);
}
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
}
}
Adım 2: values/attrs.xml
Kaynak dosyada bir dize niteliği tanımlayın :
<resources>
<declare-styleable name="CustomView">
<attr name="title" format="string"/>
</declare-styleable>
</resources>
Adım 3: Görünüm açıklandığında Spyglass çerçevesine öznitelik değerini bu yönteme yönlendirmesini bildirmek için @StringHandler
ek açıklamayı setTitle
yönteme uygulayın .
@HandlesString(attributeId = R.styleable.CustomView_title)
public void setTitle(String title) {
titleView.setText(title);
}
Artık sınıfınızda bir Spyglass ek açıklaması olduğu için, Spyglass çerçevesi bunu derleme zamanında algılar ve otomatik olarak CustomView_SpyglassCompanion
sınıfı oluşturur .
4. Adım: Oluşturulan sınıfı özel görünüm init
yönteminde kullanın:
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
CustomView_SpyglassCompanion
.builder()
.withTarget(this)
.withContext(getContext())
.withAttributeSet(attrs)
.withDefaultStyleAttribute(defStyleAttr)
.withDefaultStyleResource(defStyleRes)
.build()
.callTargetMethodsNow();
}
Bu kadar. Şimdi sınıfı XML'den başlattığınızda, Spyglass arkadaşı öznitelikleri yorumlar ve gerekli yöntem çağrısını yapar. Örneğin, aşağıdaki düzeni şişirirsek argüman setTitle
olarak çağrılır "Hello, World!"
.
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:width="match_parent"
android:height="match_parent">
<com.example.CustomView
android:width="match_parent"
android:height="match_parent"
app:title="Hello, World!"/>
</FrameLayout>
Çerçeve, dize kaynaklarıyla sınırlı değildir, diğer kaynak türlerini işlemek için birçok farklı ek açıklama içerir. Ayrıca, varsayılan değerlerin tanımlanması ve yöntemlerinizde birden çok parametre varsa yer tutucu değerlerin iletilmesi için ek açıklamalar bulunur.
Daha fazla bilgi ve örnek için Github repo'ya bakınız.
android:title="@{"Hello, world!"}"
.
format
özniteliği attr
öğeden atlarsanız, XML düzenlerinden bir sınıfa başvurmak için bu özniteliği kullanabilirsiniz.
Refactor > Rename
İşlerFind Usages
İşler... / src / main / res / değerleri / attrs.xmlformat
içinde bir özellik belirtmeyin
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
....
<attr name="give_me_a_class"/>
....
</declare-styleable>
</resources>
bazı düzen dosyalarında kullanın ... / src / main / res / layout / activity__main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- make sure to use $ dollar signs for nested classes -->
<MyCustomView
app:give_me_a_class="class.type.name.Outer$Nested/>
<MyCustomView
app:give_me_a_class="class.type.name.AnotherClass/>
</SomeLayout>
görünümü başlatma kodunuzda sınıfı ayrıştırın ... / src / main / java /.../ MyCustomView.kt
class MyCustomView(
context:Context,
attrs:AttributeSet)
:View(context,attrs)
{
// parse XML attributes
....
private val giveMeAClass:SomeCustomInterface
init
{
context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
{
try
{
// very important to use the class loader from the passed-in context
giveMeAClass = context::class.java.classLoader!!
.loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
.newInstance() // instantiate using 0-args constructor
.let {it as SomeCustomInterface}
}
finally
{
recycle()
}
}
}