android 流行布局,Android流行UI布局——底部导航(BottomNavigationView+ViewPager+Fragment)...

前言:

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

这篇文章为大家带来

1.官方BottomNavigationView的使用方法

2.结合ViewPager、Fragment实现一个流行UI布局!

3.并用反射解决ViewPager与BottomNavigationView侧滑联动时的一个小问题。

最终实现效果:

0ba25cc65889?mType=Group

BottomNavigationView.gif

在谷歌官方发布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菜单,多少个自己看着办吧:

android:id="@+id/item_news"

android:icon="@mipmap/ic_news_gray"

android:title="新闻" />

android:id="@+id/item_lib"

android:icon="@mipmap/ic_library_gray"

android:title="图书" />

android:id="@+id/item_find"

android:icon="@mipmap/ic_discovery_gray"

android:title="发现" />

android:id="@+id/item_more"

android:icon="@mipmap/ic_more_gray"

android:title="更多" />

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

android:id="@+id/viewpager"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_above="@+id/bottom_navigation" />

android:id="@+id/bottom_navigation"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

app:itemIconTint="@drawable/bottom_navigation_selector"

app:itemTextColor="@drawable/bottom_navigation_selector"

app:menu="@menu/menu_bottom_navigation" />

android:layout_width="match_parent"

android:layout_height="5dp"

android:layout_above="@id/bottom_navigation"

android:background="@drawable/bottom_shadow" />

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可以实现流行的布局框架,可以像微信那样左右滑动,也可以像支付宝那样点击切换。

0ba25cc65889?mType=Group

截图20161211104920.png

细心的朋友可能发现了,上面的代码为什么用了反射呢?

原因就是官方的BottomNavigationView默认有个放大的ShiftingMode效果,但是尚未支持代码层级的切换。在3个menu item及以下时默认关闭,而到了4个及以上时就懵逼了,因为我们是要做ViewPager的侧滑啊!

0ba25cc65889?mType=Group

20161211105617.png

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

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

0ba25cc65889?mType=Group

mShiftingMode.png

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;

}

});

最后来看下效果:

0ba25cc65889?mType=Group

BottomNavigationView.gif

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值