android使用Viewpager和TabLayout结合fragment实现首页底部导航的效果
前言
现如今几乎每一款手机APP首页都采用了底部导航的功能,现在我们使用Viewpager和TabLayout结合fragment来实现该功能。
效果图如下:
这里有一个问题,TabLayout的五个icon在模拟器中宽度无法充满屏幕,暂时还不知道为什么,手机能够正常显示。
该项目的githup地址为:https://github.com/gumaoqi/bottomNavigation
你可以去将项目clone下来,然后查看或更改来达到自己的需求。
具体代码:
build.gradle
implementation 'com.jakewharton:butterknife:8.8.1'
//butterknife
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
//butterknife
implementation 'com.android.support:design:27.1.1'
项目中用到butterknife,添加依赖;TabLaout需要添加design的依赖,该依赖下还有经常用到的RecyclerView等控件
MainActivity.java
public class MainActivity extends AppCompatActivity {
@BindView(R.id.activity_main_back_tv)
TextView activityMainBackTv;
@BindView(R.id.activity_main_title_tv)
TextView activityMainTitleTv;
@BindView(R.id.activity_main_menu_tv)
TextView activityMainMenuTv;
@BindView(R.id.activity_main_fragment_vp)
ViewPager activityMainFragmentVp;
@BindView(R.id.activity_main_bottom_navigation_tl)
TabLayout activityMainBottomNavigationTl;
List<Fragment> fragmentList;
List<String> stringList;
MyFragmentPagerAdapter myFragmentPagerAdapter;
void inidata() {
fragmentList = new ArrayList<>();
fragmentList.add(new MyFragment());
fragmentList.add(new MyFragment());
fragmentList.add(new MyFragment());
fragmentList.add(new MyFragment());
fragmentList.add(new MyFragment());
stringList = new ArrayList<>();
stringList.add("苹果");
stringList.add("香蕉");
stringList.add("菠萝");
stringList.add("葡萄");
stringList.add("西瓜");
myFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragmentList, stringList);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
inidata();
//设置viewpager和tablayout
activityMainFragmentVp.setAdapter(myFragmentPagerAdapter);
activityMainFragmentVp.setOffscreenPageLimit(5);
activityMainBottomNavigationTl.setupWithViewPager(activityMainFragmentVp);
for (int i = 0; i < activityMainBottomNavigationTl.getTabCount(); i++) {
activityMainBottomNavigationTl.getTabAt(i).setIcon(R.mipmap.ic_launcher_round);
}
activityMainBottomNavigationTl.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
switch (tab.getPosition()) {
case 0:
activityMainTitleTv.setText("苹果");
break;
case 1:
activityMainTitleTv.setText("香蕉");
break;
case 2:
activityMainTitleTv.setText("菠萝");
break;
case 3:
activityMainTitleTv.setText("葡萄");
break;
case 4:
activityMainTitleTv.setText("西瓜");
break;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
一共设置了5个相同的fragment,实际项目中根据不同需求添加不同的fragment完成不同的功能
activity.main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="@color/turquoise"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/activity_main_back_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回" />
<TextView
android:id="@+id/activity_main_title_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="苹果"
android:textColor="@color/colorPrimary" />
<TextView
android:id="@+id/activity_main_menu_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="菜单" />
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/activity_main_fragment_vp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></android.support.v4.view.ViewPager>
<android.support.design.widget.TabLayout
android:id="@+id/activity_main_bottom_navigation_tl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"></android.support.design.widget.TabLayout>
</LinearLayout>
最上方有一个标题栏,实际项目中通常为toolbar,这里用LinearLayout代替
MyFragment.java
public class MyFragment extends Fragment {
final String TAG = "MyFragment";
private Unbinder unbinder;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
//返回一个Unbinder值(进行解绑),注意这里的this不能使用getActivity()
unbinder = ButterKnife.bind(this, view);
intData();
setView();
return view;
}
void intData() {
}
void setView() {
}
/**
* onDestroyView中进行解绑操作
*/
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}
Myfragment不做任何事,仅仅是显示一个文字。
fragment_my.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="我是一个fragment" />
</LinearLayout>
布局也很简单,只有一个textview
至此,已成功实现了该功能,更多的后续功能需要实现各种Fragment去完成,其中涉及到Activity和Fragment的通信,Fragment之间的通信,但这些不是本文的内容,请自行学习。
后记
在使用Viewpager结合Fragment中你一定会遇到很多的坑,这里记录一个坑:Viewpager会默认预加载一个左右的Fragment,也就是说当我处于苹果Fragment的时候,香蕉Fragment其实已经被加载出来了;当我处于香蕉Fragment的时候,苹果Fragment和菠萝Fragment其实已经被加载出来了。我们可以通过setOffscreenPageLimit(int limit)调整这个预加载的数量,比如说:设置为5,就会预加载左右最多各5个一共最多10个Fragment,那么可以设置为0关闭预加载吗?答案是:不行。查看setOffscreenPageLimit(int limit)源码:
public void setOffscreenPageLimit(int limit) {
if (limit < 1) {
Log.w("ViewPager", "Requested offscreen page limit " + limit + " too small; defaulting to " + 1);
limit = 1;
}
if (limit != this.mOffscreenPageLimit) {
this.mOffscreenPageLimit = limit;
this.populate();
}
}
当你传入的数字小于1时,他会设为1,也就是说我们无法通过该手段关闭其预加载。
本篇文章的主要目的为:记录某个功能的实现方法,以便日后查询。如果阅读后对你有所帮助,我将深感荣幸。
博主水平有限,如有指正错误和其他建议请在评论区留言。