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

这篇文章为大家带来

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

最终实现效果:

这里写图片描述

在谷歌官方发布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"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/action_home"
        android:title="首页"
        android:icon="@drawable/home_selected"/>

    <item
        android:id="@+id/action_explore"
        android:title="直播"
        android:icon="@drawable/live"/>

    <item
        android:id="@+id/action_me"
        android:title="关注"
        android:icon="@drawable/follow"/>
    <item
        android:id="@+id/mfaxin"
        android:title="发现"
        android:icon="@drawable/video"/>
    <item
        android:id="@+id/mi"
        android:title="我的"
        android:icon="@drawable/user"/>
</menu>

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

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.example.myzg2.myapplication.MainActivity"
    android:weightSum="1">



    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="151dp"
        android:layout_above="@+id/bottom_navigation" />

    <android.support.design.widget.BottomNavigationView
        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" />

    <View
        android:layout_width="match_parent"
        android:layout_height="0.1dp"
        android:layout_above="@id/bottom_navigation"
        android:background="#808080" />
</RelativeLayout>

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

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

package com.example.myzg2.myapplication;

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;
import android.view.MotionEvent;
import android.view.View;

public class MainActivity extends AppCompatActivity {
    private ViewPager viewPager;
    private MenuItem menuItem;
    private BottomNavigationView bottomNavigationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        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.action_home:
                        viewPager.setCurrentItem(0);
                        break;
                    case R.id.action_explore:
                        viewPager.setCurrentItem(1);
                        break;
                   case R.id.action_me:
                        viewPager.setCurrentItem(2);
                        break;
                    case R.id.mfaxin:
                        viewPager.setCurrentItem(3);
                        break;
                    case R.id.mi:
                        viewPager.setCurrentItem(4);
                        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("发现"));
        adapter.addFragment(BaseFragment.newInstance("我的s"));
        viewPager.setAdapter(adapter);
    }
}



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

禁止ViewPager滑动

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

viewPager.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return true;
    }
});

滑动时,ViewPager是切换过去了,下面这item也切换过去了,这种动画效果不需要时,创建一个BottomNavigationViewHelper

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();
        }
    }
}

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

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

BaseFragment.java


package com.example.myzg2.myapplication;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by bruce on 2016/11/1.
 * BaseFragment
 */

public class BaseFragment extends Fragment {
    public static BaseFragment newInstance(String info) {
        Bundle args = new Bundle();
        BaseFragment fragment = new BaseFragment();
        args.putString("info", info);
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_base, null);
       /*// TextView tvInfo = (TextView) view.findViewById(R.id.textView);
        tvInfo.setText(getArguments().getString("info"));
        tvInfo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(v, "Don't click me.please!.", Snackbar.LENGTH_SHORT).show();
            }
        });*/
        return view;
    }
}

ViewPagerAdapter.java

package com.example.myzg2.myapplication;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by bruce on 2016/11/1.
 * ViewPagerAdapter
 */

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private final List<Fragment> mFragmentList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment) {
        mFragmentList.add(fragment);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值