I'm trying to create a layout that integrates both a collapsing toolbar with a tab bar underneath it that remains visible after the user scrolls up. My problem is that the tab bar sticks to the top of the screen under the MainActivity toolbar. I'm using a sliding window activity with fragments, and this fragment has nested fragments for each tab that will have each its own layout. I'm following the examples from here that use the support design library to achieve this.
My layout code for the main fragment is as follows:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed">
<ImageView
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/details_header"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:id="@+id/anim_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/tabanim_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="@mipmap/ic_action_share"
app:backgroundTint="@color/primary_dark"
app:layout_anchor="@+id/appbar"
app:layout_anchorGravity="bottom|right|end"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="@mipmap/ic_action_location"
app:backgroundTint="@color/primary_dark"
app:layout_anchor="@+id/appbar"
app:layout_anchorGravity="bottom|center"/>
<android.support.design.widget.AppBarLayout
android:id="@+id/tabanim_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="false"
android:baselineAligned="false"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="@+id/tabanim_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</TabHost>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
For this instance to simplify the tab fragment layout, let's assume I just have a recycleview in it:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/dummyfrag_bg"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_material_light">
<android.support.v7.widget.RecyclerView
android:id="@+id/dummyfrag_scrollableview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
The MainActivity layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
android:id="@+id/DrawerLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="7dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar"/>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/RecyclerView"
android:layout_width="320dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="@color/white_transparent"
android:scrollbars="vertical"/>
</android.support.v4.widget.DrawerLayout>
The toolbar layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
MainActivity class:
public class MainActivity extends AppCompatActivity {
private final static int PROFILE_FRAGMENT = 1;
private final static int PRIZES_FRAGMENT = 2;
private final static int SALES_FRAGMENT = 3;
private final static int ABOUT = 4;
private int currentFragment = 1;
private String currentFragmentName = "ProfileFragment";
public int HEADER_IMAGE = R.drawable.avatar;
private DrawerLayout drawer;
private List<DrawerItem> dataList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
}
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.RecyclerView);
mRecyclerView.setHasFixedSize(true);
dataList = new ArrayList<>();
addItemsToDataList();
NavDrawerAdapter mAdapter = new NavDrawerAdapter(dataList, this, "Person name", "Person email", HEADER_IMAGE);
mRecyclerView.setAdapter(mAdapter);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
drawer = (DrawerLayout) findViewById(R.id.DrawerLayout);
drawer.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(
this, drawer, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
};
drawer.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
onTouchDrawer(currentFragment);
final GestureDetector mGestureDetector =
new GestureDetector(MainActivity.this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
View child = recyclerView.findChildViewUnder(motionEvent.getX(), motionEvent.getY());
if (child != null && mGestureDetector.onTouchEvent(motionEvent)) {
drawer.closeDrawers();
onTouchDrawer(recyclerView.getChildLayoutPosition(child));
return true;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
}
private void addItemsToDataList() {
dataList.add(new DrawerItem(getString(R.string.title_profile), R.mipmap.ic_action_profile));
dataList.add(new DrawerItem(getString(R.string.title_prizes), R.mipmap.ic_action_prizes));
dataList.add(new DrawerItem(getString(R.string.title_sales), R.mipmap.ic_action_sales));
dataList.add(new DrawerItem(getString(R.string.title_about),R.mipmap.ic_action_about));
}
public void openFragment(final Fragment fragment) {
int backStackEntryCount = getSupportFragmentManager()
.getBackStackEntryCount();
if (!fragment.toString().equalsIgnoreCase(currentFragmentName)) {
switchContent(fragment);
}
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
private void onTouchDrawer(final int position) {
currentFragment = position;
switch (position) {
case PROFILE_FRAGMENT:
openFragment(new ProfileFragment());
setTitle(getString(R.string.title_profile));
break;
case PRIZES_FRAGMENT:
openFragment(new PrizesFragment());
setTitle(getString(R.string.title_prizes));
break;
case SALES_FRAGMENT:
openFragment(new SalesFragment());
setTitle(getString(R.string.title_sales));
break;
case ABOUT:
openFragment(new AboutFragment());
setTitle(getString(R.string.title_about));
break;
default:
}
}
public void switchContent(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
}
}
The fragment class:
public class SaleFragment extends TemplateFragment {
CollapsingToolbarLayout collapsingToolbar;
ViewPager viewPager;
TabLayout tabLayout;
ViewPagerTabAdaper adapter;
public SaleDetailFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View result = inflater.inflate(R.layout.fragment_sale_detail, container, false);
ViewPager pager = (ViewPager) result.findViewById(R.id.tabanim_viewpager);
setupViewPager(pager);
return (result);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final Toolbar toolbar = (Toolbar) view.findViewById(R.id.anim_toolbar);
getMainActivity().setSupportActionBar(toolbar);
getMainActivity().getSupportActionBar().setDisplayHomeAsUpEnabled(true);
collapsingToolbar = (CollapsingToolbarLayout) view.findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("Sale Detail");
ImageView header = (ImageView) view.findViewById(R.id.header);
Picasso.with(getActivity().getApplicationContext()).load(R.drawable.details_header).fit().into(header);
viewPager = (ViewPager) view.findViewById(R.id.tabanim_viewpager);
tabLayout = (TabLayout) view.findViewById(R.id.tabanim_tabs);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
List<String> listData = new ArrayList<>();
int ct = 0;
for (int i = 0; i < VersionModel.data.length * 2; i++) {
listData.add(VersionModel.data[ct]);
ct++;
if (ct == VersionModel.data.length) {
ct = 0;
}
}
setupViewPager(viewPager);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
switch (tab.getPosition()) {
case 0:
Toast.makeText(getActivity(), "Sales", Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(getActivity(), "Store Description", Toast.LENGTH_SHORT).show();
break;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void setupViewPager(ViewPager viewPager) {
adapter = new ViewPagerTabAdaper(getActivity().getSupportFragmentManager());
adapter.addFrag(new DummyFragment(getResources().getColor(R.color.accent_material_light)), "Sales");
adapter.addFrag(new DummyFragment(getResources().getColor(R.color.ripple_material_light)), "Store Description");
viewPager.setAdapter(adapter);
}
public static class DummyFragment extends android.support.v4.app.Fragment {
int color;
SimpleRecyclerAdapter adapter;
public DummyFragment() {
}
@SuppressLint("ValidFragment")
public DummyFragment(int color) {
this.color = color;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tabs_fragment, container, false);
final FrameLayout frameLayout = (FrameLayout) view.findViewById(R.id.dummyfrag_bg);
frameLayout.setBackgroundColor(color);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.dummyfrag_scrollableview);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity().getBaseContext());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
List<String> list = new ArrayList<>();
for (int i = 0; i < VersionModel.data.length; i++) {
list.add(VersionModel.data[i]);
}
adapter = new SimpleRecyclerAdapter(list);
recyclerView.setAdapter(adapter);
return view;
}
}
}
The view pager tab adaper:
public class ViewPagerTabAdaper extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerTabAdaper(FragmentManager manager) {
super(manager);
}
@Override
public android.support.v4.app.Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(android.support.v4.app.Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
My objective is to get a layout that looks like -- this--
So that the collapsing toolbar collapses when scrolled up and just the fragment title toolbar and the tabs are visible and then return back when scrolled down. I've already tried many solutions, but they either pin the tabs to the bottom or do not work will collapsing toolbars in general, which is not an option here.
Appreciate all suggestions and thanks.
I was able to solve this by following the example posted here. The main issues were that the app:layout_collapseMode="parallax" attribute made the image fill the entire space and cover the elements in it and as I found out AppBarLayout extends LinearLayout so it accepts the atribute android:layout_gravity="bottom" on the TabLayout and so forcing it to the bottom. I then added elements as I needed to get the final layout below:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="300dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?attr/actionBarSize"
android:background="@drawable/details_header"/>
<LinearLayout
android:id="@+id/smth"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="?attr/actionBarSize"
android:background="#f8f5ee"
android:orientation="vertical">
<TextView
android:id="@+id/text_store_page_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="35dp"
android:text="LEITARIA QUINTA DO PAÇO"
android:textColor="#000000"
android:textSize="20sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/textView14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="13dp"
android:layout_marginTop="3dp"
android:drawableLeft="@mipmap/ic_action_profile"
android:text="Pastelaria caseira"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#000000"/>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="right"
android:layout_marginTop="115dp"
android:elevation="0dp"
android:src="@mipmap/ic_action_share"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_location"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="right"
android:layout_marginEnd="68dp"
android:layout_marginTop="115dp"
android:elevation="0dp"
android:src="@mipmap/ic_action_location"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_share"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="right"
android:layout_marginEnd="130dp"
android:layout_marginTop="115dp"
android:elevation="0dp"
android:src="@mipmap/ic_action_share"/>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/prize_icon"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginStart="16dp"
android:layout_marginTop="115dp"
android:src="@drawable/eclair"/>
<android.support.v7.widget.Toolbar
android:id="@+id/anim_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/transparent"
app:layout_collapseMode="parallax"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
android:id="@+id/tabanim_tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
android:gravity="center"
app:tabGravity="center"
app:tabIndicatorColor="#F1514A"
app:tabMode="scrollable"
app:tabSelectedTextColor="@android:color/white"
app:tabTextColor="#99ffffff"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/tabanim_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
And thanks to @skynet for the very helpful references.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With