开发流程之五:TabBar切换应用主页面

引言:
当我们的启动页、引导页、网络请求管理类和用户管理类都一步步完善好之后,就要开始实现整个应用的界面了,根据主流应用和多数用户的习惯。首页(主页面)一般都是有底部导航栏的,根据所点击的导航栏中不同的按钮,完成对应的Fragment的切换是主流的做法。
效果如下,上方是ViewPager中的“日更”Fragment,底下一排就是用来切换不同Fragment的TabBar的按钮:

image.png

首先整理一下思路:

整个布局在一个Activity中,上方是一个ViewPager,底部是一个TabBar。通过点击TabBar中的不同按钮,实现ViewPager中不同的Fragment之间的切换,从而实现该功能。这里的底部TabBar可以自己写,也可以用第三方的,这里采用第三方。

实现:

步骤一、
引入依赖:
compile 'me.majiajie:pager-bottom-tab-strip:2.2.4'

步骤二、
主页面:

  1. xml布局:
    其中 NoScrollMainViewpage是继承自ViewPager的自定义控件,其作用是使ViewPager不滑动,可先直接复制下来放入项目中备用(后面有源代码)。
    PageNavigationView为第三方的TabBar切换工具。
<RelativeLayout                       
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:fitsSystemWindows="true">

    <!--首页ViewPager,不可左右滑动的VP,-->
    <com.smartlib.cmnObject.ui.NoScrollMainViewpage
        android:id="@+id/vp_main_home"
        android:background="@color/white"
        android:layout_above="@+id/ll_bottom_tab_bar"
        android:layout_below="@id/rl_main_navigation"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </com.smartlib.cmnObject.ui.NoScrollMainViewpage>
   
    <LinearLayout
        android:id="@+id/ll_bottom_tab_bar"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="49.5dp">

        <!--用于底部切换的TabBar-->
        <me.majiajie.pagerbottomtabstrip.PageNavigationView
            android:id="@+id/tab_bar"
            android:background="@color/transparent"
            android:layout_width="match_parent"
            android:layout_height="49dp">
       </me.majiajie.pagerbottomtabstrip.PageNavigationView>

    </LinearLayout>

</RelativeLayout>

NoScrollMainViewpage源代码如下,直接复制到项目中:

/**
 * 不可以滑动的viewpager
 */
public class NoScrollMainViewpage extends ViewPager {
    private boolean noScroll = false;
    /**
    * 上一次x坐标
    */
    private float beforeX;
    private int xDown, xUp, yDown, yUp;

    private int pageIndex;
    private OnTouchListener onTouchListener;

    public void setIndex(int index) {
        this.pageIndex = index;
    }

    public NoScrollMainViewpage(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public NoScrollMainViewpage(Context context) {
        super(context);
    }

    public void setNoScroll(boolean noScroll) {
        this.noScroll = noScroll;
    }

    @Override
    public void scrollTo(int x, int y) {
        super.scrollTo(x, y);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (noScroll)
            return false;
        else
            return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int index = getCurrentItem();
        if (noScroll) {
            return super.dispatchTouchEvent(ev);
        } else {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN://按下如果‘仅’作为‘上次坐标’,不妥,因为可能存在左滑,motionValue大于0的情况(来回滑,只要停止坐标在按下坐标的右边,左滑仍然能滑过去)
                    beforeX = ev.getX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    float motionValue = ev.getX() - beforeX;
                    if (motionValue > 0 && index == 1 && pageIndex == 0) {//禁止左滑
                        return true;
                    }
                    beforeX = ev.getX();//手指移动时,再把当前的坐标作为下一次的‘上次坐标’,解决上述问题
                    break;
                case MotionEvent.ACTION_UP:
                    break;
                default:
                    break;
            }
            if (onTouchListener != null) {
                onTouchListener.onTouch(this, ev);
            }
            return super.dispatchTouchEvent(ev);
        }
    }

    @Override  
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (noScroll){
            return false;
        } else {
            return super.onInterceptTouchEvent(event);
        }
    }

    @Override
    public void setCurrentItem(int item) {
        super.setCurrentItem(item);
    }

    @Override
    public void setOnTouchListener(OnTouchListener l) {
        super.setOnTouchListener(l);
        onTouchListener = l;
    }
}

主页面的布局到此完成。

  1. Activity中的java代码:
    其中HomeViewPagerAdapter是自定义的适配器(后面有源代码)
/**
 *主页面
 */
public class MainActivity extends AppCompatActivity{
    private NoScrollMainViewpage mViewPager;
    //TabBar的外层容器
    private LinearLayout mBottomTabBarLL;

    //将要在ViewPager中切换的三个Fragment
    private HomeListFragment homeListFragment;//日更
    private CatCircleFragment suckCatFragment;//吸猫
    private MineFragment mineFragment;//我的

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

        initView();
    }


    /**
     * 主页视图初始化
     */
    private void initView() {
        configViewPager();
        configTabBar();
 
        //TabBar的外层容器
        mBottomTabBarLL = (LinearLayout) findViewById(R.id.ll_bottom_tab_bar);
    }
   

    /**
     * 设置VP关联Fragment
     */
    private void configViewPager() {
        mViewPager = (NoScrollMainViewpage) findViewById(R.id.vp_main_home);
        mViewPager.setNoScroll(true);
        List<Fragment> fragmentList = new ArrayList<>();

        homeListFragment = new HomeListFragment();//日更
        suckCatFragment = new CatCircleFragment();//吸猫
        mineFragment = new MineFragment();//我的

        fragmentList.add(homeListFragment);
        fragmentList.add(suckCatFragment);
        fragmentList.add(mineFragment);

        FragmentManager fragmentManager = getSupportFragmentManager();

        //自定义适配器
        HomeViewPagerAdapter viewPagerAdapter = new HomeViewPagerAdapter(fragmentManager, fragmentList);
        mViewPager.setAdapter(viewPagerAdapter);
        mViewPager.setCurrentItem(0);
        mViewPager.setOffscreenPageLimit(2);//预加载2个
    }

    /**
     * 初始化底部导航
     */
    private void configTabBar() {
        PageNavigationView tabBar = (PageNavigationView) findViewById(R.id.tab_bar);
        NavigationController navigationController = tabBar.custom()
            .addItem(createTabBarItem(R.drawable.ic_day_up_date_normal, R.drawable.ic_day_up_date_selected, "日更"))
            .addItem(createTabBarItem(R.drawable.ic_cat_circlr_normal, R.drawable.ic_cat_circle_selected, "吸猫"))
            .addItem(createTabBarItem(R.drawable.ic_mine_normal, R.drawable.ic_mine_selected, "我的"))
            .build();
        navigationController.setupWithViewPager(mViewPager);
        //此方法决定点击按钮切换不同的Fragment 
        navigationController.addTabItemSelectedListener(new OnTabItemSelectedListener() {
            @Override
            public void onSelected(int index, int old) {
                //需要注意的是,本方法可能会对Fragment中的生命周期产生影响,尽量不要在本方法中使用各Fragment的对象去调用其中的方法
                if (index == 0) {
                    //第一个按钮的逻辑
                    xxx.setText("日更");
                } else if (index == 1) {
                    //第二个按钮的逻辑
                    xxx.setText("吸猫");
                } else if (index == 2) {
                   //第三个按钮的逻辑
                    xxx.setText("我的");
                }
            }

            @Override
            public void onRepeat(int index) {
      
            }
        });
    }

    /**
     * tabBar 初始图文及其颜色
     */
    private BaseTabItem createTabBarItem(int normalDrawable, int selectedDrawable, String text) {
        MainTabItemView itemView = new MainTabItemView(this);
        itemView.initialize(normalDrawable, selectedDrawable, text);
        itemView.setTextDefaultColor(getResources().getColor(R.color.color_home_list_bar_normal));
        itemView.setTextCheckedColor(getResources().getColor(R.color.color_home_list_bar_selected));
        return itemView;
    }
}

Activity中的代码到此完成,下面看一下HomeViewPagerAdapter:

3.自定义VP适配器:HomeViewPagerAdapter
代码如下:

/**
  * 主页VP适配器
  * 用来切换页卡中不同Fragment
  */
public class HomeViewPagerAdapter extends FragmentPagerAdapter {

    private FragmentManager fragmentManager;
    private List<Fragment> fragmentList;

    public HomeViewPagerAdapter(FragmentManager fm, List<Fragment> list) {
        super(fm);
        this.fragmentManager = fm;
        this.fragmentList = list;
    }

    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentList.size();
    }
}

以上,完成了应用的页面切换功能,该第三方控件还有其他更多的功能,共同学习。
结束。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。