Skip to main content

Actionbar and toolbar using support library

Action bar has been our friend since a long time. But it has its own drawbacks. You can not change its color, or size or appearance of its elements.

So came toolbar in android Lollipop. The beauty of this is, you add a toolbar like any other item in the layout xml file, set its color, size, position. Then add a few lines of code to make it an action bar.

So let us dive straight into coding.

I am using support library for toolbar and also appcompat activity. If you do not want to bother about devices with older versions than 5.0, you can straight use toolbar.


You can find toolbar in appcompat option in Android studio design view of your xml file.

So you insert that toolbar in the layout xml file.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent" 
   android:layout_margin="10dp" 
android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme" /> 
 </LinearLayout>


Now you can notice that it already has background as colorPrimary. Next let us set this toolbar as actiobar writing some code in onCreate() function of our activity.

Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        if(toolbar!=null){            
            setSupportActionBar(toolbar); 
getSupportActionBar().setTitle("My activity");  
 }

Now this is how our output screen looks like

What went wrong? Why is the actionbar cropped at left and right ends? And where is the title?

The layout_margin="10dp" causes even the actionbar to have a margin. Remove that line from parent linearlayout.

Actionbar title will not be set unless we mention it before setting toolbar as action bar. We shall correct both now.

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

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme" /> 
 </LinearLayout>


Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        if(toolbar!=null){
            toolbar.setTitle("your title");
            setSupportActionBar(toolbar);           
        }

After these two corrections, our action bar is ready like this. 

But if you have a theme such as
Theme.AppCompat.Light.NoActionBar 
then the actionbar title will be in black. To have white text but still using them light, we need to modify the toolbar like this.

<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
          />


Next we need to add home navigation to actionbar. That is done using changes in java file as well as androidmanifest.xml file.


Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        if(toolbar!=null){
            toolbar.setTitle("your title");
            setSupportActionBar(toolbar);
            ActionBar actionBar = getSupportActionBar();
            actionBar.setDisplayShowHomeEnabled(true);
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setDisplayShowTitleEnabled(true);
            actionBar.setHomeButtonEnabled(true);
        }

And in manifest file - androidmanifest.xml add these lines to your activity

<activity 
android:name=".youractivity" 
         android:parentActivityName=".yourhomeactivity">
             <meta-data android:name="android.support.PARENT_ACTIVITY"
            android:value=".yourhomeactivity">
            </meta-data>
 </activity>

parentActivityName is used for mentioning home activity. But for sdks less than 4.0, we need to provide the metadata as shown above.

OK. Now we have a pretty actionbar plus home navigation. Now how about some menu options?

You can add menu options in two different ways. a) Add buttons to toolbar. b) use onCreateOptions menu. Let us see the second option.

   @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.mymenu,menu);
        return true;
    }
 
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if(id==R.id.print){
            TextView tv = new TextView(this);
            tv.setLayoutParams(
               new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
            tv.setText("Hello world");
            LinearLayout linearLayout = (LinearLayout)findViewById(R.id.linlayout);
            linearLayout.addView(tv);
            return  true;
        }  
        return true;
    }
 


printhello is a dummy options menu entry which will print helloworld in a textview by creating textview dynamically.

First we use createOptionsMenu to inflate the options menu defined by menu file mymenu.xml in /res/menu folder

<?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:title="printHello"
    android:id="@+id/print"
    app:showAsAction="ifRoom"/>
</menu>

Next in onOptionsItemSelected we print helloworld on textview which we create and add to linearlayout.

But now a strange thing happens. The home button does not work. So home navigation is not present.

There are two ways of overcoming this.
  • Do not return true from onOptionsItemSelected 
    • public boolean onOptionsItemSelected(MenuItem item) {
              int id = item.getItemId();
              if(id==R.id.print){
                  TextView tv = new TextView(this);
                  tv.setLayoutParams(
      
                     new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                          ViewGroup.LayoutParams.WRAP_CONTENT));
                  tv.setText("Hello world");
                  LinearLayout linearLayout = (LinearLayout)findViewById(R.id.linlayout);
                  linearLayout.addView(tv);
                  return  true;
              }  
              return false;
          }
       
      
  • Take home as a separate itemid and write code for that

   @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.mymenu,menu);
        return true;
    }
 
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if(id==R.id.print){
            /*write your code*/
            return  true;
        } else if (id==android.R.id.home){
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return true;
    }
 

 That's it. Now you are well equipped to toolbar as actionbar to any activity in your android app.

Comments

Popular posts from this blog

Copy to clipboard

In my upcoming app, I have codes which I display. These are some times lengthy, and I want the app to be able to copy this to clipboard. Once it is in clipboard, users can paste it anywhere. So how do you copy some text from your app to clipboard. You need to use clipboard manager. Clipboard Manager This class sets and gets data for the clipboard using Clipdata objects.  You can get the object of this class using system service.  - using statement context.getSystemService(Context.CLIPBOARD_SERVICE) Example I have a dummy project with a button, onclick of which copies content to clipboard. Here is my activity file package com . hegdeapps . testapp ; import android.content.ClipData ; import android.content.ClipboardManager ; import android.support.v7.app.AppCompatActivity ; import android.os.Bundle ; import android.view.View ; import android.widget.Button ; import android.widget.TextView ; public class MainActivity extends ...

Drawables in Android - Layer drawable

Let us see how to use layer drawable. You can have two or more bitmaps on different layers to create such a drawable Using xml : You should use layer-list in your xml file to create layerdrawable. Here is layer.xml <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <bitmap android:src="@drawable/whiteicon" android:gravity="top|left"/> </item> <item> <bitmap android:src="@drawable/blueicon" android:gravity="top|left"/> </item> <item> <bitmap android:src="@drawable/redicon" android:gravity="top|left"/> </item> </layer-list> We are using three different bitmaps whiteicon.png, redicon.png and blueicon.png which are present in /res/drawable/mdpi folder. All these are of different sizes and aligned to top left. Thi...

Using a list fragment with cursor adapter

All these days, I avoided using fragments. But then I realized for my this particular applications fragments are ideal. I have a master - detail list in my app. Let us say you want to have two fragments - one is a fragment which contains a list of elements and second one expands one element of the list. Both of them share the same cursor from the activity. Let us start with list fragment. Do not try creating list fragment using a wizard. It unnecearrily adds too many methods and classes. Let us start writing our own fragment like this class MyListFragment extends ListFragment { } Next using code menu override option, override the following method onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) This method should be used for inflating the layout file for the fragment.  I have a framelayout in parent activity of this fragment with the id as container. So I will specify that for inflating. The framelayout will be the paren...