Showing posts with label ActionBars. Show all posts
Showing posts with label ActionBars. Show all posts

Sunday, November 3, 2013

ActionBarCompat - Action Item's basics

This post discusses how to add Actionitem's using compat library. For configuring v7 libararies, look here.

My Menu acction_bar.xml file goes like this.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:compat="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/action_settings"
        compat:showAsAction="always"
        android:title="@string/action_settings"/>
    <item
        android:id="@+id/action_help"   
        compat:showAsAction="never"
        android:title="@string/action_help"/>
    
</menu>

Observe the above XML contain's xmlns:compat attribute. This attribute is pointing to the Application resources. The attribute compat:showAsAction will bind at run time and thus uses compat library. It is very important to use xmlns:compat.

Use the Menu xml in my ActionBarActivity like

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.acction_bar, menu);
        return true;
    }


Output :

Action bar with Action bar compat libararies



Action bar compatible library configuration

Android is providing compat libraries for Android level grater than 7 i.e Andorid Os version 2.1 and above. In this post I would like to discuss the configuration of Actionbar Compat project.

  • Download V7 library project from here
  • Import the downloaded project into the current work space.
  • Build the project.
  • Create  New Android Project.
  • Add the imported project as the supporting project.
Properties of the new working project

As shown above, add the  supporting project as library for the current working project.
Now you are ready with the configuration. 

Post configuration:
Some points to be noted for using the App compat action bar are:
  • The Class which wish to use AppCompat features must extend with ActionBarActivity.
  • In the res - > values --> styles.xml, Modify the AppBaseTheme to
    • <style name="AppBaseTheme" parent="Theme.AppCompat.Light"> for light theme.

Wednesday, June 5, 2013

Navigation Mode's in Android Action Bars

Actions bar's can be represented in 3 different styles or formats

All these modes can be achieved using Sherlock as well as Native Action bar's. Native action bar's are supported from Android OS Version 3.0 and above.

Sherlock ActionBar with NavigationList

NavigationList is one more type of navigation in ActionBar's which serves the same functionality as tabs.

Let me show you how this look's like
Gmail App with Navigation list mode 
In the above pic, Upon click of Inbox, the navigation list appears.

If you are not familiar with the configuration of Sherlock Action Bar project please refer my previous post.

Comming back...To achieve List style of navigation mode, set the navigationmode of Action bar to ActionBar.NAVIGATION_MODE_LIST and pass the respective adapter for this list. The code is shown below.

/**
* Initialises the views and variables of the activity.
 */
private void init() {

    //  initialise ActionBar
    mActionBar = getSupportActionBar();
    mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
        
    //  Initialise Array Adapter.
    final ArrayAdapter arrayAdapter = new ArrayAdapter(this,
         android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
    arrayAdapter.add("Login");
    arrayAdapter.add("Elections");
    arrayAdapter.add("Maintainance");
    arrayAdapter.add("Results");
        
    //  Set array adapter to navigation list, implement a listener for the list.
            mActionBar.setListNavigationCallbacks(arrayAdapter, new OnNavigationListener() {
            @Override
            public boolean onNavigationItemSelected(int arg0, long arg1) {
                Toast.makeText(SherlockListActionBarActivity.this, arrayAdapter.getItem(arg0), Toast.LENGTH_SHORT).show();
                return false;
            }
        });
}

The above method should be called from onCreate() method of your SherlockActivity.

This method defines ActionBar, Prepares the Adapter for NavigationList, sets call back for Navigation List item click.

Related topics:

Tuesday, June 4, 2013

Android Sherlock Action Bars with Tab's

Action bar's provide a functionality to integrate tabs.

As mentioned in my previous post I'm just recapping how to configure Sherlock API with our project. 

Steps to implement Sherlock action bar include.
  • Download Sherlock source.
  • UnZip the source and find "actionbarsherlock" folder, which is the library project for implementing Sherlock ActionBar.
  • Import the library project into the workspace.
  • Create a new Android Project.
  • Click on properties of the project and add "actionbarsherlock" as library project.

  • Extend your class with SherlockActivity        
public class SherlockAtionBar extends SherlockActivity
  • Override onCreate and setTheme as one of the sherlock theme before calling super.onCreate()
Now, we are almost ready to implement our tabbed action bar.

Here I would like to use a ViewPager, Fragments along with Tab's.  Add tabs to ActionBar, intialiase FragmentPagerAdapter, set FragmentPagerAdapter to ViewPager, integrate tab clicks with viewpager.

The complete activity looks like

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.ActionBar.TabListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.vl.actionbar.LoginFragment;
import com.vl.actionbar.R;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewParent;

import java.util.ArrayList;

/**
 * Sherlock Action Bar to demonstrate Tabs behavior
 * 
 * @author shpolavarapu
 * 
 */
public class SherlockTabsActionBarActivity extends SherlockFragmentActivity {

    private ViewPager mViewPager;
    private ActionBar mSupportActionBar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.Theme_Sherlock_Light_DarkActionBar);
        super.onCreate(savedInstanceState);
        
        init();
    }

    /**
     * Initialises the Views and variables for this activity.
     */
    private void init() {
        
        //  Initialise and set viewpager to the activity.
        mViewPager = new ViewPager(this);
        mViewPager.setId(1232);
        setContentView(mViewPager);
        
        //  Init and set ActionBar Properties.
        mSupportActionBar = getSupportActionBar();
        mSupportActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        
        //  Initialise Adapter for the view pager.
        SherlockTabAdapter adapter = new SherlockTabAdapter();
        ArrayList<Bundle> bundleAL = new ArrayList<Bundle>();
        String texts[] = {"Login", "Elections", "Polling", "Results"};
        for(int index = 0; index < texts.length; index++)
        {
            //  Prepare Bundle object for each tab.
            Bundle bundle = new Bundle();
            bundle.putString("text", texts[index]);
            bundleAL.add(bundle);
            
            //  Add tabs for the action bar.
            ActionBar.Tab tab = mSupportActionBar.newTab().setText(texts[index])
                    .setTabListener(adapter);
            mSupportActionBar.addTab(tab);
        }
        
        adapter.setBundle(bundleAL);
        mViewPager.setAdapter(adapter);
        mViewPager.setOnPageChangeListener(adapter);
    }




    /**
     * Adapter for setting the content for the tab click's.
     * 
     * @author shpolavarapu
     * 
     */
    private class SherlockTabAdapter extends FragmentPagerAdapter implements ActionBar.TabListener,
            ViewPager.OnPageChangeListener {

        private ArrayList<Bundle> mBundleAL;
        
        public SherlockTabAdapter() {
            super(getSupportFragmentManager());
        }
        
        /**
         * ArrayList of bundle's to pass as Arguments to Fragment.
         * @param bundleAL  ArrayList of bundle's
         */
        void setBundle(ArrayList<Bundle> bundleAL) {
            mBundleAL = bundleAL;
        }
        @Override
        public void onPageScrollStateChanged(int position) {
            
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {

        }

        @Override
        public void onPageSelected(int position) {
            //  Change the tab selection upon page selection.
            mSupportActionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onTabReselected(Tab arg0, FragmentTransaction arg1) {

        }

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction arg1) {
            //  On Tab selection change the View Pager's Current item position. 
            mViewPager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {

        }

        @Override
        public Fragment getItem(int pos) {
            return Fragment.instantiate(SherlockTabsActionBarActivity.this, LoginFragment.class.getName(), mBundleAL.get(pos));
        }

        @Override
        public int getCount() {
            return mBundleAL.size();
        }

    }

}

The LoginFragment is posted below.

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

public class LoginFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        
        View view = inflater.inflate(R.layout.login, null);
        if(getArguments() != null)
        {
            String text = getArguments().getString("text");
            ((TextView)view.findViewById(R.id.tv_login)).setText(text);
        }
        return view;
    }
}

login Layout is posted below :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical" >

     <TextView
        android:id="@+id/tv_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Login" />


</LinearLayout>

Output :


Overview:

 Create Tabs and ArrayList of Bundle data which contain name of the tab. Create a ViewPager and set the FragmentPagerAdaper to it. The Adapter also listens TabClick and ViewPager PageChange. On TabClick, Login Fragment with the bundle data as arguments is instantiated  and supplied to viewpager.

Don't forget to add NavigationMode as ActionBar.NAVIGATION_MODE_TABS. Native Action Bar's implementation with tabs can also use the same code with minor changes,

Related topics : 

Android Action Bar MenuItem's using Sherlock API

Android introduced Action bar's in API level 11 i.e in HoneyComb 3.0. Native implementation is posted here.  There is no backward compatibility as of now. This leads to our point of discussion.

In some cases where our action bar needs to be compatible from Android SDK version 2.1. In such cases we can go with Sherlock API.

Steps to implement Sherlock action bar include.
  • Download Sherlock source.
  • UnZip the source and find "actionbarsherlock" folder, which is the library project for implementing Sherlock ActionBar.
  • Import the library project into the workspace.
  • Create a new Android Project.
  • Click on properties of the project and add "actionbarsherlock" as library project.


Now, we are ready to implement our action bar.

1) Extend your class with SherlockActivity
            
public class SherlockAtionBar extends SherlockActivity

2) Override onCreate and setTheme as one of the sherlock theme before calling super.onCreate()

@Override
protected void onCreate(Bundle savedInstanceState) {
    setTheme(R.style.Theme_Sherlock);   
    super.onCreate(savedInstanceState);
    setContentView(R.layout.login);
}

3) Override onCreateOptionsMenu()


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Collapsible Action Item
    menu.add("Search").setIcon(R.drawable.ic_search)
                      .setActionView(R.layout.collapsible_edittext)  
                          .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | 
                                  MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);

    // OverFlow menu in actionbar.
    SubMenu submenu = menu.addSubMenu("");
    submenu.setIcon( R.drawable.abs__ic_menu_moreoverflow_normal_holo_dark);

    submenu.add(1, 0, 1, "Cut");
    submenu.add(1, 1, 2, "Copy");
    submenu.add(1, 2, 3, "Paste");
    submenu.getItem(). setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS|
                         MenuItem.SHOW_AS_ACTION_WITH_TEXT);
    // end overflow menu

   return true;
}


My collapsible_edittext layout looks like


<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:hint="Search"/>


That's it ..... our action bar with menu items and action view is ready. Snapshot of output is shown below.
 
Sherlock action bar with Action view, menu item's and sub menu item's

 I will now explain code in OnCreateMenuOptions(). First with the submenu thing.

If we add menu items to Menu directly using Menu.add(), Actionbar will have different UI for different OS versions of Android. For 3.0 and above it will be shown as overflow menu like in the above picture. For Android OS version's less than 3.0, action bar's overflow type of menu is overrided by the default menu's(at the bottom). I think you got my point... For consistent behaviour of overflow menu's, we have to use SubMenu instead of Menu. Don't forget to add setShowAction() property for the sub menu item. This property will change the style of the menu's to overflow.

We also have some default things for an activity such as Search. Considering these functionalities,  concept of ActionViews is introduced. In the above discussed OnCreateMenuOptions(), we have added search menu item to Menu and provided collapsible_edittext layout for the ActionView. Upon click of search Menu Item the layout appears on the top of action bar like ..

Sherlock ActionBar with Action View.
As per our layout edit text appears with hint as Search.

Split ActionBar :

 We can split the action bar based on the space availability. Just add a tag android:uiOptions = "splitActionBarWhenNarrow".

Observe the change in the below output by using this tag.

Split action bar in Android Phone
The split behavior is different in large screens. See the below output in Nexus 10 device.


From this observation, we can judge that split behavior comes into act when there is no real estate to display on action bar .

Related topics : 

Saturday, June 1, 2013

Andoroid Action Bar Menu items

ActionBar is a header sort of thing with number of powerful options to play with the application.
Let us come to a conclusion why to go for an action bar?

We will be having some options in our activity like.. popping a Menu, search in the activity, Tabs, title, app icon  etc. Think, if there is a mechanism where we can handle all these tasks in a single view sort of thing.. Yes .. this can be achieved by action bars.

The above pic represents action bar in Google Play App.

Before learning the tabbed behavior, we will go through the integration of menu items with Actionbars. The new menu items with action bar looks like :


Three vertical dots represent the Menu, Upon Click menu items will be populated.

Coming to implementation, there are no changes compared to implementation of menu in previous versions.
  1. Define menu options in xml.
  2. Inflate them and add it to the menu in OnCreateOptionsMenu method.
My menu action_items.xml look like.

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/refresh"
        android:icon="@drawable/refresh"
         
        android:title="Refresh"/>
    <item
        android:id="@+id/inbox"
        android:icon="@drawable/email"
        android:title="Inbox"/>

    <item
        android:id="@+id/compose"
        android:title="Compose"/>

</menu>

Now, Override OnCreateOptionsMenu() and inflate menu. This piece of code is shown below.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.action_items, menu);
    return true;
}

We are having number of options to arrange menu within this action bar itself. We can display icons for these menu items.For displaying menu icons provide another tag android:showAsAction="ifRoom". This will show the menu item's icon, if there is sufficient room on the ActionBar. This output wil be like


My action_items.xml look like

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/refresh"
        android:icon="@drawable/refresh"
        android:showAsAction="ifRoom"
        android:title="Refresh"/>
    <item
        android:id="@+id/inbox"
        android:icon="@drawable/email"
        android:showAsAction="ifRoom"
        android:title="Inbox"/>
    <item
        android:id="@+id/compose"
        android:title="Compose"/>

</menu>


Observe showAsAction tag.

We can split the action bar's to the bottom of the screen when screen is narrow. This can be achieved by adding a tag in manifest file. Add android:uiOptions="splitActionBarWhenNarrow" tag in the Activity of manifest file. The output will be looking like.




With the uiOptions tag in Manifest file, the complete menu is pushed to bottom. In landscape, considering the real estate available, these UI changes wont be reflected. Menu will be placed on the top in landscape mode.

In Some of the devices, where the menu hard key is present, the menu options with 3 dots will not be shown. The default behavior of the device will override the action bar behavior. In such cases, if you strictly want the action bar behavior, call the below method in onCreate() method of your activity.

private void getOverflowMenu() {

     try {
        ViewConfiguration config = ViewConfiguration.get(this);
        Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
        if(menuKeyField != null) {
            menuKeyField.setAccessible(true);
            menuKeyField.setBoolean(config, false);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

For the backward compatibility of Action Bar's, refer to the topic ActionBar's with Sherlock API

Related topics :