Quantcast
Channel: Alexandru V. Simonescu
Viewing all articles
Browse latest Browse all 17

Mastering tools namespace on Android

$
0
0

You probably saw in lots of XML layout examples provided by Google, that sometimes appears the tools namespace. This namespace is useful when developing and doesn’t affect the user experience. Are just a set of handy attributes who help rendering layouts in Android’s Studio Design View.

All this tricky attributes can sometimes save us build time. I’m not saying your build will be faster, but your builds related to UI changes can be fewer.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

The tools namespace full URI is http://schemas.android.com/tools, usually bound to the tools prefix but you can use whatever you want.

All this attributes doesn’t impact on runtime or apk size, all tools attributes are stripped by gradle when application is packaged.

You can quickly add the tools namespace with the provided shortcut for Android Studio. Just write toolsNS and hit TAB.

Quick add Tools namespace

Worth mentioning that Android Studio at time of writing this article, doesn’t help too much with the xml syntax completion, so don’t worry, keep writing the tools override even if AS doesn’t gives you syntax hints. The easiest way to use them is to first write the attributes with the android: namespace, duplicate the line with CMD + D and replace the prefix.

Duplicate and replace namespace

Getting started

When i started developing Android, i used to use the android:text="" attribute with some hardcoded dummy text to see how my TextView or EditText will look on the preview window. But Lint was complaining about hardcoded string and i ended up with defined strings that didn’t deliver nothing to the user and my .apk contained unuseful stuff.

The trick is to use the tools:text="@string" to see your views pre filled with data on the preview window. You will end up with similar xml:

<TextView
      tools:text="Mastering ToolsNs"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      />

In the above snippet, at design time you will be able to see the TextView’s text but on runtime that attribute it wont exist.

Different attributes on runtime and design time

Worth note that you can use both android and tools namespaces at same time. The tools namespace will be used at design time and first one at runtime.

Sometimes you want to enable some features on runtime but not on design preview. The Android documentation shows the ListView example:

<ListView
        android:id="@+id/listView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fastScrollAlwaysVisible="true"
        tools:fastScrollAlwaysVisible=""/>

There you can see that at runtime, the fastScrollAlwaysVisible is enabled but at design time, is disabled.

Actually you can override any existing attributes from android namespace but with custom attributes it won’t work.

Target API versions on XML

You can target API levels on XML, in the same way as using @TargetApi annotation on Java. The API version can be specified by an integer or as codename. This way Lint it won’t complain about version specific XML attributes.

<TextView
      tools:text="Mastering ToolsNs"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      tools:layout_height="match_parent"
      tools:targetApi="M"
      />

Tell Lint your string resources are correct

This happens commonly, Android Studio / Lint defaults language is english. If you have for example string resources in other language, it will show some typo warnings as bellow.

Language typos warnings

The trick is to tell Lint your resources locale:

<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="es">

This way it won’t show more typo warnings.

Preview layout on fragment and custom views

I found this specially useful when using Fragment and Custom Views. With the tools:layout="@layout/your_layout" you can set a layout to be shown in the preview window.

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

  <fragment
      android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      tools:layout="@layout/fragment_books"
      />

</LinearLayout>

Above is used the tools:layout attribute to preview the BooksFragment layout, without running the project on a device or emulator.

Let’s take this view hierarchy:

activity_main:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

  <fragment
      android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      tools:layout="@layout/fragment_book"
      />

</LinearLayout>

fragment_book:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/list"
    android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    app:layoutManager="LinearLayoutManager"
    tools:context="com.alexsimo.mastertoolsnamespace.BooksFragment"
    tools:listitem="@layout/fragment_book_list_item"
    />

fragment_book_list_item:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="horizontal"
              xmlns:tools="http://schemas.android.com/tools">

  <ImageView
      android:layout_width="150dp"
      android:layout_height="150dp"
      android:id="@+id/imageView"
      tools:src="@android:drawable/ic_media_play"
      />
  <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    <TextView
        android:id="@+id/id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem"
        tools:text="My book title"
        />
    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem"
        tools:text="My book description"
        />
  </LinearLayout>

</LinearLayout>

If i open the preview window for activity_main, i will see the following:

Preview list item’s layout

If you were a bit sharp, in the above xml snippet you saw the tools:listitem="" line. While previewing a list is useful to see it with your own custom list item and not the default one @android:layout/list_content".

There are more related attributes, but as RecyclerView doesn’t have a header or footer property, can only be used with ListView. The mentioned attributes are tools:listheader and tools:listfooter.

Views with parent context

Imagine you have a custom view or reusable layout that will be used in many other places using <include> tag. While designing the custom view it may be helpful to preview how it would fit in the parent where is planned to be included.

With the above fragment_book_list_item if we add tools:showIn="@layout/activity_main", we can preview how this list item would fit in the activity_main. It doesn’t make lot of sense, but just for demonstrating the concept.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="horizontal"
              xmlns:tools="http://schemas.android.com/tools"
              tools:showIn="@layout/activity_main">
    <!-- Remaining views removed -->
</LinearLayout>

It would be previewed like this:

It also depends on your Android Studio version. At writing the article i’m using Android Studio v2.1.

Associate XML to an Activity

I’m sure this attribute you may already know it, by default when creating an Activity using Android’s Studio wizard, in the generated XML file you will find this attribute tools:context=".MainActivity". As you may know, a single xml layout can be used by multiple activities or fragments, using this attribute, you tell Android Studio who’s the associated .java Activity class.

This can help the layout editor to guess the activities theme, since themes are used to be defined in the AndroidManifest.xml file.

Ignore Lint warnings

You should take special care with this attribute, as ignoring Lint warnings is not always a good idea. If Lint complains, you should act and fix the errors and warnings. But sometimes, Lint gives us false warnings, we are aware and we know what we’re doing (or not..). In those cases you can use tools:ignore="".

Imagine we have an icon who’s missing its density folder, we may ignore the Lint warning with tools:ignore="IconMissingDensityFolder". You can read more about Lint at official Android’s documentation.

Preview layouts with menus

By default the menu defined in the Activity.onCreateOptionsMenu() is rendered in the preview window on design mode. But you can override the menu using tools:menu="comma separated menu IDs". This attribute, personally i don’t use it, but may be helpful for you.

Set Toolbar navigation mode

This one is short! Using tools:actionBarNavMode="standard|list|tabs" you can set the ActionBar’s navigation mode.

Shrink resources

There are more android tools namespace attributes related with resources shrinking, like tools:shrinkMode="strict|safe", tools:keep="@layout|layout_wildcard", tools:discard="@layout/unused" but i prefer not to talk about them here, since this article is not about shrink resources, if interested you can read more about in Android Studio’s official documentation.

References:


Viewing all articles
Browse latest Browse all 17

Trending Articles