zoukankan      html  css  js  c++  java
  • Tablayout ViewPage 使用示例

    上一篇文章介绍了使用 FragmenttabHost 来使用 tab 导航;到 Android 5.0 的时候,又推出了 TabLayout。因此,有必要对tablayout 进行了解下。

    首先我们来看MainActivity,看起来有点多,那是因为包含了 toolbar 的代码:

    public class MainActivity extends AppCompatActivity {
    
        private TabLayout tabLayout;
        private ViewPager viewPager;
        private MyViewPagerAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
    
            tabLayout = (TabLayout) findViewById(R.id.tab_layout);
            viewPager = (ViewPager) findViewById(R.id.pager);
    
            int s = 0;
    
            if (viewPager != null) {
                setupViewPager(viewPager);
            }
        }
    
        private void setupViewPager(ViewPager viewPager) {
            adapter = new MyViewPagerAdapter(getSupportFragmentManager(), this);
            adapter.addFragment(new TabFragment1().newInstance("Page1"), "Tab 1");
            adapter.addFragment(new TabFragment2().newInstance("Page2"), "Tab 2");
            adapter.addFragment(new TabFragment3().newInstance("Page3"), "Tab 3");
            viewPager.setAdapter(adapter);
            tabLayout.setupWithViewPager(viewPager);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
    
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
    
            return super.onOptionsItemSelected(item);
    }

    首先是初始化 tabLayout 和 viewPager,接着是建立一个 MyViewPagerAdapter 的实例,并向里面添加 fragment。

    那我们就去看看神秘的 MyViewPagerAdapter。

    public class MyViewPagerAdapter extends FragmentStatePagerAdapter {
    
        private final List<Fragment> myFragments = new ArrayList<>();
        private final List<String> myFragmentTitles = new ArrayList<>();
        private Context context;
    
        public MyViewPagerAdapter(FragmentManager fm, Context context) {
            super(fm);
            this.context = context;
        }
    
        public void addFragment(Fragment fragment, String title) {
            myFragments.add(fragment);
            myFragmentTitles.add(title);
        }
    
        @Override
        public Fragment getItem(int position) {
            return myFragments.get(position);
        }
    
        @Override
        public int getCount() {
            return myFragments.size();
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return myFragmentTitles.get(position);
        }
    }

     这里我们重写了其中几个方法,分别是 getItem,getCount,getPageTitle。那这样我们的数量能够传进去嘛?

    不用怕,当我们调用 setAdapt 的时候,其实就把 adapt 传进 ViewPager 了,当需要获取数量的时候,直接调用这个方法就可以了。

    tabLayout.setupWithViewPager(viewPager) 则是把tab 与ViewPage 建立联系,这样在变动的时候一起变,在TabLaout 中,可以通过 viewPager.getAdapt 来获取我们刚刚穿进去的adapt;这样两者都有 adapt 这个变量了。

    public void setupWithViewPager(ViewPager viewPager) {
            PagerAdapter adapter = viewPager.getAdapter();
            if(adapter == null) {
                throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
            } else {
                this.setTabsFromPagerAdapter(adapter);
                viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));
                this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
            }
        }

     看源码可以发现 tablayout 和 viewpager 互相设置或者添加监听器,这样无论是滑动 viewPager,还是点击tab都可以实现 view 的切换,两者就可以同步了。

    public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
            private final ViewPager mViewPager;
    
            public ViewPagerOnTabSelectedListener(ViewPager viewPager) {
                this.mViewPager = viewPager;
            }
    
            public void onTabSelected(TabLayout.Tab tab) {
                this.mViewPager.setCurrentItem(tab.getPosition());
            }
    
            public void onTabUnselected(TabLayout.Tab tab) {
            }
    
            public void onTabReselected(TabLayout.Tab tab) {
            }
        }

    我们可以具体看看 ViewPagerOnTabSelectedListener,发现其实现了 TabLayout.OnTabSelectedListener 的接口,在构造函数中,将 viewPager 变量赋值给内部变量,这样在 tab 选中的时候,获取选中 tab 的 position,然后再将设置显示 同样位置的 fragment 即可。

    public static class TabLayoutOnPageChangeListener implements OnPageChangeListener {
            private final WeakReference<TabLayout> mTabLayoutRef;
            private int mScrollState;
    
            public TabLayoutOnPageChangeListener(TabLayout tabLayout) {
                this.mTabLayoutRef = new WeakReference(tabLayout);
            }
    
            public void onPageScrollStateChanged(int state) {
                this.mScrollState = state;
            }
    
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();
                if(tabLayout != null) {
                    tabLayout.setScrollPosition(position, positionOffset, this.mScrollState == 1);
                }
    
            }
    
            public void onPageSelected(int position) {
                TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();
                if(tabLayout != null) {
                    tabLayout.getTabAt(position).select();
                }
    
            }
        }

    当滑动页面,回掉  onPageSelected,传入目前选中的 pager,这时候只要指定对应的 tab 即可。这样两者很好的进行同步了。

    我们再来看看布局文件:

    <?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:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context=".MainActivity">
    
        <android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
            android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay">
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay"
                app:layout_scrollFlags="scroll|enterAlways" />
    
            <android.support.design.widget.TabLayout
                android:id="@+id/tab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#eeeeee"
                app:tabTextColor="#888888"
                app:tabSelectedTextColor="#000000"
                app:tabGravity="fill"
                app:tabMode="fixed"/>
    
        </android.support.design.widget.AppBarLayout>
    
    
            <android.support.v4.view.ViewPager
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    
    
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:src="@android:drawable/ic_dialog_email" />
    
    </android.support.design.widget.CoordinatorLayout>

     因为有 toolbar ,所以布局文件看上去有些复杂,但其实很简单。

    简化后的布局(id 不一定对得上,其他地方 copy 过来的):

    <?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:orientation="vertical">
    
    
        <android.support.design.widget.TabLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/tabLayout"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:background="#cdc36e"
            app:tabMode="fixed"
            app:tabGravity="fill"/>
    
        <android.support.v4.view.ViewPager
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/viewPager"
            android:layout_below="@+id/tabLayout"
            android:layout_centerHorizontal="true" />
    </RelativeLayout>

    至于 fragment 文件可以参考上一篇文章中的布局 

    fragmentTabHost 使用示例

    或者直接查看源码所在地:

    https://github.com/huanshen/Learn-Android/tree/master/TablayoutViewpager

  • 相关阅读:
    第二次作业
    《自动化技术中的进给电气传动》读书笔记1.1-1.2
    证券投资分析
    微信官方文档概述
    联想拯救者Y7000电池无法充电问题
    Ubuntu用户权限管理
    证券市场基础知识
    Markdown All in One使用教程
    Markdown学习笔记
    第九周
  • 原文地址:https://www.cnblogs.com/huansky/p/7862380.html
Copyright © 2011-2022 走看看