Android custom xml attr

Android Custom Views Tutorial. Part-2: Custom Attributes

In the last part of this series, we discussed how to make basic Custom Shapes in Android. If you haven’t seen that Part, I would recommend going through that first:

Android Custom Views Tutorial. Part-1

In Android, the learning curve basically goes on for a long period of time. At a particular stage in this field, you…

If you want to get hold of the project code, it is recommended that you clone/fork/download the following repository:

robillo/CustomViewsTutorial

CustomViewsTutorial — Custom Views set for your app a majestic feel. This series of tutorials is aimed at enhancing…

In this part of the series, you will learn to add custom attributes to the Custom Views.

The previous part of the series has the code for MyCustomView as:

In this code for the custom view, you may have noticed that we have the init() method with empty body, and several warnings are there in the onDraw() method that was overridden to avoid using layout allocations during draw operations. Removing this warning is very important, as this is one of the easiest causes of a memory leak. Our first step of this series will be to remove this warning only.

  1. Make mRect and mPaintobjects of Rect and Paint class respectively as globalto the class. make their instances in the init() method that was made. Then replace rect with mRect, and paint with mPaint.The warning should be removed by following this step.
  2. Now, to begin adding custom attributesto your custom views, you have to first add a new file your “values” directory and name it “attrs.xml”.Inside this xml file, inside tags, add a “declare-styleable” tag with attribute “name” as MyCustomView(your custom view class name).
  3. Inside these tags, all your custom attributes will be inserted in the form of key (“name=”) — value (“format=”)pairs. In our case, we will add a custom attribute named square_colorwith format as color.

4. Next, we need to check in our init() method whether the AttributeSet set being passed as a parameter is null or not. If it is not null, then we obtain a TypedArray typedArray (say) by calling obtainStyledAttributes(set, R.styleable.MyCustomView) using getContext();

5. Next, we declare an int variable mSquareColor and initialise with the values input through the TypedArray ta, also providing the default colour in case no value for that attribute was input by the user. Also remember to call ta.recycle() once you are done accessing it. Your class should now look like this:

6. Now all you need to do is add your custom attribute square_color to your activity_main.xml , you will see that the custom view colour changes to whatever colour you add inside the attribute parameter.

Thats all you needed to know how you make custom attributes for your custom views. More examples on custom attributes are for size of your view, radius in case of circle, text input, etc.

To continue learning in depth of the basics of custom view, it is recommended that you go through the remaining parts of the series. And like always, happy programming. 🙂

If you liked the post, please press the little heart/follow to promote more tuts from this side. 🙂

Link to other parts of this series:

Источник

Guide to Android custom views: attributes

Jan 7, 2020 · 5 min read

I’ve been designing, writing and publishing Android custom views for the past 5 years now. I guess it’s about time to sum it up and share the results.

The article series here, on Medium, is a copy of materials published on my repository, which you can find under the following link: https://github.com/ZieIony/GuideToCustomViews. There you can also find case studies, issues and my other projects including custom views.

Читайте также:  Quik для андроида сбербанк

Topics

Using attributes

Each style uses attributes to provide values to views. Here’s an example XML with a view declaration:

The enclosing la y out is invalid because it needs at least layout_width and layout_height attributes to be parsed correctly. Let’s forget about for the sake of simplicity. This view has an inline style with four attributes:

  • style=»@style/ImageView.Icon» — style attribute is a special attribute parsed by the framework. It’s used to change apply a style defined in an external XML file. There’s a couple of special tags and attributes without any prefixes: layout , fragment , include , data and probably a couple more.
  • android:layout_width/_height=»wrap_content» — attribute usages prefixed with android are defined by the Android framework. You can reuse them in your custom views if you wish. Attribute names prefixed with layout_ by convention are used by enclosing layouts. You can learn how to add your own layout attributes here. wrap_content is an enum — one of many types of attributes. Attributes can reference values, resources, styles and many more.
  • app:srcCompat=»@drawable/ic_airplanemode_on_24px» — this is an attribute added by a library. The app prefix is declared somewhere in the layout and can have any name. srcCompat is an attribute of type drawable and is used here to add support for vector drawables. It references a file from res/drawable folder.

This view is enclosed in layout tag — it’s a data binding declaration. This tag has some special meaning and features.

  • This view also uses layout_width and layout_height , but this time with values of type dimension . The dp means that the value is expressed in device independent pixels. Some of the attributes have more than one type.
  • guide_htmlText=»Select Dates» — this is a library attribute and is used without any namespace prefix. It’s a data binding attribute handled by a binding adapter.
  • android:textColor=»?android:attr/textColorPrimary» — this attribute has a theme reference value. The question mark starts a theme reference. The android: part is a namespace and is empty for custom attributes. The attr/textColorPrimary part declares an attribute present in the current theme to take a value from.
  • android:textAppearance=»@style/TextAppearance.Body1″ — a framework’s attribute of reference type. Is used to change text style of text views. Here it references a style resource of name TextAppearance.Body1`.

Resources are a very broad topic. Even a very simple application usually needs at least a theme, a couple of drawables (icons) and uses styles and colors declared somewhere. Read more about resources on developer.android.com.

Custom attributes

First thing to do to add a custom attribute is to declare a styleable in XML. A styleable is an XML with a bunch of attributes that will be used by a custom view.

You will also need an attribute for the styleable to use. You can either add your own attribute (remember to prefix it) or reuse an existing one. Your attributes can be declared and then used in a styleable or declared and used at once. Reusing attributes is just as easy — just remember to use the same namespace, name and type as the original declaration.

For a custom view, you may want to add a theme attribute. That attribute will be used by the view to read the default style provided by a theme. It’s just a simple reference attribute, usually with a style suffix.

You also need a style. It can be a base style (if it’s a completely new style) or a derived style (if there was a parent style you could use).

Then declare a theme in themes.xml and use the style attribute to set the style.

The attributes are passed to a view in a couple of ways:

  • Using base theme values.
  • Using a default style resource. This way corresponds to the 4th parameter in the 4-parameter constructor and the 4th parameter in obtainStyledAttributes() . It’s a reference to the default style for a view. If this value is 0, it won’t be used to look for defaults.
  • Style using the theme attribute. This way corresponds to the 3rd parameter in the 3 and 4-parameter constructors and the 3rd parameter in obtainStyledAttributes() . It’s a reference to a style specified in the current theme. If this value is 0, it won’t be used to look for defaults.
  • Style using the style attribute and using inline attribute usage in a layout. These come in AttributeSet attrs . Can be null if the view was created without using an XML layout.
  • Default values applied when grabbing attribute values from value arrays.
Читайте также:  Что проще андроид или смартфон

In a typical case, you need only two constructors and a bit of initialization code. obtainStyledAttributes() is used to get an array of values for this view considering default style, the current theme and XML attributes. Then, attribute by attribute, you have to get a value by id and set it to the view. Notice how the attribute names declared in XML (with namespaces) are transformed to field names of the ids in the example.

Custom layout attributes

LayoutParams classes have their own style attributes. You can spot them in layout XMLs. The following button has four inline style attributes. android:text is used by the Button class. The rest of the attributes (starting with layout_) is used by LayoutParams classes — android:layout_width and android:layout_height by plain LayoutParams and android:layout_margin by MarginLayoutParams.

Adding custom layout attributes is very similar to adding custom view attributes. You also need to declare attributes, a styleable, read the attributes using obtainStyledAttributes() and the value getters, etc. Only the place, where all of that attribute parsing and storing happens is different.

By convention layout styleables are named after the owning layout with _ Layout suffix. I like to also add _ layout prefix to attributes’ names. The rest is identical to the usual styleables.

LayoutParams usually are implemented as static classes inside their owning layouts. The most interesting part of a LayoutParams class is the XML constructor — very similar to views’ XML constructors. The attrs parameter contains values of style attributes. You can get the layout style attributes from there. Complete example code can be found here.

For the layout to use the new LayoutParams class you have to override a couple of methods:

Источник

Android. Заметка на будущее

Layouts

Думаю каждый начинающий программист под платформу Android, сразу замечает, чтобы построить какой-либо UI, требуется создать xml файл в директории проекта /res/layout, а потом еще чудесным образом связать его с кодом на Java. По началу это кажется своебразным методом и сразу появлется ощущение того, что чего-то не хватает, и UI дизайнер в плагине Android для IDE далеко не чудо. Ну хватит разглагольствований, к делу!

Если сильно не углубляться в разнообразие устройств на рынке, что в моем случае так и вышло, есть платформа Android какой-то версии, знаем размер экрана целевого устройства. Допустим у вас такая же ситуация.

В общем случае приходиться иметь две папки /res/layout и /res/layout-land. Здесь -land выступает квалификатором (qualifier), который обозначает, что любой layout в этой папке доступен только для Landscape (горизонтального) режима. Если существует layout, который одинакого выглядит для обоих режимов, вертикального и горизонтального, то его помещают в /res/layout. Android самостоятельно вызывает деструктор Activity и создает новое Activity при повороте экрана, если не указана конкретная ориентация в AndroidManifest. Таким образом, можно размещать layout с одним и тем же именем в обоих папках /res/layout и /res/layout-land, а Android позаботится о загрузке актуального layout.

В коде Activity, как обычно, вызывается

Что от меня? И правда, описал в кратце то, что можно и так найти в сети. Дело в том, что мне пришлось писать очень графически измененное приложение. Большенство элементов были очень изменены. Первое что пришло в голову, было ошибочно. Решил написать собственный дочерний компонент, от того же ListView, к примеру, и там понеслось: onDraw, dispatchDraw и др. Так мне показалось мало, еще и вбил конкретные значения в пикселях при отрисовке какого-либо элемента.

Это то, как не надо делать. Даже если нет выхода, пытайтесь до последнего не создавать компонент, а выкручиваться layout’ами. Намного лучше написать BaseAdapter для ListView, к примеру, где загружать другой layout и его контроллировать. Если выхода нет, то все значения для UI в пикселях, выносить в свойства компонента (attrs), которые будет передаваться при описании компонента в xml. Сами значения в xml, так же не указывать на прямую, а использовать dimensions, ссылки.

Читайте также:  Как сделать экран цветным андроид

Давайте рассмотрим, что я подразумиваю под attrs и dimensions.

Attrs

Android предоставляет неявный способ расширять ваши нестандартные компоненты дополнительными свойствами. Потребуется создать attrs.xml файл в /res/values. Вполне вероятно, назвать данный файл можно как угодно по другому, но это название я считаю стандартом.

Содержание attrs.xml вполне доступно для чтение человеком. Давайте рассмотрим простой пример:

Resources встречается постоянно, используется для хранения каких-либо ресурсов и впоследствии доступен в коде Java через статический класс R пакета приложения. К примеру наше объявляение доступно через R.styleable.MyExampleView. По моим наблюдениям и тому, что приходилось использовать, есть такой список format (тип свойства):

  • dimension — может быть значение типа 10px, 10dip или ссылка на dimen/[имя значения]
  • integer — может быть значение типа 10, 5, 2. Так же думаю, что и ссылка может сработать
  • string — просто текстовое значение типа «Hello World» или ссылка на string/[имя значения]
  • reference — ссылка на @drawable к примеру, что в свою очередь может быть @drawable, color или что-то другое

Допустим у нас есть собственный класс, наследник View: com.android.example.view.MyExampleView. Опишем его просто:

Таким образом мы создали собственный элемент управления, который можно настраивать прямо из xml, и данный метод очень гибок, т.к. отсутствует привязка к определенным значениям в коде, кроме по умолчанию. Чтобы создать элемент, напишим в layout:

Dimensions

В идеальном мире все значения выносить в /res/values/dimensions.xml в формате: [значение]dp, после чего использовать в xml или коде через ссылку на dimen/[имя]. Я советую, как и поступаю на данный момент, выносить размер текста, главных элементов приложения, к примеру смещения каких-то панелей, padding/margin по умолчанию и др. Не выносить значения для каких-то конкретных элементов, например в одном диалоге кнопка от кнопки на расстоянии в 10 пикселей.

Такой подход поможет быть уверенным, что в приложении весь текст выглядит стандартизированно, например большие заголовки в 30 пикселей, средние в 24, а обычный текст в 16. Если не понравилось — меняем только в одном месте.

В принципе останавливаться на этом долго не стоит, но есть один момент. Недавно Google обновила плагин Android для Eclipse, соответственно, и теперь там есть такой зверь Lint. Так вот, он мне все время подмигивал и убеждал, что надо бы использовать dp, а не px, и расписывал еще по какой такой причине. Я и поверил, сделал. А теперь давайте вспомним о Density. Насколько я понимаю, это значение показывает насколько плотно расположены пиксели друг к другу. Т.е. на пример у вас есть устройство в разрешением в 800×600. Но дело в том, что одно устройство имеет 800 * 600 пикселей, в другое 2 * 800 * 2 * 600. Думаю уловили разницу? Т.е. разрешение одно, но качество и соответственно плотность пикселей совершенно другая. И именно в этом скрывается подвох Lint. После миграции на устройство с большей плотностью, используя dp, у меня все элементы поехали, а текст стал совершенно других размеров (на взгляд).

Как оказалось, используй я с самого начала px везде и игнорируй предупреждения Lint, я бы не тратил дополнительное время на переписывание dp на px.

Colors

Цвета в Android так же могут (должны) быть представлены в xml в форматах: argb, rgb. К примеру, белый цвет:

  • rgb = #fff. Это не #0f0f0f или #f0f0f0 — это сокращенная форма, в итоге имеем непрозрачный белый цвет #ffffffff
  • argb = #ffff. На подобии предыдущего, только включая alpha составляющую
  • rgb = #ffffff. Полная форма rgb
  • argb = #ffffffff. Полная форма argb

В принципе очень схоже на dimensions правила, обычно располагается в /res/values/colors.xml, так же в resources теге. Выносить в colors стоит цвета которые используются для стандартизации полного UI, а не каких-либо мелких деталей одного из элементов. Так сказать золотая серидина между параноей и ленью.

Надеюсь кому то эти заметки сохранят время или помогут в чем-то более глубоко разобраться.

UPD:
Спасибо sdfsdhgjkbmnmxc и andreich за указание ошибок в тексте.

Источник

Оцените статью