Android

Android Working with Bottom Navigation

Pinterest LinkedIn Tumblr

Android Bottom Navigation stays at the bottom of the screen providing navigation between top-level views in the app. This is introduced in design support library with backward compatibility. Bottom Navigation should be used when the app has three to five top-level navigations.

This article explains the basics of Bottom Navigation, combining it with Fragments. We also going to learn how to load the first fragment with grid data (using RecyclerView) by fetching JSON through HTTP call.

1. Bottom Navigation

The Bottom Navigation can be easily added using BottomNavigationView component. You have to use gravitation or relative attributes to make it appear at the bottom of the screen.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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">
 
    <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 
    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="?android:attr/windowBackground"
        app:itemBackground="@color/bgBottomNavigation"
        android:foreground="?attr/selectableItemBackground"
        app:itemIconTint="@android:color/white"
        app:itemTextColor="@android:color/white"
        app:menu="@menu/navigation" />
 
</android.support.design.widget.CoordinatorLayout>

Here few important attributes have to noted down.

app:menu — The menu resource file to display the navigation items along with icon and text.
app:itemBackground — Applies background color to bottom navigation.
app:itemTextColor — The text color of bottom navigation item.
app:itemIconTint — The icon color of bottom navigation item.

When to use Bottom Navigation?
As per the design specs, the below navigations should be used depending on the criteria.

> Navigation Drawer – Use when top-level navigation has more than six destinations.

> Tabs – Use when there are two navigational destinations.

> Bottom Navigation – Use when there are three to five top-level destinations.

Before going further, have a quick look at the design specifications of Bottom Navigation.

Now let’s try it by creating a new project in Android Studio.

2. Creating New Project

1. Create a new project in Android Studio from File ⇒ New Project and select Basic Activity from templates.

2. Download this res folder and add the drawables to your project’s res. This folder contains necessary drawables required for bottom navigation items.

3. Make sure you have design support library in your build.gradle.

build.gradle
dependencies {
    implementation 'com.android.support:design:26.1.0'
}

4. Add below color, string values to your colors.xml and strings.xml.

colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#7b4bff</color>
    <color name="colorPrimaryDark">#6539ba</color>
    <color name="colorAccent">#FF4081</color>
    <color name="bgBottomNavigation">#fe485a</color>
</resources>
strings.xml
<resources>
    <string name="app_name">Bottom Navigation</string>
    <string name="title_shop">Shop</string>
    <string name="title_gifts">Gifts</string>
    <string name="title_cart">Cart</string>
    <string name="title_profile">Profile</string>
</resources>

5. As the Bottom Navigation items rendered using a menu file, create a new xml named navigation.xml under res ⇒ menu folder.

navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item
        android:id="@+id/navigation_shop"
        android:icon="@drawable/ic_store_white_24dp"
        android:title="@string/title_shop" />
 
    <item
        android:id="@+id/navigation_gifts"
        android:icon="@drawable/ic_card_giftcard_white_24dp"
        android:title="@string/title_gifts" />
 
    <item
        android:id="@+id/navigation_cart"
        android:icon="@drawable/ic_shopping_cart_white_24dp"
        android:title="@string/title_cart" />
 
    <item
        android:id="@+id/navigation_profile"
        android:icon="@drawable/ic_person_white_24dp"
        android:title="@string/title_profile" />
 
</menu>

6. Open the layout file of main activity i.e activity_main.xml and add BottomNavigationView widget. Here we are also adding a FrameLayout to load the Fragments when the navigation item is selected.

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="info.androidhive.bottomnavigation.MainActivity">
 
    <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 
    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="?android:attr/windowBackground"
        app:itemBackground="@color/bgBottomNavigation"
        android:foreground="?attr/selectableItemBackground"
        app:itemIconTint="@android:color/white"
        app:itemTextColor="@android:color/white"
        app:menu="@menu/navigation" />
 
</android.support.design.widget.CoordinatorLayout>

7. Now open MainActivity.java and modify it as below.

> Here, OnNavigationItemSelectedListener will be called when the bottom navigation item is selected. For now we are just changing the toolbar title upon selecting the navigation item.

MainActivity.java
package info.androidhive.bottomnavigation;
 
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
 
import info.androidhive.bottomnavigation.fragment.CartFragment;
import info.androidhive.bottomnavigation.fragment.GiftsFragment;
import info.androidhive.bottomnavigation.fragment.ProfileFragment;
import info.androidhive.bottomnavigation.fragment.StoreFragment;
import info.androidhive.bottomnavigation.helper.BottomNavigationBehavior;
 
public class MainActivity extends AppCompatActivity {
 
    private ActionBar toolbar;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        toolbar = getSupportActionBar();
 
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
 
        toolbar.setTitle("Shop");
    }
 
    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {
 
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            Fragment fragment;
            switch (item.getItemId()) {
                case R.id.navigation_shop:
                    toolbar.setTitle("Shop");
                    return true;
                case R.id.navigation_gifts:
                    toolbar.setTitle("My Gifts");
                    return true;
                case R.id.navigation_cart:
                    toolbar.setTitle("Cart");
                    return true;
                case R.id.navigation_profile:
                    toolbar.setTitle("Profile");
                    return true;
            }
            return false;
        }
    };
}

If you run the app, you can see the bottom navigation displayed as shown below.

3. Adding Fragments

As we have the Bottom Navigation ready, let’s see how to switch views when the navigation menu item is selected. This can be done easily by using the Fragments.

Note: ViewPager shouldn’t be used when using Bottom Navigation as per design specs (Avoid using lateral motion to transition between views)

I am creating four fragments named StoreFragmentGiftsFragmentCartFragment and ProfileFragment.

8. Create new Fragment by going to File ⇒ New ⇒ Fragment ⇒ Fragment (Blank) and name it as StoreFragment.java. Likewise create other three fragments too.

9. Open MainActivity.java and modify bottom navigation listener as below to load the fragments in FrameLayout.

> loadFragment() – loads the Fragment into FrameLayout. The same method is called in OnNavigationItemSelectedListener callback by passing appropriate fragment instance.
> The logic needed for specific module goes into appropriate Fragment keeping the MainActivity clean.

MainActivity.java
package info.androidhive.bottomnavigation;
 
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
 
import info.androidhive.bottomnavigation.fragment.CartFragment;
import info.androidhive.bottomnavigation.fragment.GiftsFragment;
import info.androidhive.bottomnavigation.fragment.ProfileFragment;
import info.androidhive.bottomnavigation.fragment.StoreFragment;
import info.androidhive.bottomnavigation.helper.BottomNavigationBehavior;
 
public class MainActivity extends AppCompatActivity {
 
    private ActionBar toolbar;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        toolbar = getSupportActionBar();
 
        // load the store fragment by default
        toolbar.setTitle("Shop");
        loadFragment(new StoreFragment());
    }
 
    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {
 
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            Fragment fragment;
            switch (item.getItemId()) {
                case R.id.navigation_shop:
                    toolbar.setTitle("Shop");
                    fragment = new StoreFragment();
                    loadFragment(fragment);
                    return true;
                case R.id.navigation_gifts:
                    toolbar.setTitle("My Gifts");
                    fragment = new GiftsFragment();
                    loadFragment(fragment);
                    return true;
                case R.id.navigation_cart:
                    toolbar.setTitle("Cart");
                    fragment = new CartFragment();
                    loadFragment(fragment);
                    return true;
                case R.id.navigation_profile:
                    toolbar.setTitle("Profile");
                    fragment = new ProfileFragment();
                    loadFragment(fragment);
                    return true;
            }
 
            return false;
        }
    };
 
    private void loadFragment(Fragment fragment) {
        // load fragment
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.frame_container, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }
 
}

Now if you run the project you can see the fragments loaded when navigation is selected.

4. Implementing ShopFragment – Displaying Items in Grid

Now we’ll see how to implement the first fragment i.e ShopFragment which displays the shop items in a Grid fashion. For demonstration, I have created a sample json which contains few movies for sale. To implement this, all we have to do is, fetch json and display the data in RecyclerView in a grid format. To make the task simpler, follow my other article which explains the same.

10. Open build.gradle and add RecyclerViewCardViewVolley and Glide dependencies.

build.gradle
dependencies {
    // RecyclerView
    compile 'com.android.support:recyclerview-v7:26.1.0'
 
    // CardView
    compile 'com.android.support:cardview-v7:26.1.0'
 
    // volley http library
    implementation 'com.android.volley:volley:1.0.0'
    implementation 'com.google.code.gson:gson:2.6.2'
 
    // glide image library
    implementation 'com.github.bumptech.glide:glide:4.3.1'
}

11. Create a class named MyApplication.java implement the class from Application. This is a singleton class in which volley library will be initiated.

MyApplication.java
package info.androidhive.bottomnavigation.app;
 
import android.app.Application;
import android.text.TextUtils;
 
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
 
public class MyApplication extends Application {
 
    public static final String TAG = MyApplication.class
            .getSimpleName();
 
    private RequestQueue mRequestQueue;
 
    private static MyApplication mInstance;
 
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }
 
    public static synchronized MyApplication getInstance() {
        return mInstance;
    }
 
    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }
 
        return mRequestQueue;
    }
 
    public <T> void addToRequestQueue(Request<T> req, String tag) {
        // set the default tag if tag is empty
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }
 
    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }
 
    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

12. Open AndroidManifest.xml and add MyApplication to <application> tag. We also need INTERNET permission as we gonna make http calls.

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.bottomnavigation">
 
    <uses-permission android:name="android.permission.INTERNET"/>
 
    <application
        android:name=".app.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

13. Open the layout file of StoreFragment i.e fragment_store.xml and add below layout code. Here we are adding the RecyclerView component.

fragment_store.xml
<android.support.v4.widget.NestedScrollView 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:background="#f1f5f7"
    tools:context="info.androidhive.bottomnavigation.fragment.StoreFragment">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
 
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingTop="10dp"
            android:text="New Release Films"
            android:textColor="#111"
            android:textSize="16dp" />
 
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clipToPadding="false"
            android:scrollbars="vertical" />
    </LinearLayout>
</android.support.v4.widget.NestedScrollView>

14. Create an xml layout named store_item_row.xml under res ⇒ layout. This layout file will be used in RecyclerView adapter class to render single item.

store_item_row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
 
    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="@dimen/card_margin"
        android:clickable="true"
        android:elevation="3dp"
        android:foreground="?attr/selectableItemBackground"
        card_view:cardCornerRadius="@dimen/card_album_radius">
 
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
 
            <ImageView
                android:id="@+id/thumbnail"
                android:layout_width="match_parent"
                android:layout_height="@dimen/album_cover_height"
                android:background="?attr/selectableItemBackgroundBorderless"
                android:clickable="true"
                android:scaleType="fitXY" />
 
            <TextView
                android:id="@+id/title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/thumbnail"
                android:lines="2"
                android:paddingLeft="@dimen/album_title_padding"
                android:paddingRight="@dimen/album_title_padding"
                android:paddingTop="@dimen/album_title_padding"
                android:textColor="#111"
                android:textSize="11dp" />
 
            <TextView
                android:id="@+id/price"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/title"
                android:layout_marginRight="10dp"
                android:gravity="right"
                android:paddingBottom="@dimen/songs_count_padding_bottom"
                android:textColor="@color/colorAccent"
                android:textSize="11dp" />
 
        </RelativeLayout>
 
    </android.support.v7.widget.CardView>
</LinearLayout>

15. Create a class named Movie.java. This POJO class will be useful while parsing the json.

Movie.java
package info.androidhive.bottomnavigation;
 
public class Movie {
    String title;
    String image;
    String price;
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getImage() {
        return image;
    }
 
    public void setImage(String image) {
        this.image = image;
    }
 
    public String getPrice() {
        return price;
    }
 
    public void setPrice(String price) {
        this.price = price;
    }
}

16. Now open StoreFragment.java and add below code. For simplicity the RecyclerView adapter class StoreAdapter included in the same fragment.

> fetchStoreItems() Method fetches the movies json using Volley and serializes it using Gson.

> StoreAdapter class renders the movies in RecyclerView.

StoreFragment.java
package info.androidhive.bottomnavigation.fragment;
 
 
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
 
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.bumptech.glide.Glide;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
 
import org.json.JSONArray;
 
import java.util.ArrayList;
import java.util.List;
 
import info.androidhive.bottomnavigation.Movie;
import info.androidhive.bottomnavigation.app.MyApplication;
import info.androidhive.bottomnavigation.R;
 
public class StoreFragment extends Fragment {
 
    private static final String TAG = StoreFragment.class.getSimpleName();
    private static final String URL = "https://api.androidhive.info/json/movies_2017.json";
 
    private RecyclerView recyclerView;
    private List<Movie> movieList;
    private StoreAdapter mAdapter;
 
    public StoreFragment() {
        // Required empty public constructor
    }
 
    public static StoreFragment newInstance(String param1, String param2) {
        StoreFragment fragment = new StoreFragment();
        Bundle args = new Bundle();
        fragment.setArguments(args);
        return fragment;
    }
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_store, container, false);
 
        recyclerView = view.findViewById(R.id.recycler_view);
        movieList = new ArrayList<>();
        mAdapter = new StoreAdapter(getActivity(), movieList);
 
        RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getActivity(), 3);
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(8), true));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(mAdapter);
        recyclerView.setNestedScrollingEnabled(false);
 
        fetchStoreItems();
 
        return view;
    }
 
    private void fetchStoreItems() {
        JsonArrayRequest request = new JsonArrayRequest(URL,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        if (response == null) {
                            Toast.makeText(getActivity(), "Couldn't fetch the store items! Pleas try again.", Toast.LENGTH_LONG).show();
                            return;
                        }
 
                        List<Movie> items = new Gson().fromJson(response.toString(), new TypeToken<List<Movie>>() {
                        }.getType());
 
                        movieList.clear();
                        movieList.addAll(items);
 
                        // refreshing recycler view
                        mAdapter.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // error in getting json
                Log.e(TAG, "Error: " + error.getMessage());
                Toast.makeText(getActivity(), "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
 
        MyApplication.getInstance().addToRequestQueue(request);
    }
 
    public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
 
        private int spanCount;
        private int spacing;
        private boolean includeEdge;
 
        public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
            this.spanCount = spanCount;
            this.spacing = spacing;
            this.includeEdge = includeEdge;
        }
 
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view); // item position
            int column = position % spanCount; // item column
 
            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
 
                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        }
    }
 
    /**
     * Converting dp to pixel
     */
    private int dpToPx(int dp) {
        Resources r = getResources();
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
    }
 
    class StoreAdapter extends RecyclerView.Adapter<StoreAdapter.MyViewHolder> {
        private Context context;
        private List<Movie> movieList;
 
        public class MyViewHolder extends RecyclerView.ViewHolder {
            public TextView name, price;
            public ImageView thumbnail;
 
            public MyViewHolder(View view) {
                super(view);
                name = view.findViewById(R.id.title);
                price = view.findViewById(R.id.price);
                thumbnail = view.findViewById(R.id.thumbnail);
            }
        }
 
 
        public StoreAdapter(Context context, List<Movie> movieList) {
            this.context = context;
            this.movieList = movieList;
        }
 
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.store_item_row, parent, false);
 
            return new MyViewHolder(itemView);
        }
 
        @Override
        public void onBindViewHolder(MyViewHolder holder, final int position) {
            final Movie movie = movieList.get(position);
            holder.name.setText(movie.getTitle());
            holder.price.setText(movie.getPrice());
 
            Glide.with(context)
                    .load(movie.getImage())
                    .into(holder.thumbnail);
        }
 
        @Override
        public int getItemCount() {
            return movieList.size();
        }
    }
}

Now if you run the app, you can see the ShopFragment displaying the movies in grid manner. Likewise you can implement other fragments too.

5. Hiding Bottom Navigation on Scroll

As per design specs, the Bottom Navigation has to be hidden when the content is scrolled giving more room to content on the screen. To achieve this, we need to attach the BottomNavigationBehavior to Bottom Navigation.

17. Create a class named BottomNavigationBehavior.java with the below code.

BottomNavigationBehavior.java
package info.androidhive.bottomnavigation.helper;
 
import android.content.Context;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
 
public class BottomNavigationBehavior extends CoordinatorLayout.Behavior<BottomNavigationView> {
 
    public BottomNavigationBehavior() {
        super();
    }
 
    public BottomNavigationBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, BottomNavigationView child, View dependency) {
        boolean dependsOn = dependency instanceof FrameLayout;
        return dependsOn;
    }
 
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }
 
    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View target, int dx, int dy, int[] consumed) {
        if (dy < 0) {
            showBottomNavigationView(child);
        } else if (dy > 0) {
            hideBottomNavigationView(child);
        }
    }
 
    private void hideBottomNavigationView(BottomNavigationView view) {
        view.animate().translationY(view.getHeight());
    }
 
    private void showBottomNavigationView(BottomNavigationView view) {
        view.animate().translationY(0);
    }
}

18. Add the BottomNavigationBehavior using setBehavior() in MainActivity.java as shown below.

MainActivity.java
public class MainActivity extends AppCompatActivity {
 
    private ActionBar toolbar;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
 
        // attaching bottom sheet behaviour - hide / show on scroll
        CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) navigation.getLayoutParams();
        layoutParams.setBehavior(new BottomNavigationBehavior());
 
        // load the store fragment by default
        // ..
    }
}

Now if you test the app, you can see the Bottom Navigation sliding down when the app content is scrolled.

Vishal Swami is a hardcore Android programmer and Android programming has been his passion since he compiled his first hello-world program. Solving real problems of Android developers through tutorials has always been an interesting part for him.

36 Comments

  1. 5 stars
    עיסוי ארוטי בבאר שבע כולל ותומן בתוכו
    יתרונות רבים. עיסוי אירוטי בחדרה (כמו עיסוי אירוטי בעפולה, בצפת,
    בטבריה, בפתח תקווה, באשקלון,
    בירושלים או בכל מקום אחר בארץ) הוא דרך מצוינת להפוך את החלום למציאות כיפית.
    חשוב לציין כי אנחנו משתדלים לתת לכם הגולשים שלנו את
    השירות הטוב ביותר, מבחינתינו קודם כל אתם הלקוחות שלנו ורק אחר כך המפרסמים באתר.
    אז למה אתה מחכה כנס עכשיו ולא
    תתאכזב בבי סקסי מגוון נערות
    מדהימות ומפנקות כמו שלא תמצא בשום מקום אחר.
    למה מסאז’ רפואי עדיף על פני
    שיטות טיפול אחרות? על איזו נערת ליווי חלמת?
    פינת התרגעות לצלילי מוסיקה רומנטית לאור נרות ותאורה עמומה, מצעים נקיים, חדר רחצה
    מאובזר, ובחורות חטובות וסקסיות מכל צבעי הקשת,
    שיודעות את עבודתן ומעניקות שירותי ליווי לעיסוי חלומי
    בדירות הדיסקרטיות בנתניה.
    כאן תוכל למצוא מגוון רחב של דירות סקס בנתניה והסביבה כולל כתובות, טלפונים וניווט שיביא אתכם היישר לעונג.
    רוצים פרטים על דירות דיסקרטיות בשרון?
    כל הדירות הדיסקרטיות בנתניה שנבחרו בקפידה רבה על ידי פורטל אקספיינדר, נבחרו בקפידה רבה על
    מנת להנעים לשוהה בהן את השהות במקום ולהנות מחוויה
    רומנטית ומענגת. נתניה המקבצת בתוכה מגוון בחורות
    נאות וחטובות מאפשרת לכם יותר מתמיד לצאת לבילוי משותף ומענג
    בדירות דיסקרטיות בנתניה. ראשית, אינכם צריכים לצאת
    מהבית, כך שאתם חוסכים המון
    זמן בכל הקשור להגעה לקליניקת
    העיסויים בקרית שמונה/נהריה .

  2. 4 stars
    אתרי אינטרנט מציעים נערות ליווי מפתות מכל הסוגים:
    ישראליות, ערביות, אפריקאיות, רוסיות, רזות, מלאות ועוד.
    לכן, אם אתם אוהבים נערות ליווי רזות, כהות, מבוגרות, בהירות, צעירות וכדומה, הרי שחיפוש מהיר יעלה מאות תוצאות של נערות ליווי חושניות הממתינות
    לקריאתכם. נערות ליווי תמונות אמיתיות כך אומרים
    תוצאות המחקרים שהשוו אנשים פעילים מינית לאלה שאינם פעילים מינית.
    ישנן סיבות רבות לקיים יחסי מין בתדירות גבוהה יותר, לפחות כשמדובר במין איכותי בזוגיות תומכת.נערות ליווי תמונות אמיתיות פעילות מינית תכופה יותר קשורה לתועלות גופניות, כגון לחץ
    דם נמוך יותר, הטבות רגשיות, כמו לחץ מופחת ויתרונות בזוגיות, כמו אינטימיות רבה יותר ושיעור גירושין נמוך
    יותר .נערות ליווי תמונות אמיתיות אמנם אין מספר קסמים כשזה מגיע על פי התדירות האידיאלית של יחסי מין, תוצאות של כמה מחקרים יכולים להצביע על גן שעשועים.
    נערות ליווי תמונות אמיתיות כמה מחקרים מראים כי קצב פעימות הלב הממוצע באורגזמה
    זהה לזה בזמן פעילות קלה, למשל הליכה למעלה.
    למרות הפרסומים הרבים בהם נראות בנות המפרסמות
    את מספר הטלפון שלהן ברצוננו להדגיש כי הבנות מחפשות קשר לא מחייב אך עם גברים איכותיים.
    יש מצבים בהם אחד מבני הזוג
    מנהל מערכת יחסים נוספת מעבר למערכת היחסים הרגילה שלו.

  3. 4 stars
    So, choose an escort service and explore the Ankleshwar metropolis!

    Escort service has emerged out as one of the leading technique of happiness, enjoyable and romance
    for everybody willing to beat the loneliness.
    Upon completion you’ll receive a bonus which suggests you’re
    taking much less damage from car collisions.
    Now it’s time to take back just what concerns you, your gang and Stilwater!

    You can then drive a brief distance away after which return and it will likely be there again. The best way is to search out an area
    with destructible fencing, you then need a automotive and keep
    driving by means of it, a zig-zag will sustain enough pace to undergo extra at a time.
    All that you must do is keep getting in your ambulance
    and hitting things at high sufficient pace to be ejected out of the automobile and this activity is a breeze.
    If you need to keep the additional weight low it is best to take a
    look at carbon fiber body kits which are sturdy but very
    mild. The complement boosts the quantity of creatin inside the body and is elevated by bodybuilding
    exercise. Gabriela has been constantly coaching since she was a young lady and now her training has given her an ideal body, very lengthy legs, and
    good muscles, she is a hymn to sport and physique care.

    my webpage: דרושות נערות ליווי

  4. 1 star
    בין הדרכים היעילות ביותר להעלות את מצב הרוח ואת החשק המיני שלך – עיסוי ארוטי.
    רק חשוב לא להשאר שם פרק זמן ארוך מ 20 דקות,
    כדי לא להעלות את הדופק מדי.
    ראשית, אינכם צריכים לצאת מהבית,
    כך שאתם חוסכים המון זמן בכל הקשור להגעה לקליניקת העיסויים.

    התחושות שאתם חשים עוזרות לכם לחדד את תחושת הרכות והחיבור לחלקים הרכים שלכם ולהתחברות אל רגשותיכם.
    חוויה זו יכולה להיות לא רגילה ומהנה במיוחד, מכיוון שאתם מקבלים יחס
    הרבה יותר מפנק! ניתן להקל על נשים אלו דרך עיסוי רפואי, במיוחד, כאשר הנשים ממשיכות
    עדיין לעסוק במטלות השונות המאפיינות את אורח חייהן.
    מהסיבה הזאת, כל מי שמעוניין בעיסוי רפואי, חשוב שיקפיד לבחור בצורה מושכלת ונבונה את המעסה, תוך דגש על כל אותם הפרמטרים אשר יבטיחו עיסוי מקצועי ואיכותי, אשר
    יסייע לו להתמודד עם הבעיה הרפואית הפרטנית עמה הוא מתמודד.
    התענגו על התחושה הנינוחה והרגועה של כל
    השרירים בגופכם, קומו ממיטת הטיפולים
    לאט ובזהירות, ודאגו להתמתח בעדינות.
    הוא מזהה את אימו על פי הריח בחזה .
    מובן כי כל פי אורח חיים זה מגע נשי אינו בא בחשבון, כך שעל מנת ליהנות מהעיסוי מבקשים
    הגברים לקבל עיסוי מגבר.

    My web blog: http://calhoy.net/

  5. 2 stars
    A shingle that is simply too plush will be uncomfortable for the receiver to use.

    These simple tips will aid you in staying fit despite having little or
    no time to spare for train and can protect your well being from the in poor health-effects of an office job.
    A therapeutic massage chair is an funding in your longer term well being and effectively-being.
    A preferred route is the huge constellation of
    well being resorts, which embody a spread of companies to the person as various
    and ever. You may expect to get a complete vary of therapies in addition to effective therapeutic massage therapy.
    You could also be surprised to know that there are many alternative sorts of those
    units and the most important consideration is what kind of stress
    point therapy you need. These are good as a result of they are very
    simple to clean up afterwards. It should also be simple to wash and dry out after every
    session.

    Also visit my web page; דרושות נערות ליווי

  6. 5 stars
    ראשית, דעו כי עיסוי ברחובות עולה הרבה פחות ממה שאתם מדמיינים.
    עולה מולנו מקומי ושם לב שהנחש קשור בחוט למקל, המקומיים תפסו אותו וקשרו חבל
    שימות לאט לאט זרקו אותו
    ליד השביל שהנחשים יראו אותו וידעו לא להתקרב לשביל, או שילדי הג’ונגל השתעשעו איתו ואפילו התכוונו לאכול אותו בהמשך, שחררנו את הנחש,
    יותר מאוחר הבנו שזה צפע ירוק ארסי
    מאוד, שיכול להרוג בקלות בן אדם.
    יום שני בנוגריאט יש לתמרה יום הולדת 8
    וגשם לא מפסיק לרדת, תמרה מתעוררת כשכל
    הקילה שלה מלאה בבלונים ורודים עד
    אפס מקום וקשורה בסרטים אדומים, אוכלים ארוחת בוקר וצופים בסרטונים וברכות ליום הולדת, מקריאים ברכות תמרה מתרגשת נורא, מחפשים את המטמון סביב הגסט האוס
    כולל מתנות, הכל במרחק של
    מטרים ובתנאי שטח קשים של רטיבות וגשם
    מבול של ממש, תמרה מקבלת שמלה שכל כך ביקשה עם נוצצים פאייטים,
    מתנפחת עם טול, אני ואלונה כיתתנו רגלינו בכל שילונג למצוא אחת
    כזו, קשת מגונדרת עם נוצות ופרחים, צמיד, שרשרת ועגילים, כדוריות
    צבעוניות מתנפחות במים, בקבוק סוכריות, משחק אונו, בלוני סבון ומניפה.
    קמים בבוקר כרגיל מבול, אוכלים
    ארוחת בוקר ומתארגנים, הילדים משתוללים עם החבורה של ביירון, הולכים
    למינגטנג, כפר של 26 משפחות, עם גשרי חבלים ונהר ענק, יוצאים לדרך השמיים
    בהירים, כל הרכס למעלה מכוסה מפלים,
    חוצים את הכפר חולפים צמוד לכנסיה, עד לכאן ישו הגיע לא יאומן.

    Stop by my page; דרושות נערות ליווי

  7. I truly enjoy reading on this site, it holds fantastic articles. “Don’t put too fine a point to your wit for fear it should get blunted.” by Miguel de Cervantes.

Reply To שירותי ליווי אילת Cancel Reply