Android项目中使用侧滑菜单栏功能的有很多量级很大的APP,比如QQ、OFO、Mobike等,所以该功能属于较为常见的、用户熟悉的功能,因此可以在任意的项目中使用。我之前就用开源库SlidingMenu实现过侧滑菜单栏,尽管SlidingMenu已经很久没有维护了,我还是打算用它来实现,毕竟轻车熟路能避免很多坑,同时网上的经验也能帮助我使用的更加轻松。
使用SlidingMenu开源库的第一步肯定是下载该开源库,但是不推荐直接下载该原始开源库。因为很久没有维护了,互联网发展又很迅速,该库已经有些不满足日新月异的需求,所以需要我们自己修改源代码,满足需求。
优化后的开源库下载地址(https://download.csdn.net/download/qq941263013/10551527)
注:文章末尾附项目源码下载地址(内含优化后的开源库)
1.实现沉浸式状态栏;
(方法:https://blog.csdn.net/qq941263013/article/details/81112192)
2.为侧滑剩余部分添加淡入淡出的阴影;
(方法:https://blog.csdn.net/qq941263013/article/details/81112095)
注:①关于网上说的按钮点击无效问题,亲测不存在此类问题,需要注意的是
传入的View和实现点击事件的View要使用相同的实例。
②导入报错等问题,百度解决即可,就不在这里一一赘述了。
主要展示了通过手势左滑(右滑)展示菜单栏、通过点击按钮展示左滑(右滑)菜单栏、FragmentTabHost的切换、侧滑菜单栏的点击事件(切换Fragment)、返回键关闭侧滑菜单栏、侧滑菜单栏的沉浸式效果、侧滑剩余部分的阴影效果等。
1.导入优化后的开源库SlidingMenuLibrary;
2.因为侧滑菜单栏需要实现沉浸式效果,所以首先需要SlidingMenu依赖的Activity也实现
沉浸式状态栏效果(4.4以上);在onCreate()中添加以下代码即可:
//判断当前设备版本号是否为4.4以上,如果是,则通过调用setTranslucentStatus让状态栏变透明
//透明状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
3.初始化SlidingMenu实现侧滑菜单栏,代码中的注释非常详细,在这里直说几个重要的点。
①菜单栏的呈现模式分为三种:左、右、左右;如果设置为左右模式,则必须实现setSecondaryMenu();
②setOffsetFadeDegree()实现了为侧滑剩余部分添加淡入淡出的阴影,该方法原始的开源库是没有的;
③setTouchModeBehind()实现菜单栏内部可以滑动,但是会导致菜单栏内的点击事件无效;
④attachToActivity()中的第二个入参传入WINDOW为沉浸式状态栏,而传入CONTENT为非沉浸式;
⑤setMenu()中传入的View,要与点击事件使用同一个View,否则点击事件无效;
/**
* 初始化SlidingMenu实现侧滑菜单栏
*/
private void initSlidingMenu() {
slidingMenu = new SlidingMenu(this);
//设置呈现模式(分为左、右、左右三种)
slidingMenu.setMode(SlidingMenu.LEFT_RIGHT);
//设置侧滑界面偏移出的尺寸(剩余部分)
slidingMenu.setBehindOffset(DensityUtil.dip2px(100, context));
//设置剩余部分的阴影
slidingMenu.setOffsetFadeDegree(0.4f);
//设置全屏都可以触摸
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
//设置菜单内可以滑动(会导致菜单内的点击事件无效)
// slidingMenu.setTouchModeBehind(SlidingMenu.TOUCHMODE_FULLSCREEN);
//添加到当前Activity当中
//(SLIDING_WINDOW配合沉浸式状态栏,SLIDING_CONTENT配合非沉浸式状态栏)
slidingMenu.attachToActivity(this, SlidingMenu.SLIDING_WINDOW);
//给侧滑界面传入View,与点击事件使用同一个View
//如果给侧滑界面引用一个布局资源作为所展示的界面,点击事件无效,
//因为侧滑界面和点击事件是不同的View
View view = View.inflate(context, R.layout.my_sliding_menu, null);
slidingMenu.setMenu(view);
slidingMenu.setSecondaryMenu(R.layout.my_sliding_menu_right);
initSlidingMenuButton(view);
//openListener仅在侧滑菜单栏开启的时候调用;
//openedListener在侧滑菜单栏开启后调用(open之后);
// 并且在滑动且未关闭的时候再次调用。
// (也就是滑动未关闭然后又回到开启的状态时再次调用)
slidingMenu.setOnOpenedListener(new SlidingMenu.OnOpenedListener() {
@Override
public void onOpened() {
slidingMenuToggleStatus = true;
}
});
//closeListener仅在侧滑菜单栏开启的时候调用;
//closedListener在侧滑菜单栏开启后调用(close之后);
// 并且在滑动且未关闭的时候再次调用。
// (也就是滑动未关闭然后又回到开启的状态时再次调用)
slidingMenu.setOnClosedListener(new SlidingMenu.OnClosedListener() {
@Override
public void onClosed() {
slidingMenuToggleStatus = false;
}
});
}
4.初始化侧滑菜单栏中按钮的点击事件:
通过setCurrentTab()实现Fragment的切换,通过toggle()实现菜单栏的开启与关闭;
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.ll_home://首页
tabHost.setCurrentTab(0);
slidingMenu.toggle();
break;
case R.id.ll_order://订单
tabHost.setCurrentTab(1);
slidingMenu.toggle();
break;
case R.id.ll_statistic://统计
tabHost.setCurrentTab(2);
slidingMenu.toggle();
break;
case R.id.ll_refresh://检查更新
ToastUtil.makeText(context,"点击了检查更新");
slidingMenu.toggle();
break;
case R.id.ll_logout://切换用户/注销
ToastUtil.makeText(context,"点击了切换用户/注销");
slidingMenu.toggle();
break;
default:
break;
}
}
5.返回键关闭处于开启状态的菜单栏:
首先通过3中的SlidingMenu开启、关闭的监听,时时改变状态,然后通过状态判断是否处于开启状态,
如果是开启状态,就关闭SlidingMenu,再执行退出程序的操作。时间的判断可以防止频繁点击返回键,
导致菜单栏一直处于滑动状态的问题,看需求吧,可以不管它也挺好玩的。
private long mExitTime;
private long mSlidingMenuTime;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//防止频繁点击返回键,导致侧滑一直在滑动状态
//可以放弃时间的判断,当成个小玩意
if (slidingMenuToggleStatus == true) {
if ((System.currentTimeMillis() - mSlidingMenuTime) > 1000){
mSlidingMenuTime = System.currentTimeMillis();
slidingMenu.toggle();
}
return true;
}
if ((System.currentTimeMillis() - mExitTime) > 2000) {
ToastUtil.makeText(context, "再按一次退出程序");
mExitTime = System.currentTimeMillis();
} else {
//模拟Home键操作
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
}
return true;
}
//拦截MENU按钮点击事件,让它无任何操作
if (keyCode == KeyEvent.KEYCODE_MENU) {
return true;
}
return super.onKeyDown(keyCode, event);
}
6.在Fragment中开启侧滑菜单栏:
showMenu()开启左侧滑菜单栏,showSecondaryMenu()开启右侧滑菜单栏
@OnClick({R.id.iv_titlebar_left, R.id.iv_titlebar_right})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.iv_titlebar_left://左侧滑菜单栏
if (MainActivity.slidingMenu != null) {
MainActivity.slidingMenu.showMenu();
}
break;
case R.id.iv_titlebar_right://右侧滑菜单栏
if (MainActivity.slidingMenu != null) {
MainActivity.slidingMenu.showSecondaryMenu();
}
break;
}
}
1.页面布局:主要通过FragmentTabHost+FrameLayout实现底部导航栏,用View当做分割线。
2.初始化FragmentTabHost
/**
* 初始化FragmentTabHost
*/
private void initFragmentTabHost() {
//初始化tabHost
FragmentTabHost tabHost = (FragmentTabHost) findViewById(R.id.tabHost);
//将tabHost和FragmentLayout关联
tabHost.setup(context, getSupportFragmentManager(), R.id.fl_content);
//去掉分割线
if (Build.VERSION.SDK_INT > 10) {
tabHost.getTabWidget().setShowDividers(0);
}
//添加tab和其对应的fragment
MainTabs[] tabs = MainTabs.values();
for (int i = 0; i < tabs.length; i++) {
MainTabs mainTabs = tabs[i];
TabHost.TabSpec tabSpec = tabHost.newTabSpec(mainTabs.getName());
View indicator = View.inflate(context, R.layout.tab_indicator, null);
TextView tv_indicator = (TextView) indicator.findViewById(R.id.tv_indicator);
Drawable drawable = context.getResources().getDrawable(mainTabs.getIcon());
tv_indicator.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
tv_indicator.setText(mainTabs.getName());
tabSpec.setIndicator(indicator);
tabHost.addTab(tabSpec, mainTabs.getCla(), null);
}
}
以上就是侧滑菜单栏功能的实现过程了,其它具体的实现细节,文章末尾的源码中都有详细的注解,在这里就不一一赘述了。本博客主要是对SlidingMenu的使用做了比较详细的讲解,关于FragmentTabHost的部分比较粗糙,并不是懒呦,而是因为FragmentTabHost的知识点也有很多,将会在下一篇的博客中做成详细的讲解和demo,届时也会将博客地址添加到本博客中。
项目源码下载地址(https://download.csdn.net/download/qq941263013/10551541)
GitHub项目地址(https://github.com/wangyang0313/SlidingMenuBestImplementation)
优化后的开源库地址(https://download.csdn.net/download/qq941263013/10551527)
---------------------------------------------------------------------------------------------------------------------------
早计划,早准备,早完成。 欢迎关注!交流!Star!
GitHub:https://github.com/wangyang0313
微信公众号:一个灵活的胖子MrWang
简书:https://www.jianshu.com/u/e5e733d79b96