前沿 距Google I/O(2014)最新发布的Material Design Android 设计风格已经有一段时间了, 2016年Google在 Android Design Support Library 25基础上增加了 一个BottomNavigationView
新控件,
相比之前实现导航栏的方式,如LinearLayout + TextView(使用android:drawableTop属性+selector状态切换)、
LinearLayout + RelativeLayout(TextView+ImageView)
RadioGroup + RadioButton,2015年Google推出的兼容包Android Design Support Library中的TabLayout等
该控件提供更简洁的方式实现功能模块导航,符合材料设计规范,
效果图如下:
BottomNavigationView 继承自 FrameLayout 对外暴露了OnNavigationItemSelectedListener接口,便于对子视图点击事件的处理,可以通过此接口动态
改变文字颜色 图标颜色;
在XML需要了解其以下属性 (记得添加 xmlns:app="http://schemas.android.com/apk/res-auto")
app:itemIconTint : 设置图标着色
app:itemTextColor : 设置文本颜色
app:menu : 设置菜单
app:itemBackground : 设置导航栏的背景色
默认该控件图标、文本都使用系统自带的@color/colorPrimary颜色
需要注意的是源码中明确指出最大子View个数不能超过5个,在子View个数大于等于4的时候 只有选中的显示文字,没有选中的只显示图标
并且会显示自带的动画,貌似看起来有些浮夸,在源码BottomNavigationMenuView中,有一个全局变量:mShiftingMode,
private boolean mShiftingMode = true;在创建、更新Menu的时候调用了buildMenuView()方法
public void buildMenuView() {
...
mShiftingMode = mMenu.size() > 3;
...
}
具体效果图如下:
下面使用BottomNavigationView+ViewPager+Fragment组合实现 导航展示界面 真机5.0.2测试
compile 'com.android.support:design:25.0.0'
首先在Res目录下创建一个menu文件夹,并新建一个activity_main_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/home"
android:icon="@drawable/ic_home_white_24dp"
android:title="首页" />
<item
android:id="@+id/love"
android:icon="@drawable/ic_favorite_white_24dp"
android:title="喜欢" />
<item
android:id="@+id/video"
android:icon="@drawable/ic_videogame_asset_white_24dp"
android:title="视频" />
<item
android:id="@+id/book"
android:icon="@drawable/ic_book_white_24dp"
android:title="订阅" />
<item
android:id="@+id/github"
android:icon="@drawable/ic_github_circle_white_24dp"
android:title="Github" />
</menu>
<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:orientation="vertical"
tools:context="com.createfuture.android.md50.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9" />
<android.support.design.widget.BottomNavigationView
android:id="@+id/main_bottom_nav_bar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.1"
android:background="@android:color/white"
app:itemIconTint="#be4c00"
app:itemTextColor="#be4c00"
app:menu="@menu/activity_main_bottom"
/>
</LinearLayout>
BaseActivity基类简单封装如下:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutViewId());
//initView
initView();
//initData
initData();
//initListener
initListener();
}
protected abstract void initListener();
protected abstract void initData();
protected abstract void initView();
// UI View Layout
protected abstract @LayoutRes int getLayoutViewId();
//get View ID
public <T extends View> T getViewId(int id){
View view=getWindow().getDecorView().findViewById(id);
return (T) view;
}
}
MainActivity代码如下:
官方的BottomNavigationView的item个数大于4个的时候会自动的改变显示模式,
隐藏了文字,相比之下,下面的导航栏就没有这个问题,而且功能更全。
目前github开源了几个好用的控件,
第一个:外国开源 https://github.com/aurelhubert/ahbottomnavigation
下面是包含的开源文件
AHNotification.java
AHNotificationHelper.java
AHBottomNavigation.java
AHBottomNavigationAdapter.java
AHBottomNavigationBehavior.java
AHBottomNavigationFABBehavior.java
AHBottomNavigationItem.java
AHBottomNavigationViewPager.java
AHHelper.java
VerticalScrollingBehavior.java
...
可以实现消息角标提示等效果,如图:
第二个:外国开源https://github.com/Ashok-Varma/BottomNavigation
BottomVerticalScrollBehavior.java
VerticalScrollingBehavior.java
utils文件夹中包含如下:
BadgeItem.java
BottomNavigationBar.java
BottomNavigationHelper.java
BottomNavigationItem.java
BottomNavigationTab.java
FixedBottomNavigationTab.java
ShapeBadgeItem.java2.0.1 released
ShiftingBottomNavigationTab.java
TextBadgeItem.java
第三个:外国开源
https://github.com/armcha/LuseenBottomNavigation
实现效果跟官方的类似
包含文件:
..
BottomNavigationItem.java
BottomNavigationUtils.java
BottomNavigationView.java
OnBottomNavigationItemClickListener.java
主要说一下第一个开源实现案例 自定义ViewPager+底部导航栏AHBottomNavigation+自定义Fragment实现
首先引入依赖
compile 'com.aurelhubert:ahbottomnavigation:2.1.0'
compile 'com.android.support:design:25+'
注意:如果想实现如图所示的效果,需要在页面中添加一个上下滑动的列表,如果不是RecyclerView,没有上下联动效果,
如果想自己实现,可以继承CoordinatorLayout.Behavior<V> ,重写必要的方法实现
RecyclerView对应的适配器 MyAdapter代码如下:
列表子视图layout_item_demo.xml
自定义一个Fragment 起名为TestFragment 对应布局文件(fragment_demo_list.xml)如下:
TestFragment文件内容:
MainActivity对应的布局文件如下:
MainActivity对应的代码如下:
除了上面显示的底部导航栏效果,还有一种也是较为常见的,先上图:
感兴趣可以到Github,传送门:https://github.com/armcha/Space-Navigation-View
相比之前实现导航栏的方式,如LinearLayout + TextView(使用android:drawableTop属性+selector状态切换)、
LinearLayout + RelativeLayout(TextView+ImageView)
RadioGroup + RadioButton,2015年Google推出的兼容包Android Design Support Library中的TabLayout等
该控件提供更简洁的方式实现功能模块导航,符合材料设计规范,
效果图如下:
BottomNavigationView 继承自 FrameLayout 对外暴露了OnNavigationItemSelectedListener接口,便于对子视图点击事件的处理,可以通过此接口动态
改变文字颜色 图标颜色;
在XML需要了解其以下属性 (记得添加 xmlns:app="http://schemas.android.com/apk/res-auto")
app:itemIconTint : 设置图标着色
app:itemTextColor : 设置文本颜色
app:menu : 设置菜单
app:itemBackground : 设置导航栏的背景色
默认该控件图标、文本都使用系统自带的@color/colorPrimary颜色
需要注意的是源码中明确指出最大子View个数不能超过5个,在子View个数大于等于4的时候 只有选中的显示文字,没有选中的只显示图标
并且会显示自带的动画,貌似看起来有些浮夸,在源码BottomNavigationMenuView中,有一个全局变量:mShiftingMode,
private boolean mShiftingMode = true;在创建、更新Menu的时候调用了buildMenuView()方法
public void buildMenuView() {
...
mShiftingMode = mMenu.size() > 3;
...
}
具体效果图如下:
下面使用BottomNavigationView+ViewPager+Fragment组合实现 导航展示界面 真机5.0.2测试
使用前打开build.gradle 添加依赖
//可以修改为你项目中对应的版本号 建议修改与 compile 'com.android.support:appcompat-v7:25.0.0' 相同的版本号compile 'com.android.support:design:25.0.0'
首先在Res目录下创建一个menu文件夹,并新建一个activity_main_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/home"
android:icon="@drawable/ic_home_white_24dp"
android:title="首页" />
<item
android:id="@+id/love"
android:icon="@drawable/ic_favorite_white_24dp"
android:title="喜欢" />
<item
android:id="@+id/video"
android:icon="@drawable/ic_videogame_asset_white_24dp"
android:title="视频" />
<item
android:id="@+id/book"
android:icon="@drawable/ic_book_white_24dp"
android:title="订阅" />
<item
android:id="@+id/github"
android:icon="@drawable/ic_github_circle_white_24dp"
android:title="Github" />
</menu>
MainActivity XML定义如下:
<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:orientation="vertical"
tools:context="com.createfuture.android.md50.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9" />
<android.support.design.widget.BottomNavigationView
android:id="@+id/main_bottom_nav_bar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.1"
android:background="@android:color/white"
app:itemIconTint="#be4c00"
app:itemTextColor="#be4c00"
app:menu="@menu/activity_main_bottom"
/>
</LinearLayout>
BaseActivity基类简单封装如下:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutViewId());
//initView
initView();
//initData
initData();
//initListener
initListener();
}
protected abstract void initListener();
protected abstract void initData();
protected abstract void initView();
// UI View Layout
protected abstract @LayoutRes int getLayoutViewId();
//get View ID
public <T extends View> T getViewId(int id){
View view=getWindow().getDecorView().findViewById(id);
return (T) view;
}
}
MainActivity代码如下:
package com.createfuture.android.guidenavigationbar; import android.annotation.SuppressLint; import android.content.res.ColorStateList; import android.graphics.Color; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.RequiresApi; import android.support.design.internal.BottomNavigationItemView; import android.support.design.internal.BottomNavigationMenuView; import android.support.design.widget.BottomNavigationView; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.widget.Toast; import com.createfuture.android.md50.R; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; public class MainActivity extends BaseActivity implements BottomNavigationView.OnNavigationItemSelectedListener, ViewPager.OnPageChangeListener { private ViewPager viewPager;//实现左右滑动的ViewPager private BottomNavigationView bottomNavigationView;//底部导航栏 private List<Fragment> myFragment = new ArrayList<>();//存放Fragment集合 private String[] mTiltls = new String[]{"首页", "喜欢", "视频", "订阅", "Github"}; private long currentTime = 0; @Override protected int getLayoutViewId() { return R.layout.activity_main; } @Override protected void initView() { bottomNavigationView = getViewId(R.id.main_bottom_nav_bar); //设置背景色 bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffffbb33"))); //禁用模式 disableShiftMode(bottomNavigationView); //设置默认选中最后一个 bottomNavigationView.setSelectedItemId(R.id.github); viewPager = getViewId(R.id.viewPager); //可以设置ViewPager禁止滑动 //禁止ViewPager滑动 viewPager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); } /** * * 如何禁用ShiftingMode这种模式,stackoverflow上面找到解决办法:反射: * <a href="https://stackoverflow.com/questions/40176244/how-to-disable-bottomnavigationview-shift-mode">禁用</a>. */ @SuppressLint("RestrictedApi") public void disableShiftMode(BottomNavigationView view) { BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0); try { Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode"); shiftingMode.setAccessible(true); shiftingMode.setBoolean(menuView, false); shiftingMode.setAccessible(false); for (int i = 0; i < menuView.getChildCount(); i++) { BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i); //noinspection RestrictedApi item.setShiftingMode(false); // set once again checked value, so view will be updated //noinspection RestrictedApi item.setChecked(item.getItemData().isChecked()); } } catch (NoSuchFieldException e) { Log.e("shiftingMode", "Unable to get shift mode field", e); } catch (IllegalAccessException e) { Log.e("shiftingMode", "Unable to change value of shift mode", e); } } /** * 初始化底部导航栏数据 Fragment集合 并配置适配器 */ @Override protected void initData() { for (int i = 0; i < mTiltls.length; i++) { myFragment.add(TestFragment.getInstance(mTiltls[i])); } viewPager.setAdapter(new CustomPagerAdapter(getSupportFragmentManager())); viewPager.setCurrentItem(4); } @Override protected void initListener() { bottomNavigationView.setOnNavigationItemSelectedListener(this); viewPager.setOnPageChangeListener(this); } /** * @param item 获取到MenuItem Id * @return 返回true 显示选中效果 反之不会显示 */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { // int itemId = item.getItemId(); switch (itemId) { case R.id.home: viewPager.setCurrentItem(0); break; case R.id.love: viewPager.setCurrentItem(1); break; case R.id.video: viewPager.setCurrentItem(2); break; case R.id.book: viewPager.setCurrentItem(3); break; case R.id.github: viewPager.setCurrentItem(4); break; } return true; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } /** * 选中的效果 * //API 21 及其以上才可以设置setBackgroundTintList * @param position */ @SuppressLint("ResourceAsColor") @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onPageSelected(int position) { switch (position) { case 0: bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffff8800"))); bottomNavigationView.setSelectedItemId(R.id.home); break; case 1: bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ff99cc00"))); bottomNavigationView.setSelectedItemId(R.id.love); break; case 2: bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ff0099cc"))); bottomNavigationView.setSelectedItemId(R.id.video); break; case 3: bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.GRAY)); bottomNavigationView.setSelectedItemId(R.id.book); break; case 4: bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffffbb33"))); bottomNavigationView.setSelectedItemId(R.id.github); break; } } @Override public void onPageScrollStateChanged(int state) { } //ViewPager Adapter 真正开发 记得要新建一个类,尽可能的少用内部类 private class CustomPagerAdapter extends FragmentPagerAdapter { public CustomPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return myFragment == null ? null : myFragment.get(position); } @Override public int getCount() { return myFragment.size() == 0 ? 0 : myFragment.size(); } } /** * 监听返回键 */ @Override public void onBackPressed() { if (viewPager.getCurrentItem() != 0) { viewPager.setCurrentItem(0); } else { exit(); } } //退出 private void exit() { if (System.currentTimeMillis() -currentTime >2000) { currentTime = System.currentTimeMillis(); Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show(); } else { finish(); } } }
TestFragment代码如下:
package com.createfuture.android.guidenavigationbar; import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.TextView; /** * Created by GuoBin on 2017/12/23. */ public class TestFragment extends Fragment { //静态常量标识 private final static String KEY=TestFragment.class.getSimpleName(); public static Fragment getInstance(String textContent){ /** * 实例化当前Fragment 并初始化Bundle 保存数据到Fragment,用于Fragment界面文本展示 */ TestFragment fragment=new TestFragment(); Bundle bundle=new Bundle(); bundle.putString(KEY,textContent); fragment.setArguments(bundle); return fragment; } /** * 加载视图 * @param inflater * @param container * @param savedInstanceState * @return */ @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { /** * 布局文件通过动态生成 首先新建一个 RelativeLayout,设置宽高属性 * 同理新建一个TextView,设置宽高属性,并设置文本 * 将TextView添加到RelativeLayout中 */ RelativeLayout relativeLayout=new RelativeLayout(getContext().getApplicationContext()); RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); relativeLayout.setLayoutParams(layoutParams); TextView textView=new TextView(getContext().getApplicationContext()); textView.setLayoutParams(layoutParams); textView.setGravity(Gravity.CENTER); textView.setTextSize(23); textView.setTextColor(Color.BLACK); textView.setText(getArguments().getString(KEY)!=null?getArguments().getString(KEY).toString():""); relativeLayout.addView(textView); return relativeLayout; } }
官方的BottomNavigationView的item个数大于4个的时候会自动的改变显示模式,
隐藏了文字,相比之下,下面的导航栏就没有这个问题,而且功能更全。
目前github开源了几个好用的控件,
第一个:外国开源 https://github.com/aurelhubert/ahbottomnavigation
下面是包含的开源文件
AHNotification.java
AHNotificationHelper.java
AHBottomNavigation.java
AHBottomNavigationAdapter.java
AHBottomNavigationBehavior.java
AHBottomNavigationFABBehavior.java
AHBottomNavigationItem.java
AHBottomNavigationViewPager.java
AHHelper.java
VerticalScrollingBehavior.java
...
可以实现消息角标提示等效果,如图:
第二个:外国开源https://github.com/Ashok-Varma/BottomNavigation
封装了好多东西 里面包含有角标 ,可以实现消息提示
BottomVerticalScrollBehavior.java
VerticalScrollingBehavior.java
utils文件夹中包含如下:
BadgeItem.java
BottomNavigationBar.java
BottomNavigationHelper.java
BottomNavigationItem.java
BottomNavigationTab.java
FixedBottomNavigationTab.java
ShapeBadgeItem.java2.0.1 released
ShiftingBottomNavigationTab.java
TextBadgeItem.java
效果图:
第三个:外国开源
https://github.com/armcha/LuseenBottomNavigation
实现效果跟官方的类似
包含文件:
..
BottomNavigationItem.java
BottomNavigationUtils.java
BottomNavigationView.java
OnBottomNavigationItemClickListener.java
实现效果与官方类似,这里不贴图。
主要说一下第一个开源实现案例 自定义ViewPager+底部导航栏AHBottomNavigation+自定义Fragment实现
首先引入依赖
compile 'com.aurelhubert:ahbottomnavigation:2.1.0'
compile 'com.android.support:design:25+'
注意:如果想实现如图所示的效果,需要在页面中添加一个上下滑动的列表,如果不是RecyclerView,没有上下联动效果,
如果想自己实现,可以继承CoordinatorLayout.Behavior<V> ,重写必要的方法实现
RecyclerView对应的适配器 MyAdapter代码如下:
package com.createfuture.android.aurelhubertahbottomnavigation; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.ArrayList; /** * RecyclerView列表适配器 */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { //集合 private ArrayList<String> mDataset = new ArrayList<>(); //数据入口 public MyAdapter(ArrayList<String> dataset) { mDataset.clear(); mDataset.addAll(dataset); } /** * 创建视图 * * @param parent * @param viewType * @return */ @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item_demo, parent, false); ViewHolder vh = new ViewHolder(v); return vh; } /** * 绑定数据到 TextView * * @param holder * @param position */ @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.mTextView.setText(mDataset.get(position)); } /** * 获取集合大小 * * @return */ @Override public int getItemCount() { return mDataset.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public ViewHolder(View v) { super(v); mTextView = (TextView) v.findViewById(R.id.layout_item_demo_title); } } }
列表子视图layout_item_demo.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="200dp" android:orientation="vertical" android:layout_margin="8dp"> <TextView android:id="@+id/layout_item_demo_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:padding="16dp" android:textColor="#212121" android:textSize="18sp" /> </RelativeLayout>
自定义一个Fragment 起名为TestFragment 对应布局文件(fragment_demo_list.xml)如下:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/fragment_container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/fragment_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
TestFragment文件内容:
package com.createfuture.android.aurelhubertahbottomnavigation; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; /** * Created by GuoBin on 2017/12/23. */ public class TestFragment extends Fragment { //RecyclerView private RecyclerView recyclerView; //RecyclerView.LayoutManager private RecyclerView.LayoutManager layoutManager; //静态常量标识 private final static String KEY = TestFragment.class.getSimpleName(); //列表适配器 private MyAdapter mAdapter; /** * 获得带有数据的TestFragment实类 * @param content * @return */ public static Fragment getInstance(String content) { /** * 实例化当前Fragment 并初始化Bundle 保存数据到Fragment,用于Fragment界面文本展示 */ TestFragment fragment = new TestFragment(); Bundle bundle = new Bundle(); bundle.putString(KEY, content); fragment.setArguments(bundle); return fragment; } //加载布局 @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_demo_list, container, false); initDemoList(view); return view; } private void initDemoList(View view) { recyclerView = (RecyclerView) view.findViewById(R.id.fragment_recycler_view); layoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(layoutManager); //初始化数据 ArrayList<String> itemsData = new ArrayList<>(); for (int i = 0; i < 50; i++) { itemsData.add("Fragment " + getArguments().get(KEY)); } mAdapter = new MyAdapter(itemsData); recyclerView.setAdapter(mAdapter); } }
MainActivity对应的布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.aurelhubert.ahbottomnavigation.AHBottomNavigationViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="wrap_content"/> <android.support.design.widget.FloatingActionButton android:id="@+id/floating_action_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|bottom" android:layout_marginBottom="88dp" android:src="@mipmap/ic_content_add" app:useCompatPadding="true"/> <com.aurelhubert.ahbottomnavigation.AHBottomNavigation android:id="@+id/bottom_navigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" app:selectedBackgroundVisible="false"/> </android.support.design.widget.CoordinatorLayout>
MainActivity对应的代码如下:
package com.createfuture.android.aurelhubertahbottomnavigation; import android.animation.Animator; import android.graphics.Color; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.animation.OvershootInterpolator; import com.aurelhubert.ahbottomnavigation.AHBottomNavigation; import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem; import com.aurelhubert.ahbottomnavigation.AHBottomNavigationViewPager; import com.aurelhubert.ahbottomnavigation.notification.AHNotification; import java.util.ArrayList; import java.util.List; /** * CoordinatorLayout+底部导航栏+自定义A HBottomNavigationViewPager+Fragment * 实现如图效果 */ public class MainActivity extends AppCompatActivity implements AHBottomNavigation.OnTabSelectedListener{ //UI元素 private AHBottomNavigationViewPager viewPager;//自定义ViewPager private AHBottomNavigation bottomNavigation;//底部导航栏 private FloatingActionButton floatingActionButton;//悬浮按钮 //Fragment集合 private List<Fragment> myFragment=new ArrayList<>(); //底部导航栏标题 private String[] mTiltls = new String[]{"Menu1", "Menu2", "Menu3", "Menu4", "Menu5"}; //底部导航栏子项集合 private ArrayList<AHBottomNavigationItem> bottomNavigationItems = new ArrayList<>(); //消息通知 private AHNotification notification; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); initListener(); } //初始化控件 private void initView() { bottomNavigation = (AHBottomNavigation) findViewById(R.id.bottom_navigation); //选中的图标着色以及文本的颜色 bottomNavigation.setAccentColor(Color.RED); //没有选中的图标着色以及文本的颜色 bottomNavigation.setInactiveColor(Color.BLACK); //去除隐藏标题的状态 bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW); viewPager = (AHBottomNavigationViewPager) findViewById(R.id.view_pager); viewPager.setPagingEnabled(false);//禁止滑动 floatingActionButton = (FloatingActionButton) findViewById(R.id.floating_action_button); //管理Floating的显示行为 bottomNavigation.manageFloatingActionButtonBehavior(floatingActionButton); //交互行为可用 // bottomNavigation.setBehaviorTranslationEnabled(true); } //初始化数据 private void initData() { /** * 为导航栏添加带图标的文字 */ AHBottomNavigationItem item1 = new AHBottomNavigationItem(mTiltls[0], R.mipmap.ic_maps_place, Color.YELLOW); AHBottomNavigationItem item2 = new AHBottomNavigationItem(mTiltls[1], R.mipmap.ic_maps_local_bar, Color.YELLOW); AHBottomNavigationItem item3 = new AHBottomNavigationItem(mTiltls[2], R.mipmap.ic_maps_local_restaurant, Color.YELLOW); AHBottomNavigationItem item4 = new AHBottomNavigationItem(mTiltls[3], R.mipmap.ic_book_white_24dp, Color.YELLOW); AHBottomNavigationItem item5 = new AHBottomNavigationItem(mTiltls[4], R.mipmap.ic_github_circle_white_24dp, Color.YELLOW); bottomNavigationItems.add(item1); bottomNavigationItems.add(item2); bottomNavigationItems.add(item3); bottomNavigationItems.add(item4); bottomNavigationItems.add(item5); bottomNavigation.addItems(bottomNavigationItems); //初始化消息提示 notification=new AHNotification.Builder() .setText("3") .setTextColor(Color.WHITE) .setBackgroundColor(Color.RED) .build(); //为最后一个加消息提示 bottomNavigation.setNotification(notification,4); //添加Viewpager中Fragment集合 for (int i = 0; i < mTiltls.length; i++) { if (i != 4) { myFragment.add(TestFragment.getInstance(mTiltls[i].toString())); }else { myFragment.add(TestFragment.getInstance("")); } } //ViewPager绑定适配器 viewPager.setAdapter(new CustomPagerAdapter(getSupportFragmentManager())); } //初始化监听 private void initListener() { bottomNavigation.setOnTabSelectedListener(this); } /** * tab 选中的效果 * @param position int: Position of the selected tab * @param wasSelected boolean: true if the tab was already selected * @return */ @Override public boolean onTabSelected(int position, boolean wasSelected) { viewPager.setCurrentItem(position, false); if (position == 1) { bottomNavigation.setNotification("1", 1); floatingActionButton.setVisibility(View.VISIBLE); floatingActionButton.setAlpha(0f); floatingActionButton.setScaleX(0f); floatingActionButton.setScaleY(0f); floatingActionButton.animate() .alpha(1) .scaleX(1) .scaleY(1) .setDuration(300) .setInterpolator(new OvershootInterpolator()) .setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { floatingActionButton.animate() .setInterpolator(new LinearOutSlowInInterpolator()) .start(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }) .start(); } else { if (floatingActionButton.getVisibility() == View.VISIBLE) { floatingActionButton.animate() .alpha(0) .scaleX(0) .scaleY(0) .setDuration(300) .setInterpolator(new LinearOutSlowInInterpolator()) .setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { floatingActionButton.setVisibility(View.GONE); } @Override public void onAnimationCancel(Animator animation) { floatingActionButton.setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animator animation) { } }) .start(); } } return true; } //ViewPager Adapter 真正开发 记得要新建一个类,尽可能的少用内部类 private class CustomPagerAdapter extends FragmentPagerAdapter { public CustomPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return myFragment == null ? null : myFragment.get(position); } @Override public int getCount() { return myFragment.size() == 0 ? 0 : myFragment.size(); } } }
代码注释已经很清楚了,不做太多重复解释。
除了上面显示的底部导航栏效果,还有一种也是较为常见的,先上图:
感兴趣可以到Github,传送门:https://github.com/armcha/Space-Navigation-View
来源:CSDN
作者:AlanMaya
链接:https://blog.csdn.net/Seeing_is_believing/article/details/78943186