開發(fā)流程之五:TabBar切換應用主頁面

引言:
當我們的啟動頁、引導頁、網(wǎng)絡請求管理類和用戶管理類都一步步完善好之后,就要開始實現(xiàn)整個應用的界面了,根據(jù)主流應用和多數(shù)用戶的習慣。首頁(主頁面)一般都是有底部導航欄的,根據(jù)所點擊的導航欄中不同的按鈕,完成對應的Fragment的切換是主流的做法。
效果如下,上方是ViewPager中的“日更”Fragment,底下一排就是用來切換不同F(xiàn)ragment的TabBar的按鈕:

image.png

首先整理一下思路:

整個布局在一個Activity中,上方是一個ViewPager,底部是一個TabBar。通過點擊TabBar中的不同按鈕,實現(xiàn)ViewPager中不同的Fragment之間的切換,從而實現(xiàn)該功能。這里的底部TabBar可以自己寫,也可以用第三方的,這里采用第三方。

實現(xiàn):

步驟一、
引入依賴:
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關聯(lián)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中的生命周期產(chǎn)生影響,盡量不要在本方法中使用各Fragment的對象去調(diào)用其中的方法
                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適配器
  * 用來切換頁卡中不同F(xiàn)ragment
  */
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();
    }
}

以上,完成了應用的頁面切換功能,該第三方控件還有其他更多的功能,共同學習。
結(jié)束。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容