- Guide to Android custom views: attributes
- Topics
- Using attributes
- Custom attributes
- Custom layout attributes
- Android Custom Views Tutorial. Part-2: Custom Attributes
- 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…
- robillo/CustomViewsTutorial
- CustomViewsTutorial — Custom Views set for your app a majestic feel. This series of tutorials is aimed at enhancing…
- Android Tools Attributes — Hidden Gems of Android Studio
- General Overview
- Design-time View Attributes
- tools: instead of android:
- tools:context
- tools:layout
- tools:showIn
- tools:listitem | tools:listheader | tools:listfooter
- tools:itemCount
- tools:menu
- tools:openDrawer
- tools:minValue | tools:maxValue
- «@tools:sample/*» resources
- Sample Data
- 🎉 🎉 Congratulations! 🎉 🎉
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.
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 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.
- 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.
- 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).
- 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:
Источник
Android Tools Attributes — Hidden Gems of Android Studio
Mar 18, 2018 · 10 min read
P robably most of you have already seen and even used the weird XML attributes with tools: prefix while designing the app layouts in Android Studio. Personally, I was using tools:text attribute a lot in places where text should be added dynamically at a runtime and therefore using android:text attribute wasn’t feasible.
However, my relationships with this powerful tool didn’t go beyond tools:text , tools:visibility and tools:context attributes until few months ago I encountered a problem while designing the layout of my personal app project. The view block below the was not visible in layout preview because the was covering the layout screen. While searching for the solution I found myself reading the official user guide of tools attributes published in Android Developers’ website. After reading the guide I realized that, I was underestimating this tool for a very long time and found out that this tool can help me a lot to precisely visualize my layouts directly from within the preview pane of Android Studio.
As you may already understand, today I want to tell you about tools attributes. So, let’s start diving deeper and getting a better understanding of how these attributes work and how they can simplify our mortal lives.
General Overview
First thing first! Before going into details I would like to give a brief overview of tools attributes and explain how to use them.
Generally speaking, tools attributes are special XML attributes that enable not only design-time features (such as which layout should be drawn inside the fragment), as well as compile-time behavior (such as suppressing lint warnings).
A ccording to the official user guide, these attributes are used solely by Android Studio and removed by build tools at build time of the app. So, using these attributes has no impact on your APK size or runtime behavior.
To use these attributes, tools namespace should be added to the root element of XML file, as shown below:
RootTag xmlns:android=”http://schemas.android.com/apk/res/android»
xmlns:tools=”http://schemas.android.com/tools» >
Based on the function that the attribute accomplishes we can divide tools attributes into 3 categories:
- Error handling attributes — used for suppressing lint warning messages. This category consist of following attributes:
- tools:ignore — intended for any element and used to suppress lint warnings. It should be supplied with a comma-separated list of lint issue ID’s that the tools should ignore on this element or any of its decedents. For example, you can force the Android Studio to ignore missing content description of :
- tools:targetApi — intended for any element and used to indicate the API level (either as an integer or as a code name) that supports this element. This attribute works the same as the @TargetApi annotation in Java code. For example, you might use this because android:elevationis available only on API level 21 and higher, but you know this layout is not used for any lower API versions:
- tools:locale — intended for resources and used to indicate the default language/locale of the given element in order to avoid warnings from the spell checker. The value must be a valid locale qualifier. In example, you can add this to your values/strings.xml file (the default string values) to indicate that the language used for the default strings is Spanish rather than English:
2. Resource shrinking attributes — used for enabling strict reference checks when using resource shrinking. This category consist of following attributes:
- tools:shrinkMode — intended for resources and used to indicate the shrink mode. The default shrink mode is safe mode. To instead use strict mode, shrinkMode=»strict» should be added to the tag as shown below:
- tools:keep — intended for resources and used to manually specify resources that should be kept from stripping out during resource shrinking (typically because they are referenced in an indirect way at runtime). To keep resources manually, you have to create an XML file in your resources directory (i.e. at res/raw/keep.xml ) with a tag and specify each resource to keep in the tools:keep attribute as a comma-separated list. You can also use the asterisk character as a wildcard. For example:
- tools:discard — intended for resources and used to manually specify resources that should be stripped out while shrinking the resources (typically because the resource is referenced but in a way that does not affect your app, or because the Gradle plugin has incorrectly deduced that the resource is referenced). The usage of this attribute is the same as the usage of the tools:keep attribute:
3. Design-time view attributes — used for defining layout characteristics that are visible only in the Android Studio’s preview pane. In other words, these attributes allow us to change the rendering of the layouts in Android Studio without affecting them in the build.
Design-time View Attributes
This is the main category of tools attributes that I want to concentrate on in this story. Besides explaining every design-time attribute I will also try to give some real-world usage examples based on a sample contacts app (I will call it Contacts+ app). So, let’s get started.
tools: instead of android:
Replacing android: prefix with tools: prefix on any attribute will allow you to insert sample data in your layout preview, as well as unset an attribute only for the layout preview. Do you remember tools:text and tools:visibility attributes that I have mentioned at the beginning of this story? These attributes belong to this category and are useful when the attribute’s value isn’t populated until runtime but it is required to display the effect beforehand in the layout preview.
Let’s try these attributes on contact_item.xml layout which defines the layout of each individual contact item in our Contacts+ app. Below you can see the preview and current XML code for this layout.
Please pay attention to tools:text attributes in
elements and tools:src attribute used in element. We are using these attributes because all data will be retrieved from DB or API during the runtime and displayed in relevant view elements. Without tools attributes our card item will look like this:
Pretty confusing. Right? So, using tools: prefixed attributes allows us to visualize data in layout preview and test our layout more precisely.
We can also use tools: prefixed attributes to unset an android: prefixed attributes only for the layout preview. For example, let’s say that we want our contact items to show only contacts’ name and mobile number and reveal other secondary data through expanding on user click. To enable this feature, I will just set ’s height to 80dp and add onClick listener to expand it and reveal the secondary information.
As you can see, after setting the height to 80dp we are no longer able to see the secondary fields in layout preview. However, it is very easy to fix this problem. We just have to add tools:layout_height=”wrap_content” into our . This also means that it is allowed to use both the android: namespace attribute (which is used at runtime) and the matching tools: attribute (which overrides the runtime attribute in the layout preview only) simultaneously on the same view element.
tools:context
This attribute declares which activity this layout is associated with by default. This enables features in the editor or layout preview that require knowledge of the activity, such as picking the right theme to show for a layout, rendering the action bar (which is associated with the activity), a place to add onClick handlers, etc.
In the example of our app, we will add this attribute to the root tag of our contacts fragment, to inform that this fragment will be added to the main activity.
tools:layout
This attribute is used only by tags and informs editor about the layout that should be drawn by layout preview inside the fragment. Below you can see the difference between layout previews of our activity_main.xml layout before and after adding tools:layout=”@layout/fragment_contacts” to the tag.
tools:showIn
This attribute is used to point to a layout that uses this layout as an include and refers to it through the tag. This allows you to preview and edit that file as it appears while embedded in its parent layout. For example, adding tools:showIn=”@layout/activity_main” to the root tag of our contact_item.xml will force the editor to redraw our layout within the main activity:
tools:listitem | tools:listheader | tools:listfooter
These attributes are intended for (and its subclasses like and ) and used to specify the layout that should be drawn inside that adapter as a list item, header or footer. For example, fragment_contacts_xml layout of our Contacts+ app declares and this is how it looks like before and after adding tools:listitem=”@layout/contact_item” :
tools:itemCount
This attribute is intended solely for and used to specify the number of list items the layout editor should render in the layout preview.
As per my observations, by default Android Studio shows 10 list items for . Therefore usually after adding tools:listitem attribute the covers the entire layout screen and you can no longer see other view elements below it. In such cases tools:itemCount attribute will help you to see the elements below the .
tools:menu
This attribute is used to specify the menu layout that should be shown in the app bar. Menu layouts should be added without @menu/ or any other ID prefix and without the .xml extension.
After adding tools:menu=”main” to the root tag of our activity_main.xml we will start to see the menu icon in the app bar:
According to the official documentation, it is also possible to pass in multiple menu IDs, separated by commas. However, passing multiple menu items won’t have any effect in the layout preview.
tools:openDrawer
This attribute works exclusively with and allows to control its state (open, closed) and position (left, right) in the preview pane of the layout editor. Below table list names and descriptions of constants that this attribute accepts as the parameter:
For example, below code will enable you to see the in open state in the preview pane:
tools:minValue | tools:maxValue
This attributes set minimum and maximum values for a in the preview pane of the layout editor.
«@tools:sample/*» resources
This is one of the most useful attributes that allows us to inject placeholder data or images into our views. Currently, Android Studio offers following types of predefined data that can be injected into our view elements:
In case of Contacts+ app, these predefined data will allow us to visualize the name, surname, phone number, address and even the avatar of contacts without using the hard-coded texts and image resources.
Pretty neat, huh?! 👍
Our layout looks now more realistic. However, since there is no predefined data for email addresses, we are still using the hard-coded text for displaying it. Also, instead of a full address, we are just using the «@tools:sample/cities» , which shows only city names. The good news is that Android Studio 3 now enables us to create our own predefined sample data.
Sample Data
To declare and use our sample data, first of all we need to create a sample data folder. To do so, we have to right click on the app folder then press New -> Sample Data directory .
After that, you will notice the new folder called sampledata under the app . Now we can put our data inside that folder. At that point we have two options:
- Add plain text file, insert raw data line by line and then reference that data using «@sample/fileName» . In case of our app, we will create two different files ( emails & addresses ) and insert email and address data inside that files. Then we will reference that data from our contact_item.xml using tools:text=”@sample/emails” and tools:text=”@sample/addresses” .
🎉 🎉 Congratulations! 🎉 🎉
We have made a very impressive work and after all changes, our app looks very clean and realistic.
Hope you found this story useful and interesting. Feel free to share your feedback and comments and don’t forget to clap 😃.
Источник