使用前打开build.gradle 添加依赖
//可以修改为你项目中对应的版本号 建议修改与 compile 'com.android.support:appcompat-v7:25.0.0' 相同的版本号MainActivity XML定义如下:
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; } }
封装了好多东西 里面包含有角标 ,可以实现消息提示
效果图:
实现效果与官方类似,这里不贴图。
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); } } }
<?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>
<?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>
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); } }
<?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>
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(); } } }
代码注释已经很清楚了,不做太多重复解释。