Android仿小米商城底部导航栏之二(BottomNavigationBar、ViewPager和Fragment的联动使用)
2017-01-07 10:59
519 查看
简介
在前文《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(); } }
Demo:https://github.com/maxliaops/android-exercise/tree/master/MiShop
相关文章推荐
- jQuery实现下滑菜单导航效果代码
- jquery实现的仿天猫侧导航tab切换效果
- Android App开发中ViewPager组件的入门使用教程
- Android组件创建DrawerLayout导航
- PHP的栏目导航程序
- jquery实现向下滑出的二级导航下滑菜单效果
- 基于jQuery实现以手风琴方式展开和折叠导航菜单
- JS+CSS实现六级网站导航主菜单效果
- JS实现网页顶部向下滑出的全国城市切换导航效果
- 原生js和jquery分别实现横向导航菜单效果
- 使用Sticky组件实现带sticky效果的tab导航和滚动导航的方法
- JS中用三种方式实现导航菜单中的二级下拉菜单
- js实现显示当前状态的导航效果代码
- javascript实现当前页导航激活的方法
- JS+CSS实现的日本门户网站经典选项卡导航效果
- JS实现自动变化的导航菜单效果代码
- 一个炫酷的Bootstrap导航菜单
- jquery实现红色竖向多级向右展开的导航菜单效果
- jQuery实现的背景动态变化导航菜单效果
- 基于jquery固定于顶部的导航响应浏览器滚动条事件