古人已用三冬足,年少今开万卷余。这篇文章主要讲述Android仿小米商城底部导航栏之二(BottomNavigationBarViewPager和Fragment的联动使用)相关的知识,希望能为你提供帮助。
简介 在前文《Android仿小米商城底部导航栏(
基于BottomNavigationBar)
》我们使用BottomNavigationBar控件模仿实现了小米商城底部导航栏效果。接下来更进一步的,
我们将通过BottomNavigationBar控件和ViewPager空间的联动使用来实现主界面的滑动导航。
导航是移动应用最重要的方面之一,
对用户体验是良好还是糟糕起着至关重要的作用。好的导航可以让一款应用更加易用并且让用户快速上手。相反,
糟糕的应用导航很容易让人讨厌,
并遭到用户的抛弃。为了打造流畅的用户导航体验,
我们不得不依赖智能手机最常见的一个功能:
触摸。
触摸改变应用程序的视图是现在最流行一种导航设计。本文中,
我们将经过必要的几步来实现应用内的横向滑动导航与底部导航的联动。
基本原理 我们的MainActivity包含了ViewPager组件,
它封装了几个不同的子界面,
每一界面有一个不同的Fragment。我们要做的第一件事就是声明一个FragmentPagerAdapter,
用它在不用的界面Fragment间切换。
ViewPager 如其名所述,
是负责翻页的一个 View。准确说是一个 ViewGroup,
包含多个 View 页,
在手指横向滑动屏幕时,
其负责对 View 进行切换。为了生成这些 View 页,
需要提供一个 PagerAdapter 来进行和数据绑定以及生成最终的 View 页。
ViewPager 通过 setAdapter() 来建立与 PagerAdapter 的联系。这个联系是双向的,
一方面,
ViewPager 会拥有 PagerAdapter 对象,
从而可以在需要时调用 PagerAdapter 的方法;
另一方面,
ViewPager 会在 setAdapter() 中调用 PagerAdapter 的 registerDataSetObserver() 方法,
注册一个自己生成的 PagerObserver 对象,
从而在 PagerAdapter 有所需要时(
如 notifyDataSetChanged()或 notifyDataSetInvalidated() 时)
,
可以调用 Observer 的 onChanged() 或 onInvalidated() 方法,
从而实现 PagerAdapter 向 ViewPager 方向发送信息。
PageAdapter 是 ViewPager 的支持者,
ViewPager 将调用它来取得所需显示的页,
而 PageAdapter 也会在数据变化时,
通知 ViewPager。这个类也是FragmentPagerAdapter 以及 FragmentStatePagerAdapter 的基类。如果继承自该类,
至少需要实现 instantiateItem(), destroyItem(), getCount() 以及 isViewFromObject()。
FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,
该类更专注于每一页均为 Fragment 的情况。如文档所述,
该类内的每一个生成的 Fragment 都将保存在内存之中,
因此适用于那些相对静态的页,
数量也比较少的那种;
如果需要处理有很多页,
并且数据动态性较大、占用内存较多的情况,
应该使用FragmentStatePagerAdapter。FragmentPagerAdapter 重载实现了几个必须的函数,
因此来自 PagerAdapter 的函数,
我们只需要实现 getCount(),
即可。且,
由于 FragmentPagerAdapter.instantiateItem() 的实现中,
调用了一个新增的虚函数 getItem(),
因此,
我们还至少需要实现一个 getItem()。因此,
总体上来说,
相对于继承自 PagerAdapter,
更方便一些。
设置ViewPager的监听事件
当ViewPager的某个页面被选中时,
需要相应的选中BottomNavigationBar控件的对应标签。
viewPager.addOnPageChangeListener(this);
@
Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@
Override
public void onPageSelected(int position) {
bottomNavigationBar.selectTab(position);
}@
Override
public void onPageScrollStateChanged(int state) {}
设置BottomNavigationBar的监听事件
当BottomNavigationBar控件的某个标签被选中的时候, 需要相应的选中ViewPager的对应页面。
bottomNavigationBar.setTabSelectedListener(this);
@
Override
public void onTabSelected(int position) {
viewPager.setCurrentItem(position);
}@
Override
public void onTabUnselected(int position) {}@
Override
public void onTabReselected(int position) {}
实现效果
文章图片
主要代码 主界面布局文件activity_main,xml:
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
LinearLayout
android:id=
"
@
+
id/activity_main"
xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:tools=
"
http://schemas.android.com/tools"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
android:orientation=
"
vertical"
tools:context=
"
com.rainsong.mishop.MainActivity"
>
<
android.support.v4.view.ViewPager
android:id=
"
@
+
id/view_pager"
android:layout_width=
"
match_parent"
android:layout_height=
"
0dp"
android:layout_weight=
"
1"
/>
<
com.ashokvarma.bottomnavigation.BottomNavigationBar
android:id=
"
@
+
id/bottom_navigation_bar"
android:layout_width=
"
match_parent"
android:layout_height=
"
wrap_content"
android:layout_gravity=
"
bottom"
/>
<
/LinearLayout>
MainActivity.java
package com.rainsong.mishop;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import com.ashokvarma.bottomnavigation.BottomNavigationBar;
import com.ashokvarma.bottomnavigation.BottomNavigationItem;
import com.rainsong.mishop.adapter.SectionsPagerAdapter;
import com.rainsong.mishop.fragment.CatagoryFragment;
import com.rainsong.mishop.fragment.DiscoverFragment;
import com.rainsong.mishop.fragment.HomeFragment;
import com.rainsong.mishop.fragment.UserCentralFragment;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements BottomNavigationBar
.OnTabSelectedListener, ViewPager.OnPageChangeListener {private ViewPager viewPager;
private BottomNavigationBar bottomNavigationBar;
private List<
Fragment>
fragments;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}private void initView() {
initBottomNavigationBar();
initViewPager();
}private void initBottomNavigationBar() {
bottomNavigationBar =
(BottomNavigationBar) findViewById(R.id.bottom_navigation_bar);
bottomNavigationBar.setTabSelectedListener(this);
bottomNavigationBar.clearAll();
bottomNavigationBar.setMode(BottomNavigationBar.MODE_FIXED);
bottomNavigationBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC);
bottomNavigationBar
.addItem(new BottomNavigationItem(R.drawable.icon_main_home_selected, R.string.home)
.setInactiveIconResource(R.drawable.icon_main_home_normal)
.setActiveColorResource(R.color.orange))
.addItem(new BottomNavigationItem(R.drawable.icon_main_category_selected, R
.string.category)
.setInactiveIconResource(R.drawable.icon_main_category_normal)
.setActiveColorResource(R.color.orange))
.addItem(new BottomNavigationItem(R.drawable.icon_main_discover_selected, R
.string.discover)
.setInactiveIconResource(R.drawable.icon_main_discover_normal)
.setActiveColorResource(R.color.orange))
.addItem(new BottomNavigationItem(R.drawable.icon_main_mine_selected, R.string.mine)
.setInactiveIconResource(R.drawable.icon_main_mine_normal)
.setActiveColorResource(R.color.orange))
.initialise();
}private void initViewPager() {
viewPager =
(ViewPager) findViewById(R.id.view_pager);
fragments =
new ArrayList<
Fragment>
();
fragments.add(new HomeFragment());
fragments.add(new CatagoryFragment());
fragments.add(new DiscoverFragment());
fragments.add(new UserCentralFragment());
viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager(), fragments));
viewPager.addOnPageChangeListener(this);
viewPager.setCurrentItem(0);
}@
Override
public void onTabSelected(int position) {
viewPager.setCurrentItem(position);
}@
Override
public void onTabUnselected(int position) {}@
Override
public void onTabReselected(int position) {}@
Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@
Override
public void onPageSelected(int position) {
bottomNavigationBar.selectTab(position);
}@
Override
public void onPageScrollStateChanged(int state) {}
}
SectionsPagerAdapter.java
package com.rainsong.mishop.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.List;
/**
* Created by maxliaops on 17-1-6.
*/public class SectionsPagerAdapter extends FragmentPagerAdapter {
List<
Fragment>
fragments;
public SectionsPagerAdapter(FragmentManager fm, List<
Fragment>
fragments) {
super(fm);
this.fragments =
fragments;
}@
Override
public Fragment getItem(int position) {
return fragments.get(position);
}@
Override
public int getCount() {
return fragments.size();
}
}
【Android仿小米商城底部导航栏之二(BottomNavigationBarViewPager和Fragment的联动使用)】Demo: https://github.com/maxliaops/android-exercise/tree/master/MiShop
推荐阅读
- Android 浮窗开发之窗口层级
- Android 7.0 ActivityManagerService 进程管理相关流程分析
- Android中Http加载如何得到Cookie和 WebView 加载网页如何得到的Cookie
- rnandroid环境搭建
- Android -- 下载进度条(只要有网址就行)
- Android中实现全屏无标题栏的两种办法
- 原Android热更新开源项目Tinker源码解析系列之三(so热更新)
- Android—Service与Activity的交互
- android studio 不能创建或者安装模拟器