引言:
當我們的啟動頁、引導頁、網(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'
步驟二、
主頁面:
- 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;
}
}
主頁面的布局到此完成。
- 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é)束。