Jul 18, 2013

How to develop google plus app like bottom menu ?

How to develop Google+ app like bottom menu ?
Google+ app detects scroll direction to maintain visibility of bottom menu bar. When user scroll up content, bottom menu will hide with animation so that user can see the new item coming up from the bottom. When user scroll down, bottom menu bar will visible so that user can access menus available in bottom menu bar.

We can achieve same functionality using Animation, Fragment as bottom menu bar and onscrolllistener event of ListView. 

 

Step 1: Create Android Project in your favourite IDE

Step 2: Create Fragment for Bottom Menu, 
  • Create new java file named "BottomFragmentMenu.java"
  • Create new layout named "bottom_menu.xml" for the bottom menu fragment
  • Implement onCreateView method in BottomFragmentMenu.java and inflate bottom_menu.xml
  • Fetch ImageButton object from the view
  • Implement and set click listener of buttons
BottomFragmentMenu.java
package com.kpbird.bottommenubar;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Toast;

public class BottomMenuFragment extends Fragment implements OnClickListener {

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
  View view = inflater.inflate(R.layout.bottom_menu, container,false);
  ImageButton b1 =(ImageButton)view.findViewById(R.id.imageButton1);
  ImageButton b2 =(ImageButton)view.findViewById(R.id.imageButton2);
  ImageButton b3 =(ImageButton)view.findViewById(R.id.imageButton3);
  ImageButton b4 =(ImageButton)view.findViewById(R.id.imageButton4);

  b1.setOnClickListener(this);
  b2.setOnClickListener(this);
  b3.setOnClickListener(this);
  b4.setOnClickListener(this);
  
  return view;
 }

 @Override
 public void onClick(View v) {
  switch(v.getId()){
  case R.id.imageButton1:
   Toast.makeText(getActivity() ,"Button 1 clicked", Toast.LENGTH_LONG).show();
   break;
  case R.id.imageButton2:
   Toast.makeText(getActivity() ,"Button 2 clicked", Toast.LENGTH_LONG).show();
   break;
  case R.id.imageButton3:
   Toast.makeText(getActivity() ,"Button 3 clicked", Toast.LENGTH_LONG).show();
   break;
  case R.id.imageButton4:
   Toast.makeText(getActivity() ,"Button 4 clicked", Toast.LENGTH_LONG).show();
   break;
  }
 }
}
bottom_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#80666666"
    android:gravity="center_horizontal"
    android:orientation="horizontal" >

    <ImageButton
        android:id="@+id/imageButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button1" />

    <ImageButton
        android:id="@+id/imageButton2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button2" />

    <ImageButton
        android:id="@+id/imageButton3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button3" />

    <ImageButton
        android:id="@+id/imageButton4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:layout_margin="5dp"
        android:src="@drawable/button4" />

</LinearLayout>

Step 3: Create Animation for Bottom Menu, we require two animations 1 entry.xml and 2. exit.xml respectively for to make fragment visible and hide. It's very simple Object Animator with translationY property, If you are developing app for Android 2.3, you can use translate animation. 

entry.xml
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/linear"
    android:valueFrom="100"
    android:valueTo="0"
    android:propertyName="translationY"
    android:duration="@android:integer/config_shortAnimTime" />

exit.xml
<?xml version="1.0" encoding="utf-8" ?>
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/linear"
    android:valueFrom="0"
    android:valueTo="100"
    android:propertyName="translationY"
    android:duration="@android:integer/config_shortAnimTime"/>


Step 4: Let's modify activity_main.xml and  MainActivity.java files to have real action.
  • Open activity_main.xml and add ListView (with match_parent height and width) and add fragment (with match_parent width, wrap_content hight and align parent bottom).
  • Open MainActivity.java and populate ListView with countries, In this example I am using ArrayAdapter and String Array (from strings.xml).
  • Implement OnScrollListener of ListView, In onScroll method we just need to calculate whether user fling down or up, We need to hide bottom fragment when user scroll down and visible when user scroll up.
MainActivity.java
package com.kpbird.bottommenubar;

import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity implements OnScrollListener{

 private String TAG = this.getClass().getSimpleName();
 private ListView listview;
 private BottomMenuFragment bmfragment;
 private int lastposition;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  listview = (ListView) findViewById(R.id.listview);
  String[] countries = getResources().getStringArray(R.array.countries_array);
  ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, countries);
  listview.setAdapter(aa);
  listview.setOnScrollListener(this);
  
  bmfragment = (BottomMenuFragment) getFragmentManager().findFragmentById(R.id.fragment_bottom_menu);
  
 }
 @Override
 public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
   int currentPosition = view.getFirstVisiblePosition();
         if(currentPosition > lastposition) {
             //scroll down
          Log.i(TAG,"on Scroll Down");
          FragmentTransaction ft = getFragmentManager().beginTransaction();
          ft.setCustomAnimations(R.animator.enter, R.animator.exit);
       ft.hide(bmfragment);
       ft.commit();
         }
         if(currentPosition < lastposition) {
             //scroll up
          Log.i(TAG,"on Scroll Up");
          FragmentTransaction ft = getFragmentManager().beginTransaction();
          ft.setCustomAnimations(R.animator.enter, R.animator.exit);
       ft.show(bmfragment);
       ft.commit();
         }
         lastposition = currentPosition;
 }
 @Override
 public void onScrollStateChanged(AbsListView view, int scrollState) {
  
 }
}

Download Source from Github.com