Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tab bar sticks to the top instead of underneath a collapsing toolbar

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.

like image 907
Luís Cunha Avatar asked Sep 27 '22 07:09

Luís Cunha


1 Answers

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.

like image 134
Luís Cunha Avatar answered Sep 30 '22 11:09

Luís Cunha