4 ответов:
в настоящее время лучшая документация является источником. Вы можете взглянуть на него здесь (у attrs.xml).
вы можете определить атрибуты в топ
<resources>или внутри<declare-styleable>элемент. Если я собираюсь использовать attr более чем в одном месте, я помещаю его в корневой элемент. Обратите внимание, что все атрибуты имеют одно и то же глобальное пространство имен. Это означает, что даже если вы создадите новый атрибут внутри<declare-styleable>элемент, он может быть использован вне, и вы не можете создать другой атрибут с тем же именем другого типа.An
<attr>элемент имеет два атрибута xmlnameиformat.nameпозволяет вам называть это чем-то, и вот как вы в конечном итоге ссылаетесь на него в коде, например,R.attr.my_attribute. Элемент может иметь разные значения в зависимости от типа атрибута, который вы хотите.
- ссылка - если он ссылается на другой идентификатор ресурса (например, " @color/my_color", "@layout/my_layout")
- цвета
- boolean
- измерение
- float
- целое
- строка
- фракция
- перечисление - обычно строго определен
- флаг - обычно строго определен
вы можете установить формат для нескольких типов с помощью
|, например,format="reference|color".
enumатрибуты могут быть определены как следует:<attr name="my_enum_attr"> <enum name="value1" value="1" /> <enum name="value2" value="2" /> </attr>
flagатрибуты похожи, за исключением того, что значения должны быть определены, чтобы они могли быть бит или вместе:<attr name="my_flag_attr"> <flag name="fuzzy" value="0x01" /> <flag name="cold" value="0x02" /> </attr>в дополнение к атрибутам есть
<declare-styleable>элемент. Это позволяет определить атрибуты, которые может использовать пользовательское представление. Вы делаете это, указав<attr>элемент, если он был ранее определен Не указанformat. Если вы хотите повторно использовать Android attr, например, android: gravity, то вы можете сделать это вname, следующим образом.пример пользовательского представления
<declare-styleable>:<declare-styleable name="MyCustomView"> <attr name="my_custom_attribute" /> <attr name="android:gravity" /> </declare-styleable>при определении пользовательских атрибутов в XML на пользовательском представлении вам нужно сделать несколько вещей. Сначала вы должны объявить пространство имен, чтобы найти свои атрибуты. Вы делаете это на корневом элементе макета. Обычно есть только
xmlns:android="http://schemas.android.com/apk/res/android". Теперь вы должны также добавитьxmlns:whatever="http://schemas.android.com/apk/res-auto".пример:
<?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>наконец, чтобы получить доступ к этому пользовательскому атрибуту, вы обычно делаете это в конструктор вашего пользовательского представления следующим образом.
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(); }конец. :)
ответ Qberticus хорош, но одна полезная деталь отсутствует. Если вы реализуете их в библиотеке заменить:
xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"С:
xmlns:whatever="http://schemas.android.com/apk/res-auto"в противном случае приложение, которое использует библиотеку будут ошибки во время выполнения.
ответ выше охватывает все очень подробно, кроме нескольких вещей.
во-первых, если нет стилей, то
(Context context, AttributeSet attrs)подпись метода будет использоваться для создания экземпляра предпочтения. В этом случае просто используйтеcontext.obtainStyledAttributes(attrs, R.styleable.MyCustomView)чтобы получить TypedArray.во-вторых, он не охватывает, как иметь дело с plaurals ресурсов (количество строк). Они не могут быть обработаны с помощью TypedArray. Вот фрагмент кода из моего SeekBarPreference, который устанавливает резюме форматирование предпочтения его значение в соответствии со значением предпочтения. Если xml для предпочтения устанавливает android: summary в текстовую строку или строку resouce, значение предпочтения форматируется в строку (в ней должен быть %d, чтобы забрать значение). Если android: summary имеет значение ресурса plaurals, то это используется для форматирования результата.
// 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()В поonDialogClosedметод.
традиционный подход полон шаблонного кода и неуклюжей обработки ресурсов. Вот почему я сделал рамки подзорной трубы. Чтобы продемонстрировать, как это работает, вот пример, показывающий, как сделать пользовательское представление, которое отображает заголовок строки.
Шаг 1: Создайте пользовательский класс представления.
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); } }Шаг 2: Определите строковый атрибут в
values/attrs.xmlфайл ресурсов:<resources> <declare-styleable name="CustomView"> <attr name="title" format="string"/> </declare-styleable> </resources>Шаг 3: применить
@StringHandlerаннотация кsetTitleметод, чтобы сообщить структуре Spyglass, чтобы направить значение атрибута к этому методу, когда представление раздуто.@HandlesString(attributeId = R.styleable.CustomView_title) public void setTitle(String title) { titleView.setText(title); }теперь, когда ваш класс имеет аннотацию Spyglass, структура Spyglass обнаружит ее во время компиляции и автоматически сгенерирует
CustomView_SpyglassCompanionкласса.Шаг 4: Используйте созданный класс в пользовательском представлении
initспособ: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(); }вот и все. Теперь, когда вы создаете экземпляр класса из XML, спутник Spyglass интерпретирует атрибуты и делает необходимый вызов метода. Например, если мы раздуваем следующий макет, то
setTitleбудет вызван с"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>структура не ограничивается строковыми ресурсами имеет множество различных аннотаций для обработки других типов ресурсов. Он также имеет аннотации для определения значений по умолчанию и для передачи значений-заполнителей, если ваши методы имеют несколько параметров.
взгляните на репозиторий Github для получения дополнительной информации информация и примеры.
Comments