Skip to content

Instantly share code, notes, and snippets.

@iamnaran
Last active May 23, 2021 15:29
Show Gist options
  • Save iamnaran/89216b521659f57ae0b627825d3d3923 to your computer and use it in GitHub Desktop.
Save iamnaran/89216b521659f57ae0b627825d3d3923 to your computer and use it in GitHub Desktop.
Bottom Sheet above Bottom Navigation
Contains custom navigation bottom and bottom sheet view with recyclerview.
#################
Here's the article you may need
https://iamnaran.medium.com/bottom-sheet-above-bottom-navigation-b10a0c92edd
#################
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom_navigation_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorPrimary" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/bottom_sheet_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_bottom_sheet"
app:layout_anchorGravity="bottom"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<LinearLayout
android:id="@+id/bottom_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/bottom_sheet_top_layout"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="?attr/colorContainer"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/text_parent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1.2"
android:gravity="center"
android:orientation="vertical">
<TextView
style="@style/LargeTextPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingTop="5dp"
android:paddingBottom="2dp"
android:text="Game Booking"
android:textColor="?attr/colorPrimaryText" />
<TextView
style="@style/ExtraSmallTextPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingBottom="5dp"
android:text="Futsal or Cricket ?"
android:textColor="?attr/colorSecondaryText" />
</LinearLayout>
<LinearLayout
android:id="@+id/book_now_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<Button
style="@style/LargeButtonPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:gravity="center"
android:text="Book Now"
/>
</LinearLayout>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorContainer"
android:layoutAnimation="@anim/layout_animation">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout
android:id="@+id/bottom_navigation_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@android:color/transparent"
android:fitsSystemWindows="true"
app:elevation="1dp">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorContainer"
/>
<LinearLayout
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:layout_alignParentBottom="true"
android:background="?attr/colorNavigationBottomBackground"
android:baselineAligned="false"
android:orientation="horizontal">
<RelativeLayout
android:id="@+id/home_parent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingTop="@dimen/item_padding"
android:paddingBottom="@dimen/item_padding_bottom">
<ImageView
android:id="@+id/home"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_centerHorizontal="true"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_home_24_dp"
android:tint="?attr/colorAccent"
/>
<TextView
style="@style/NormalTextPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/home"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="@string/home"
android:textColor="?attr/colorAccent"
android:textSize="@dimen/small_text_size"
tools:ignore="SmallSp"
/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/discount_offer_parent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingTop="@dimen/item_padding"
android:paddingBottom="@dimen/item_padding_bottom">
<ImageView
android:id="@+id/discount"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_centerHorizontal="true"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_discount_offers"
android:tint="@color/colorDefault"
/>
<TextView
style="@style/NormalTextPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/discount"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="@string/offers"
android:textColor="@color/colorDefault"
android:textSize="@dimen/extra_small_text_size"
tools:ignore="SmallSp"
/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/profile_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingTop="@dimen/item_padding"
android:paddingBottom="@dimen/item_padding_bottom">
<ImageView
android:id="@+id/profile"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_centerHorizontal="true"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_profile"
android:tint="@color/colorDefault" />
<TextView
style="@style/NormalTextPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/profile"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="@string/profile"
android:textColor="@color/colorDefault"
android:textSize="@dimen/extra_small_text_size"
tools:ignore="SmallSp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/notification_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingTop="@dimen/item_padding"
android:paddingBottom="@dimen/item_padding_bottom">
<ImageView
android:id="@+id/notification_icon"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_centerHorizontal="true"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_notification_24_dp"
android:tint="@color/colorDefault"
/>
<TextView
style="@style/NormalTextPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/notification_icon"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="@string/notification"
android:textColor="@color/colorDefault"
android:textSize="@dimen/extra_small_text_size"
tools:ignore="SmallSp" />
</RelativeLayout>
</LinearLayout>
</android.support.design.widget.AppBarLayout>
</RelativeLayout>
package com.fireball.mygame.activities;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.os.Bundle;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.fireball.mygame.R;
import com.fireball.mygame.fragments.HomeFragment;
import com.fireball.mygame.fragments.NotificationFragment;
import com.fireball.mygame.fragments.OffersFragment;
import com.fireball.mygame.fragments.ProfileFragment;
import com.fireball.mygame.helper.AppActivity;
import com.fireball.mygame.helper.AppRecyclerViewAdapter;
import com.fireball.mygame.helper.EqualSpacingItemDecoration;
import com.fireball.mygame.helper.MyApplication;
public class MainActivity extends AppActivity implements View.OnClickListener {
private RelativeLayout homeParent, offerParent, profileParent, notificationParent;
private RelativeLayout lastSelectedView;
private LinearLayout bottomNavigation;
private android.support.v7.widget.Toolbar toolbar;
private RelativeLayout bottomSheetParentLayout;
private LinearLayout bottomSheetTopLayout;
private LinearLayout bottomView;
private BottomSheetBehavior mBottomSheetBehaviour;
private RecyclerView recyclerViewBottom;
private BottomRecyclerViewAdapter bottomRecyclerViewAdapter;
private boolean isNightModeOn = false;
//testing
private LinearLayout bookNowButtonParent;
private LinearLayout bookNowTextParent;
private int bookNowButtonParentWidth = 0;
private int bookNowTextParentWidth = 0;
private int stateOfBottomSheet = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
setTheme(R.style.AppThemeDark);
isNightModeOn = true;
} else {
setTheme(R.style.AppTheme);
isNightModeOn = false;
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialiseViews();
initialiseListeners();
prepareBottomRecyclerView();
if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
isNightModeOn = true;
} else {
isNightModeOn = false;
}
setUpFragment(new HomeFragment(), "home");
}
@Override
protected void initialiseViews() {
bottomNavigation = findViewById(R.id.bottom_navigation);
homeParent = findViewById(R.id.home_parent);
profileParent = findViewById(R.id.profile_parent);
offerParent = findViewById(R.id.discount_offer_parent);
notificationParent = findViewById(R.id.notification_parent);
bottomSheetParentLayout = findViewById(R.id.bottom_sheet_parent);
bottomSheetTopLayout = findViewById(R.id.bottom_sheet_top_layout);
bottomView = findViewById(R.id.bottom_view);
bookNowButtonParent = findViewById(R.id.book_now_parent);
bookNowTextParent = findViewById(R.id.text_parent);
lastSelectedView = homeParent;
recyclerViewBottom = findViewById(R.id.recycler_view_bottom);
mBottomSheetBehaviour = BottomSheetBehavior.from(bottomSheetParentLayout);
if (bottomNavigation != null) {
TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {
int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
mBottomSheetBehaviour.setPeekHeight(actionBarHeight);
}
}
bookNowButtonParentWidth = bookNowButtonParent.getWidth();
bookNowTextParentWidth = bookNowTextParent.getWidth();
}
@Override
protected void initialiseListeners() {
homeParent.setOnClickListener(this);
offerParent.setOnClickListener(this);
profileParent.setOnClickListener(this);
notificationParent.setOnClickListener(this);
bottomView.setOnClickListener(this);
}
private void prepareBottomRecyclerView() {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this);
recyclerViewBottom.setLayoutManager(linearLayoutManager);
bottomRecyclerViewAdapter = new BottomRecyclerViewAdapter();
recyclerViewBottom.setAdapter(bottomRecyclerViewAdapter);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.home_parent:
if (!getVisibleFragment("home")) {
setUpBottomNavigation(homeParent);
setUpFragment(new HomeFragment(), "home");
}
break;
case R.id.discount_offer_parent:
if (!getVisibleFragment("offers")) {
setUpBottomNavigation(offerParent);
setUpFragment(new OffersFragment(), "offers");
}
break;
case R.id.profile_parent:
if (!getVisibleFragment("profile")) {
setUpBottomNavigation(profileParent);
setUpFragment(new ProfileFragment(), "profile");
}
break;
case R.id.notification_parent:
if (!getVisibleFragment("notification")) {
setUpBottomNavigation(notificationParent);
setUpFragment(new NotificationFragment(), "notification");
}
break;
case R.id.bottom_view:
if (isNightModeOn) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
restartApp();
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
restartApp();
}
break;
}
}
public void onBottomSheetDragListener() {
mBottomSheetBehaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
// Called every time when the bottom sheet changes its state.
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
break;
case BottomSheetBehavior.STATE_EXPANDED:
stateOfBottomSheet = 1;
break;
case BottomSheetBehavior.STATE_COLLAPSED:
stateOfBottomSheet = 0;
break;
case BottomSheetBehavior.STATE_DRAGGING:
break;
case BottomSheetBehavior.STATE_SETTLING:
break;
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
// Called when the bottom sheet is being dragged
}
});
}
public void setDefaultLayoutParams() {
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT,
1.0f
);
LinearLayout.LayoutParams param1 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT,
1.5f
);
bookNowButtonParent.setLayoutParams(param);
bookNowTextParent.setLayoutParams(param1);
}
private void scaleViewWithDragValue(float slideOffset) {
if (stateOfBottomSheet == 0) {
bookNowButtonParent.setLayoutParams(new LinearLayout.LayoutParams(bookNowButtonParent.getWidth() + (int) (2 * slideOffset), bookNowButtonParent.getHeight()));
bookNowTextParent.setLayoutParams(new LinearLayout.LayoutParams(bookNowTextParent.getWidth() - (int) (2 * slideOffset), bookNowButtonParent.getHeight()));
} else {
bookNowButtonParent.setLayoutParams(new LinearLayout.LayoutParams(bookNowButtonParent.getWidth() - (int) (2 * slideOffset), bookNowButtonParent.getHeight()));
bookNowTextParent.setLayoutParams(new LinearLayout.LayoutParams(bookNowTextParent.getWidth() + (int) (2 * slideOffset), bookNowButtonParent.getHeight()));
}
}
public int containerWidth(Activity activity) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
double ratio = 1.5;
return (int) (dm.widthPixels / ratio);
}
private void restartApp() {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
finish();
}
public boolean getVisibleFragment(String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.Fragment currentFragment = fragmentManager.findFragmentById(R.id.container);
assert currentFragment.getTag() != null;
if (currentFragment.getTag().equals(tag)) {
return true;
}
return false;
}
/**
* @param fragment fragment to load
*/
private void setUpFragment(android.support.v4.app.Fragment fragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
fragmentTransaction.replace(R.id.container, fragment, tag);
fragmentTransaction.commit();
}
public void setUpBottomNavigation(RelativeLayout view) {
if (lastSelectedView != null) {
for (int i = 0; i < lastSelectedView.getChildCount(); i++) {
View view1 = lastSelectedView.getChildAt(i);
if (view1 instanceof ImageView) {
((ImageView) view1).setColorFilter(getResources().getColor(R.color.colorDefault));
} else {
((TextView) view1).setTextColor(getResources().getColor(R.color.colorDefault));
// ((TextView) view1).setTextSize(11);
setTextChangeAnimation((TextView) view1, 12, 11);
}
}
}
for (int i = 0; i < view.getChildCount(); i++) {
View view1 = view.getChildAt(i);
if (view1 instanceof ImageView) {
((ImageView) view1).setColorFilter(ContextCompat.getColor(this, R.color.colorAccent));
} else {
((TextView) view1).setTextColor(ContextCompat.getColor(this, R.color.colorAccent));
setTextChangeAnimation((TextView) view1, 11, 12);
}
}
lastSelectedView = view;
}
public void setTextChangeAnimation(final TextView textChangeAnimation, int startValue, int endValue) {
long animationDuration = 300; // Animation duration in ms
ValueAnimator animator = ValueAnimator.ofFloat(startValue, endValue);
animator.setDuration(animationDuration);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float animatedValue = (float) valueAnimator.getAnimatedValue();
textChangeAnimation.setTextSize(animatedValue);
}
});
animator.start();
}
@Override
public void onBackPressed() {
HomeFragment homeFragment = (HomeFragment) getSupportFragmentManager().findFragmentByTag("home");
if (homeFragment != null && homeFragment.isVisible()) {
setUpBottomNavigation(homeParent);
}
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
private class BottomRecyclerViewAdapter extends AppRecyclerViewAdapter {
private static final int TYPE_SEARCH = 0;
private static final int TYPE_STICKY = 1;
private static final int TYPE_FAVOURITE = 2;
@Override
public void add(Object object) {
}
@Override
public void clear() {
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_SEARCH) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bottom_search, parent, false);
return new VHSearch(view);
} else if (viewType == TYPE_STICKY) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bottom_sticky, parent, false);
return new VHSticky(view);
} else if (viewType == TYPE_FAVOURITE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bottom_favourite, parent, false);
return new VHFavourite(view);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof VHFavourite){
VHFavourite vhFavourite = (VHFavourite) holder;
Glide.with(MainActivity.this).load(R.drawable.test2).into(vhFavourite.imageView);
}else {
}
}
@Override
public int getItemViewType(int position) {
if (isPositionSearch(position)) {
return TYPE_SEARCH;
} else if (isPositionTitleSticky(position)) {
return TYPE_STICKY;
}
return TYPE_FAVOURITE;
}
private boolean isPositionSearch(int position) {
return position == 0;
}
private boolean isPositionTitleSticky(int position) {
return position == 1;
}
@Override
public int getItemCount() {
return 10;
}
private class VHSearch extends RecyclerView.ViewHolder {
public VHSearch(View view) {
super(view);
}
}
private class VHFavourite extends RecyclerView.ViewHolder {
private ImageView imageView;
public VHFavourite(View view) {
super(view);
imageView = view.findViewById(R.id.home_footer_image);
}
}
private class VHSticky extends RecyclerView.ViewHolder {
public VHSticky(View view) {
super(view);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment