http://www.jianshu.com/p/0ba25cc65889

前言:
Android端采用底部导航栏的APP非常多,比如微信、微博、支付宝...等等,这也不能说是盲目学习iOS,毕竟好东西大家都可以用,各家操作系统也都在博采众长,互相学习。Android端的底部导航栏有着一套规范,详情。

这篇文章为大家带来
1.官方BottomNavigationView的使用方法
2.结合ViewPager、Fragment实现一个流行UI布局!
3.并用反射解决ViewPager与BottomNavigationView侧滑联动时的一个小问题。

最终实现效果:

Android流行UI布局——底部导航(BottomNavigationView+ViewPager+Fragment)_第1张图片

在谷歌官方发布BottomNavigationView控件之前我们可以自己组合控件实现,比如LinearLayout + TextView(使用android:drawableTop属性+selector状态切换)、RadioGroup + RadioButton等等组合控件的方法自定义实现复杂效果。除了第三方外,现在我们多了一个选择。

开始
1.新建project然后导入以下support:design library,BottomNavigationView就在这个design库中。顺带导入这个V4包,因为待会要使用到ViewPager(这里其实不用记这么麻烦的库跟版本怎么写,直接在AS 的design面板把控件拖进来就会自动导入了。)

compile'com.android.support:design:25.0.1'compile'com.android.support:support-v4:25.0.1'

2.在res下新建menu文件夹,新建一个menu菜单,多少个自己看着办吧:

<?xml version="1.0" encoding="utf-8"?>                

3.接着是布局文件主要代码如下(最下面的View效果是加一个阴影):


app:itemIconTint="@drawable/bottom_navigation_selector" 为icon着色,写个selector即可。
app:itemTextColor="@drawable/bottom_navigation_selector"该属性为文字着色,同样写个selector实现点击颜色切换的效果。

4.写完布局写代码,完整activity文件如下:
实例化控件后为NavigationView添加监听事件即可,代码如下:

package com.fedming.bottomnavigationdemo;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.design.widget.BottomNavigationView;import android.support.v4.view.ViewPager;import android.support.v7.app.AppCompatActivity;import android.view.MenuItem;/** * Created by bruce on 2016/11/1. * HomeActivity 主界面 */public class HomeActivity extends AppCompatActivity {    private ViewPager viewPager;    private MenuItem menuItem;    private BottomNavigationView bottomNavigationView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_home);        viewPager = (ViewPager) findViewById(R.id.viewpager);        bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);        //默认 >3 的选中效果会影响ViewPager的滑动切换时的效果,故利用反射去掉        BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);        bottomNavigationView.setOnNavigationItemSelectedListener(                new BottomNavigationView.OnNavigationItemSelectedListener() {                    @Override                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {                        switch (item.getItemId()) {                            case R.id.item_news:                                viewPager.setCurrentItem(0);                                break;                            case R.id.item_lib:                                viewPager.setCurrentItem(1);                                break;                            case R.id.item_find:                                viewPager.setCurrentItem(2);                                break;                            case R.id.item_more:                                viewPager.setCurrentItem(3);                                break;                        }                        return false;                    }                });        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            }            @Override            public void onPageSelected(int position) {                if (menuItem != null) {                    menuItem.setChecked(false);                } else {                    bottomNavigationView.getMenu().getItem(0).setChecked(false);                }                menuItem = bottomNavigationView.getMenu().getItem(position);                menuItem.setChecked(true);            }            @Override            public void onPageScrollStateChanged(int state) {            }        });        //禁止ViewPager滑动//        viewPager.setOnTouchListener(new View.OnTouchListener() {//            @Override//            public boolean onTouch(View v, MotionEvent event) {//                return true;//            }//        });        setupViewPager(viewPager);    }    private void setupViewPager(ViewPager viewPager) {        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());        adapter.addFragment(BaseFragment.newInstance("新闻"));        adapter.addFragment(BaseFragment.newInstance("图书"));        adapter.addFragment(BaseFragment.newInstance("发现"));        adapter.addFragment(BaseFragment.newInstance("更多"));        viewPager.setAdapter(adapter);    }}

可以看到BottomNavigationView+ViewPager+Fragment可以实现流行的布局框架,可以像微信那样左右滑动,也可以像支付宝那样点击切换。

Android流行UI布局——底部导航(BottomNavigationView+ViewPager+Fragment)_第2张图片

细心的朋友可能发现了,上面的代码为什么用了反射呢?
原因就是官方的BottomNavigationView默认有个放大的ShiftingMode效果,但是尚未支持代码层级的切换。在3个menu item及以下时默认关闭,而到了4个及以上时就懵逼了,因为我们是要做ViewPager的侧滑啊!

Android流行UI布局——底部导航(BottomNavigationView+ViewPager+Fragment)_第3张图片

滑动时,ViewPager是切换过去了,下面这item也切换过去了,但是你说说这效果是不是坑爹!!?

没办法了,查了一圈资料,发现官方这个控件还不支持代码层级的切换选项(如果你发现了,请告诉我)。迫不得已,只能看源码,开启上帝(反射)模式了!

Android流行UI布局——底部导航(BottomNavigationView+ViewPager+Fragment)_第4张图片

public class BottomNavigationViewHelper {    public static void disableShiftMode(BottomNavigationView navigationView) {        BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigationView.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 itemView = (BottomNavigationItemView) menuView.getChildAt(i);                itemView.setShiftingMode(false);                itemView.setChecked(itemView.getItemData().isChecked());            }        } catch (NoSuchFieldException | IllegalAccessException e) {            e.printStackTrace();        }    }}

我们通过反射拿到了BottomNavigationMenuView,至于为什么是BottomNavigationView 的第一个子View这就要看源码了,AS中直接可以点进去看。然后我们知道了这个效果是由mShiftingMode来决定的,那么上面的代码就好理解了。

在实例化BottomNavigationView后调用一次这行代码即可:

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

如果不需要配置侧滑切换的话,直接默认效果就好,不要去反射修改了。禁止滑动时,为ViewPager添加setOnTouchListener接口,在onTouch下直接消费掉点击事件。添加下面这段代码:

//禁止ViewPager滑动viewPager.setOnTouchListener(new View.OnTouchListener() {    @Override    public boolean onTouch(View v, MotionEvent event) {        return true;    }});

最后来看下效果:

Android流行UI布局——底部导航(BottomNavigationView+ViewPager+Fragment)_第5张图片

大功告成!附上源码:这里。希望能跟大家成为点赞之交,哈哈。

更多相关文章

  1. 自定义ProgressDialog(无遮罩效果)
  2. 美团,大众点评,悬浮窗功能代码
  3. android下使用Fragment实现左侧3级菜单+动画效果
  4. Android 第一行代码
  5. 转:android 图片叠加效果——两种方法
  6. 动态广告布局
  7. Android自定义添加圆角渐变色按钮+点击效果

随机推荐

  1. Android中ListView中Item的设置
  2. Android(安卓)SDK版本更新
  3. 修改系统Android版本,版本号
  4. 系出名门Android(8) - 控件(View)之TextS
  5. Android也有beacon了
  6. android adb工具
  7. Android微信界面
  8. 关于Chromium的Android(安卓)Studio使用
  9. android图像处理系统1.3
  10. How To Open An URL In Android’s Web B