SlidingTabLayout With NavigationDrawer

2019-09-10 08:18发布

I am going to handle navigation drawer with sliding tabs using following Library called ObservableScrollView https://github.com/ksoichiro/Android-ObservableScrollView. The following are the xml and java files which I used to display.

My XML file:

<com.para.paraservice.observablescrollview.TouchInterceptionFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/pager_wrapper"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
<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.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            app:popupTheme="@style/Theme.AppCompat.Light.DarkActionBar"
            app:theme="@style/Toolbar" />
        <com.para.paraservice.widgets.SlidingTabLayout
            android:id="@+id/sliding_tabs"
            android:layout_width="match_parent"
            android:layout_height="@dimen/tab_height"
            android:background="@color/primary"
            android:layout_below="@+id/toolbar" />
        <android.support.v4.widget.DrawerLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/drawer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/toolbar" >

            <FrameLayout
                android:id="@+id/fr_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clickable="true" />

            <!-- android:layout_marginTop="?android:attr/actionBarSize" -->

            <fragment
                android:id="@+id/fragment_drawer"
                android:name="com.para.paraservice.widgets.NavigationDrawerFragment"
                android:layout_width="@dimen/flexible_space_image_height"
                android:layout_height="match_parent"
                android:layout_gravity="start"
                app:layout="@layout/fragment_navigation_drawer" />
        </android.support.v4.widget.DrawerLayout>
    </RelativeLayout>

</com.para.paraservice.observablescrollview.TouchInterceptionFrameLayout>

My Java code:

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.view.ViewHelper;
import com.para.paraservice.BaseActivity;
import com.para.paraservice.R;
import com.para.paraservice.ViewPagerTab2ScrollViewFragment;
import com.para.paraservice.observablescrollview.ObservableScrollViewCallbacks;
import com.para.paraservice.observablescrollview.CacheFragmentStatePagerAdapter;
import com.para.paraservice.observablescrollview.ScrollState;
import com.para.paraservice.observablescrollview.ScrollUtils;
import com.para.paraservice.observablescrollview.Scrollable;
import com.para.paraservice.observablescrollview.TouchInterceptionFrameLayout;
import com.para.paraservice.widgets.NavigationDrawerCallbacks;
import com.para.paraservice.widgets.NavigationDrawerFragment;
import com.para.paraservice.widgets.SlidingTabLayout;

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @SuppressLint("NewApi")
    public class LandingActivity extends BaseActivity implements ObservableScrollViewCallbacks,
            NavigationDrawerCallbacks {
        private Toolbar mToolbar;
        private View mToolbarView;
        private TouchInterceptionFrameLayout mInterceptionLayout;
        private ViewPager mPager;
        private NavigationAdapter mPagerAdapter;
        private int mSlop;
        private boolean mScrolled;
        private ScrollState mLastScrollState;
        private NavigationDrawerFragment mNavigationDrawerFragment;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.landing);

            mToolbar = (Toolbar) findViewById(R.id.toolbar);
            mToolbarView = findViewById(R.id.toolbar);
            setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
            getSupportActionBar().setTitle("PARA");
            getSupportActionBar().setDisplayShowHomeEnabled(true);

            ViewCompat.setElevation(findViewById(R.id.header), getResources().getDimension(R.dimen.toolbar_elevation));
            mPagerAdapter = new NavigationAdapter(getSupportFragmentManager());
            mPager = (ViewPager) findViewById(R.id.pager);
            mPager.setAdapter(mPagerAdapter);

            final int tabHeight = getResources().getDimensionPixelSize(R.dimen.tab_height);
            findViewById(R.id.pager_wrapper).setPadding(0, getActionBarSize() + tabHeight, 0, 0);

            SlidingTabLayout slidingTabLayout = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
            slidingTabLayout.setCustomTabView(R.layout.tab_indicator, android.R.id.text1);
            slidingTabLayout.setSelectedIndicatorColors(getResources().getColor(R.color.accent));
            slidingTabLayout.setDistributeEvenly(true);
            slidingTabLayout.setViewPager(mPager);

            ViewConfiguration vc = ViewConfiguration.get(this);
            mSlop = vc.getScaledTouchSlop();
            mInterceptionLayout = (TouchInterceptionFrameLayout) findViewById(R.id.container);
            mInterceptionLayout.setScrollInterceptionListener(mInterceptionListener);


            mNavigationDrawerFragment = (NavigationDrawerFragment) getFragmentManager()
                    .findFragmentById(R.id.fragment_drawer);
            mNavigationDrawerFragment.setup(R.id.fragment_drawer,
                    (DrawerLayout) findViewById(R.id.drawer), mToolbar);

        }
        @Override
        public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
        }

        @Override
        public void onDownMotionEvent() {
        }

        @Override
        public void onUpOrCancelMotionEvent(ScrollState scrollState) {
            if (!mScrolled) {
                // This event can be used only when TouchInterceptionFrameLayout
                // doesn't handle the consecutive events.
                adjustToolbar(scrollState);
            }
        }

        private TouchInterceptionFrameLayout.TouchInterceptionListener mInterceptionListener = new TouchInterceptionFrameLayout.TouchInterceptionListener() {
            @Override
            public boolean shouldInterceptTouchEvent(MotionEvent ev, boolean moving, float diffX, float diffY) {
                if (!mScrolled && mSlop < Math.abs(diffX) && Math.abs(diffY) < Math.abs(diffX)) {
                    // Horizontal scroll is maybe handled by ViewPager
                    return false;
                }

                Scrollable scrollable = getCurrentScrollable();
                if (scrollable == null) {
                    mScrolled = false;
                    return false;
                }

                // If interceptionLayout can move, it should intercept.
                // And once it begins to move, horizontal scroll shouldn't work any longer.
                int toolbarHeight = mToolbarView.getHeight();
                int translationY = (int) ViewHelper.getTranslationY(mInterceptionLayout);
                boolean scrollingUp = 0 < diffY;
                boolean scrollingDown = diffY < 0;
                if (scrollingUp) {
                    if (translationY < 0) {
                        mScrolled = true;
                        mLastScrollState = ScrollState.UP;
                        return true;
                    }
                } else if (scrollingDown) {
                    if (-toolbarHeight < translationY) {
                        mScrolled = true;
                        mLastScrollState = ScrollState.DOWN;
                        return true;
                    }
                }
                mScrolled = false;
                return false;
            }

            @Override
            public void onDownMotionEvent(MotionEvent ev) {
            }

            @Override
            public void onMoveMotionEvent(MotionEvent ev, float diffX, float diffY) {
                float translationY = ScrollUtils.getFloat(ViewHelper.getTranslationY(mInterceptionLayout) + diffY, -mToolbarView.getHeight(), 0);
                ViewHelper.setTranslationY(mInterceptionLayout, translationY);
                if (translationY < 0) {
                    FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mInterceptionLayout.getLayoutParams();
                    lp.height = (int) (-translationY + getScreenHeight());
                    mInterceptionLayout.requestLayout();
                }
            }

            @Override
            public void onUpOrCancelMotionEvent(MotionEvent ev) {
                mScrolled = false;
                adjustToolbar(mLastScrollState);
            }
        };

        private Scrollable getCurrentScrollable() {
            Fragment fragment = getCurrentFragment();
            if (fragment == null) {
                return null;
            }
            View view = fragment.getView();
            if (view == null) {
                return null;
            }
            return (Scrollable) view.findViewById(R.id.scroll);
        }

        private void adjustToolbar(ScrollState scrollState) {
            int toolbarHeight = mToolbarView.getHeight();
            final Scrollable scrollable = getCurrentScrollable();
            if (scrollable == null) {
                return;
            }
            int scrollY = scrollable.getCurrentScrollY();
            if (scrollState == ScrollState.DOWN) {
                showToolbar();
            } else if (scrollState == ScrollState.UP) {
                if (toolbarHeight <= scrollY) {
                    hideToolbar();
                } else {
                    showToolbar();
                }
            } else if (!toolbarIsShown() && !toolbarIsHidden()) {
                // Toolbar is moving but doesn't know which to move:
                // you can change this to hideToolbar()
                showToolbar();
            }
        }

        private Fragment getCurrentFragment() {
            return mPagerAdapter.getItemAt(mPager.getCurrentItem());
        }

        private boolean toolbarIsShown() {
            return ViewHelper.getTranslationY(mInterceptionLayout) == 0;
        }

        private boolean toolbarIsHidden() {
            return ViewHelper.getTranslationY(mInterceptionLayout) == -mToolbarView.getHeight();
        }

        private void showToolbar() {
            animateToolbar(0);
        }

        private void hideToolbar() {
            animateToolbar(-mToolbarView.getHeight());
        }

        private void animateToolbar(final float toY) {
            float layoutTranslationY = ViewHelper.getTranslationY(mInterceptionLayout);
            if (layoutTranslationY != toY) {
                ValueAnimator animator = ValueAnimator.ofFloat(ViewHelper.getTranslationY(mInterceptionLayout), toY).setDuration(200);
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float translationY = (float) animation.getAnimatedValue();
                        ViewHelper.setTranslationY(mInterceptionLayout, translationY);
                        if (translationY < 0) {
                            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mInterceptionLayout.getLayoutParams();
                            lp.height = (int) (-translationY + getScreenHeight());
                            mInterceptionLayout.requestLayout();
                        }
                    }
                });
                animator.start();
            }
        }

        @Override
        public void onNavigationDrawerItemSelected(int position) {
            Toast.makeText(this, "Menu item selected -> " + position,
                    Toast.LENGTH_SHORT).show();
        }

        @SuppressLint("NewApi")
        @Override
        public void onBackPressed() {
            if (mNavigationDrawerFragment.isDrawerOpen())
                mNavigationDrawerFragment.closeDrawer();
            else
                super.onBackPressed();
        }

         /**
         * This adapter provides two types of fragments as an example.
         * {@linkplain #createItem(int)} should be modified if you use this example for your app.
         */
        private static class NavigationAdapter extends CacheFragmentStatePagerAdapter {

            private static final String[] TITLES = new String[]{"Applepie", "Butter Cookie", "Cupcake", "Donut", "Eclair", "Froyo", "Gingerbread", "Honeycomb", "Ice Cream Sandwich", "Jelly Bean", "KitKat", "Lollipop"};

            public NavigationAdapter(FragmentManager fm) {
                super(fm);
            }

            @Override
            protected Fragment createItem(int position) {
                Fragment f;
                final int pattern = position % 5;
                switch (pattern) {
                    case 0:
                        f = new ViewPagerTab2ScrollViewFragment();
                        break;
                    case 1:
    //                    f = new ViewPagerTab2ListViewFragment();
                        f = new ViewPagerTab2ScrollViewFragment();
                        break;
                    case 2:
    //                    f = new ViewPagerTab2RecyclerViewFragment();
                        f = new ViewPagerTab2ScrollViewFragment();
                        break;
                    case 3:
    //                    f = new ViewPagerTab2GridViewFragment();
                        f = new ViewPagerTab2ScrollViewFragment();
                        break;
                    case 4:
                    default:
                        f = new ViewPagerTab2ScrollViewFragment();
    //                    f = new ViewPagerTab2WebViewFragment();
                        break;
                }
                return f;
            }

            @Override
            public int getCount() {
                return TITLES.length;
            }

            @Override
            public CharSequence getPageTitle(int position) {
                return TITLES[position];
            }
        }

    }

So the sliding tab functionality working fine without Navigation Drawer.When i add navigation drawer layout to xml and java code to LandingActivity sliding tabs with view pager not working.Can you please tell me what exactly i am doing wrong here.Thanks in advance.

1条回答
Deceive 欺骗
2楼-- · 2019-09-10 08:31

Find ViewPagerTabListViewActivity.class and it layout layout/activity_viewpagertab.xml in ObservableScrollView samples

EDIT: Edited layout and class activity_viewpagertab.xml

<FrameLayout 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.v4.widget.DrawerLayout
        android:id="@+id/drawer"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolbar_actionbar">

        <!--<FrameLayout android:id="@+id/container" android:layout_width="match_parent"-->
        <!--android:clickable="true" android:layout_height="match_parent" />-->

        <!--
    Padding for ViewPager must be set outside the ViewPager itself
    because with padding, EdgeEffect of ViewPager become strange.
    -->
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v4.view.ViewPager
                android:id="@+id/pager"
                android:paddingTop="@dimen/tab_height"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <LinearLayout
                android:id="@+id/header"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:orientation="vertical">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="?attr/colorPrimary"
                    android:minHeight="?attr/actionBarSize"
                    app:popupTheme="@style/Theme.AppCompat.Light.DarkActionBar"
                    app:theme="@style/Toolbar" />

                <com.google.samples.apps.iosched.ui.widget.SlidingTabLayout
                    android:id="@+id/sliding_tabs"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/tab_height"
                    android:background="@color/primary" />
            </LinearLayout>
        </FrameLayout>
        <!-- android:layout_marginTop="?android:attr/actionBarSize"-->
        <fragment
            android:id="@+id/fragment_drawer"
            android:name="com.github.ksoichiro.android.observablescrollview.samples.NavigationDrawerFragment"
            android:layout_width="280dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:layout="@layout/fragment_navigation_drawer" />
    </android.support.v4.widget.DrawerLayout>
</FrameLayout>

part of ViewPagerTabListViewActivity.class

public class ViewPagerTabListViewActivity extends BaseActivity implements ObservableScrollViewCallbacks, NavigationDrawerCallbacks {

private View mHeaderView;
private View mToolbarView;
private int mBaseTranslationY;
private ViewPager mPager;
private NavigationAdapter mPagerAdapter;

private NavigationDrawerFragment mNavigationDrawerFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_viewpagertab);

    setSupportActionBar((Toolbar) findViewById(R.id.toolbar));

    mHeaderView = findViewById(R.id.header);
    ViewCompat.setElevation(mHeaderView, getResources().getDimension(R.dimen.toolbar_elevation));
    mToolbarView = findViewById(R.id.toolbar);
    mPagerAdapter = new NavigationAdapter(getSupportFragmentManager());
    mPager = (ViewPager) findViewById(R.id.pager);
    mPager.setAdapter(mPagerAdapter);

    SlidingTabLayout slidingTabLayout = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
    slidingTabLayout.setCustomTabView(R.layout.tab_indicator, android.R.id.text1);
    slidingTabLayout.setSelectedIndicatorColors(getResources().getColor(R.color.accent));
    slidingTabLayout.setDistributeEvenly(true);
    slidingTabLayout.setViewPager(mPager);

    // When the page is selected, other fragments' scrollY should be adjusted
    // according to the toolbar status(shown/hidden)
    slidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i2) {
        }

        @Override
        public void onPageSelected(int i) {
            propagateToolbarState(toolbarIsShown());
        }

        @Override
        public void onPageScrollStateChanged(int i) {
        }
    });

    propagateToolbarState(toolbarIsShown());

    //Added this --------------------------------------------

    ActionBar ab = getSupportActionBar();
    ab.setDisplayShowHomeEnabled(false);
    ab.setDisplayHomeAsUpEnabled(true);
    ab.setHomeButtonEnabled(true);
    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.fragment_drawer);

    // Set up the drawer.
    mNavigationDrawerFragment.setup(R.id.fragment_drawer, (DrawerLayout) findViewById(R.id.drawer), (Toolbar) mToolbarView);
}

//Added this -----------------------------------------

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    Toast.makeText(this, "Menu item selected -> " + position, Toast.LENGTH_SHORT).show();
}

Now it works like a charm, shared a screenshot. Glad to work on your problem thanks.

ToolBarWithTabs

查看更多
登录 后发表回答