Creating adaptive, legacy, tab and action bar icons with Image Asset Studio

Designing a professional-looking UI is an essential part of delivering a good user experience.

While there’s no shortage of guidelines and advice on how to craft the perfect UI, in this article we’ll be focusing on an area of user interface design that’s easy to overlook: your app’s icons.

We’ll be using Android Studio’s built-in Image Asset Studio to quickly and easily create action bar icons and tab icons, plus adaptive and legacy launcher icons, across all the screen configurations that your application supports.

Once you’ve created these icons, you’ll want to actually use them, so along the way we’ll also be creating interactive action bars and multi-tab user interfaces, ready to display your new icons.

What icons do I need?

Even though we tend to use “app icons” as a generic term, Android app icons can be divided into three distinct categories:

  • Launcher icon. This is the icon that represents your app on the device’s homescreen, app drawer, Settings application, and in shortcuts and sharing dialogs. Launcher icons can either be adaptive (API level 26 and higher) or legacy (API level 25 or earlier). Depending on your app’s minSdkVersion, you may need to provide an adaptive and a legacy icon, or a legacy icon only.
  • Action Bar icons. By default, the action bar displays your app’s title and overflow menu, but it can also include action icons. These icons represent the most important action for the current context, for example if you were viewing a message inside an SMS app, then the action bar might include a “Reply” action.
  • Tab Icons. These represent the tabs in a multi-tab interface.

Icon design made easy with Image Asset Studio

Creating multiple app icons can be time-consuming, but if you have Android 3.0 or higher installed then you already have access to Image Asset Studio, a tool that can help you quickly and easily generate all the icons your application needs.

Every time you create a launcher, action or tab icon using Image Asset Studio, it automatically generates alternative icons for all the different pixel densities, and places them in the correct density-specific folders, potentially saving you a tonne of time. You can even use the Image Asset Studio to generate a web icon, ready to use in your app’s Google Play listing!

We’ll be using the Image Asset Studio throughout this tutorial, so launch it by selecting “File > New > Image Asset” from the Android Studio toolbar, or by Control-clicking your project’s “res” folder and selecting “New > Image Asset.”

Creating an Action Bar icon

Let’s start by adding an action bar icon to our project:

  • If you haven’t already, launch the Image Asset Studio (“File > New > Image Asset”).
  • Open the “Icon Type” dropdown and select “Action Bar and Tab icons.”
  • Give your icon a name. If your project already contains an icon with the same name, then Image Asset Studio will warn you before replacing the original resource.
  • Select the type of asset that you want to use in your icon:
  1. Image. To use an image that’s stored locally, select “Image,” then click the little “…” button and choose an image from your hard drive.
  2. Clip Art. This launches a window where you can select an icon from Google’s Material Design icon set.
  3. Text. You can supply some text that Image Asset Studio will then convert into a PNG file, ready to use in your icon.

Depending on the type of asset you select, you can then edit your asset using some, or all of the following options:

  • Trim. Removes any transparent space between the icon graphic and the icon border, while preserving the aspect ratio.
  • Padding. Adjusts the amount of space around your icon.
  • Theme. Choose between “HOLO_LIGHT” or “HOLO_DARK,” or create your own theme by selecting “CUSTOM.”

Once you’re happy with your icon, click “Next.” The following screen displays the directories where the different density-specific icons will be stored.

By default, icons are stored in the “main” directory, where they can be used by all build variants, including debug and release builds. If you’d prefer to restrict this icon to a specific build variant, then open the “Res directory” dropdown and select either “debug” or “release.”

Finally, click “Finish” and Image Asset Studio will generate your icons, and place them in the appropriate directories.

Getting more out of the Action Bar: Adding icons

Next, you need to display the icon as part of your app’s action bar, by creating a menu resource file and then adding the icon as an <item> element.

If your project doesn’t already contain a “res/menu” directory and a menu.xml file, then you’ll need to create them:

  • Control-click your project’s “res” folder and select “New > Android resource directory.”
  • In the “Directory name” field, enter “menu.”
  • Open the “Resource type” dropdown, and select “menu.”
  • Click “OK.”
  • Control-click your project’s “menu” folder and select “New > Menu resource file.”
  • Enter the filename “menu” and then click “OK.”

Inside the menu.xml file, create an <item> element for each action bar icon, for example:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto">
 <item
 android:id="@+id/my_action"
 android:icon="@drawable/ic_my_action"
 android:title="My action"
 app:showAsAction="ifRoom"/>
</menu>

The app:showAsAction attribute specifies whether this icon should be displayed in the action bar, or the overflow menu:

  • app:showAsAction=”ifRoom.” The icon is displayed in the action bar, wherever possible. If the action bar is full, then the icon will be moved to the overflow menu.
  • app:showAsAction=”never.” The icon is displayed in the overflow menu only.

Every time the user interacts with an action bar icon, the system will call your Activity’s onOptionsItemSelected() callback method. You’ll need to determine which icon has been clicked, by calling MenuItem.getItemId() inside your onOptionsItemSelected() implementation, and then stating the action that should be performed. For example, here I’m displaying a toast whenever the user interacts with the “my_action” icon:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {

//Inflate the menu//

 getMenuInflater().inflate(R.menu.menu, menu);
 return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

//Every time an action button is clicked, return the identifier for that menu item//

 int id = item.getItemId();

//If the id is "my_action"//

 if (id == R.id.my_action) {

//Display a Toast//

 Toast.makeText(MainActivity.this,
 "Action button clicked", Toast.LENGTH_LONG).show();

 }

 return super.onOptionsItemSelected(item);
 }
}

Run this app on a physical Android device or Android Virtual Device (AVD), and give the action bar icon a tap – it should respond by displaying a toast.

Displaying icons in a mutli-tab UI

You add a tab icon to your project, in exactly the same way you add an action bar icon, so open the Image Asset Studio, select “Action Bar and Tab icon” from the dropdown menu, and then create your icon as normal. In this section, I’m working with two tab icons, “ic_messages” and “ic_contacts.”

Once you’ve created one or more tab icons, you’ll need to create some tabs. There’s several ways to implement tabs, but I’m going to create a TabLayout component and then add each tab declaratively, as an TabItem element. Note that TabItems are just dummy Views that let you set each tab’s text, icon and layout – you’ll still need to define the actual content for each tab.

I’m also implementing a ViewPager, so the user can swipe left and right through the tabs.

 <android.support.design.widget.TabLayout
 android:id="@+id/tablayout"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">

 <android.support.design.widget.TabItem
 android:id="@+id/tabMessages"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"

//The drawable that you want to use as this tab’s icon//

 android:icon="@drawable/ic_messages"/>

 <android.support.design.widget.TabItem
 android:id="@+id/tabContacts"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"

//The drawable that you want to use as this tab’s icon//

 android:icon="@drawable/ic_contacts" />

 </android.support.design.widget.TabLayout>

 <android.support.v4.view.ViewPager
 android:id="@+id/viewPager"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" />

</LinearLayout>

You then define each tab’s content in a separate XML file, for example here’s the content of my “fragment_contacts.xml” tab:

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

 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical|center_horizontal"
 android:text="Contacts"
 android:textSize="40sp" />

</FrameLayout>

Next, you need to inflate the layout for each tab fragment. Here’s my corresponding ContactsFragment.java file:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class ContactsFragment extends Fragment {

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
 Bundle savedInstanceState) {
 return inflater.inflate(R.layout.fragment_contacts, container, false);
 }

}

Rinse and repeat for every tab, for example I’ve also created MessagesFragment.java and fragment_messages.xml files.

Since we’re using a ViewPager, we need to create a new class that manages the fragments that’ll be displayed whenever the user selects a new tab. This class must implement the getItem() method, which will be called every time a new fragment is requested. This method uses a switch statement to identify and return the appropriate fragment instance.

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

public class PageAdapter extends FragmentPagerAdapter {

 private int totalTabs;

 PageAdapter(FragmentManager fragmentManager, int totalTabs) {
 super(fragmentManager);
 this.totalTabs = totalTabs;
 }

 @Override
 public Fragment getItem(int position) {
 switch (position) {
 case 0:
 return new MessagesFragment();
 case 1:
 return new ContactsFragment();
 default:
 return null;
 }
 }

 @Override
 public int getCount() {
 return totalTabs;
 }
}

Finally, open your MainActivity.java file and use the TabLayout.OnTabSelectedListener method to detect when the user selects a new tab.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.support.v4.view.ViewPager;
import android.widget.Toast;

import android.support.design.widget.TabItem;
import android.support.design.widget.TabLayout;

public class MainActivity extends AppCompatActivity {

 ViewPager viewPager;
 PageAdapter pageAdapter;
 TabLayout tabLayout;
 TabItem tabContacts;
 TabItem tabMessages;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 tabContacts = findViewById(R.id.tabContacts);
 tabLayout = findViewById(R.id.tablayout);
 tabMessages = findViewById(R.id.tabMessages);
 viewPager = findViewById(R.id.viewPager);

 pageAdapter = new PageAdapter(getSupportFragmentManager(),

//Pass the number of tabs that have been assigned to the TabLayout component//

tabLayout.getTabCount());
 viewPager.setAdapter(pageAdapter);

//Add a TabLayout.OnTabSelectedListener//

 tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
 @Override

//Set the current page to the currently-selected tab number//

 public void onTabSelected(TabLayout.Tab tab) {
 viewPager.setCurrentItem(tab.getPosition());
 if (tab.getPosition() == 1) {

 }
 }

 @Override
 public void onTabUnselected(TabLayout.Tab tab) {

 }

 @Override
 public void onTabReselected(TabLayout.Tab tab) {

 }
 });

//Add the TabLayout to the page change listener//

 viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

 }

This gives us a UI consisting of a “Messages” tab, and a “Contacts” tab.

You’ll find the complete code for this project, over at GitHub.

Android Oreo and higher: Creating Adaptive icons

In Android 8.0 and higher, device OEMs (Original Equipment Manufacturers) can provide masks, which the Android system then uses to render all adaptive launcher icons with the same shape, for example an icon might appear circular on one device, and rectangular on another.

Adaptive launcher icons consist of a background and a foreground layer, which you must provide as drawables sized at 108 x 108 dp, without masks or background shadows. These layers are then cut into shape by the launcher, using the mask provided by the OEM.

If your app supports Android Oreo or higher, then you’ll need to provide an adaptive launcher icon to ensure your app is visually consistent with the rest of the user’s device. While it’s good for your application to stand out from the crowd, you don’t want it getting noticed for all the wrong reasons!

If your app’s minsdkversion is Nougat or earlier, then you’ll also need to provide a legacy launcher icon, which will be used on devices running earlier versions of Android.

You can create an adaptive and a legacy icon at the same time, using the Image Asset Studio:

  • In Image Asset Studio, open the “Icon type” dropdown and select “Launcher Icons (Adaptive & Legacy).”
  • Give your icon a name.
  • Select the “Foreground Layer” tab.
  • Choose the type of asset that you want to use as your icon’s foreground layer: Image, Clip Art, or Text.

Once you’ve chosen an asset type, you can tweak that asset using familiar settings such as Trim, as well as some additional options:

  • Layer name. Give this layer a unique name.
  • Color. If you’re using Clip Art, then this will change the color of the icon; if you’re using text, then it’ll change the color of the text.
  • Resize. Change the size of your icon, ranging from the minimum 0%, to the maximum 400%.

Rinse and repeat, to create your icon’s background layer:

  • Select the “Background Layer” tab.
  • Assign the layer a unique name.
  • Choose an Image, Clip Art, or Text asset.
  • Edit your asset, as required.

Finally, select the “Legacy” tab and specify that you want to create a legacy icon. You can provide this icon in the following shapes: None (a square with sharp corners) Circle, Square (a square with rounded corners), a Vertical rectangle or a Horizontal rectangle.

Once you’re happy with your icon:

  • Click “Next.”
  • Specify whether you want to use this icon for your main, debug or release builds.
  • Click “Finish.”

If you’re curious about how the background and foreground layers come together to create an adaptive icon, then open your project’s res/mipmap-anydpi folder; it should contain a new XML file that’s responsible for combining these layers.

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
 <background android:drawable="@drawable/ic_launcher_background" />
 <foreground android:drawable="@mipmap/ic_launcher_foreground" />
</adaptive-icon>

To use this adaptive launcher icon, open your AndroidManifest.xml file, find the android:Icon attribute and make sure android:icon is referencing the “mipmap” file that Image Asset Studio has just created.

<application
 android:allowBackup="true"

//Update android:Icon//

 android:icon="@mipmap/my_launcher"

...
...
...

Only supporting earlier versions of Android?

If your app only supports Android 7.1 (API level 25) and earlier, then you just need to provide a legacy icon, which consists of a single layer.

  • Open the “Icon Type” dropdown, and select “Launcher icons (legacy only).”
  • Give your icon a name.
  • Choose the asset that you want to use: Image, Clip Art, or Text.

Depending on your chosen asset, you can then edit your icon using some, or all of the following:

  • Trim. Remove the transparent spaces around your icon.
  • Padding. Adjust the amount of padding around your icon.
  • Color. Change the foreground or background color.
  • Scaling. Choose between “Shrink to Fit” and “Crop.” Depending on the asset you’ve selected, cropping may remove some of the icon’s content.
  • Shape. Add a backdrop to your source asset, by selecting Circle, Square, Vertical, or Horizontal. Alternatively, you can remove the backdrop by selecting “None.”
  • Effect. If you’ve selected Square, Vertical, or Horizontal, then you can add a “dog-eared” effect, as shown in the following screenshot.

Wrapping up

In this article, we looked at how you can use Image Asset Studio to quickly and easily create various icons for your Android apps, and how to use those icons, by creating tabs and interactive action bars.

Do you have any tips for creating effective Android app icons? Let us know in the comments below!

Creating adaptive, legacy, tab and action bar icons with Image Asset Studio

Be the first to comment

Leave a Reply

Your email address will not be published.


*