有天在撸码的过程中不知怎么着敲出了SlidingPaneLayout这个控件,本着没见过就去百度一番了解一下的原则,发现这是官方实现的一个侧滑菜单效果的控件,可是我记得侧滑菜单不是有DrawerLayout实现了吗,怎么又来一个,而且俩都是V4包下的。而且看网上说还有利用它实现Ios右滑返回效果的,有意思,那就自己用它实现实现试试吧。
看了一下SlidingPaneLayout的使用,和DrawerLayout差不多,都是内部第一个控件作为内容,第二个控件作为菜单。
效果是这样的
用过DrawerLayout实现侧滑菜单效果的人第一眼就能看出这俩的不一样,SlidingPaneLayout的菜单是在内容下层展示的,而DrawerLayout的菜单是在内容的上层展示。这是两个控件最直观的不同之处。
一开始我还纳闷用它怎么实现Ios的右滑返回效果的,看到上面的效果后才恍然大悟,原来是这样啊~
其实利用它实现的思路并不难,甚至有点取巧的意思。因为这个控件内部分为两部分嘛,一部分是菜单,一部分是内容,并且菜单在下层,内容在上层,我们将菜单这部分设为背景透明,并将菜单宽高设为填充全屏,内容这部分就正常放要展示的东西。这样向右滑动菜单的时候,菜单部分透明显示出上一页,内容部分则滑出屏幕,再结束当前页,实现右滑返回上一页效果。
那么现在要实现这个效果就有三个点
1)菜单部分全屏
2)菜单背景透明
3)菜单打开后退出当前Activity
2.1 实现菜单部分全屏
第一个,看上面的效果图可以看出,菜单部分并没有全屏显示,内容部分还占有一小块位置。怎么解决这个问题呢,先看看源码里有没有提供方法可以修改这个边界值。
private final int mOverhangSize;
查看源码发现那个边界值是这个mOverhangSize定义的,而这个mOverhangSize被修饰为private和final,显然官方没有提供方法供我们修改这个参数。怎么办呢,反射就完事了。
private void initSlidingPane() {
SlidingPaneLayout paneLayout = new SlidingPaneLayout(this);
try {
Field overhangSize = SlidingPaneLayout.class.getDeclaredField("mOverhangSize");
overhangSize.setAccessible(true);
overhangSize.set(paneLayout,0);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//设置菜单布局
TextView MenuView = new TextView(this);
MenuView.setText("菜单");
MenuView.setTextSize(TypedValue.COMPLEX_UNIT_SP,36);
MenuView.setGravity(Gravity.CENTER);
MenuView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
paneLayout.addView(MenuView,0);
//设置内容布局
TextView contentView = new TextView(this);
contentView.setText("内容");
contentView.setTextSize(TypedValue.COMPLEX_UNIT_SP,36);
contentView.setGravity(Gravity.CENTER);
contentView.setBackgroundColor(Color.parseColor("#ffffaa"));
contentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
paneLayout.addView(contentView,1);
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
decorView.addView(paneLayout);
}
再看看效果
2.2 实现菜单背景透明
菜单全屏解决了,接下来再把菜单部分变得透明,怎么透明呢?给Activity自定义主题就完事了。
这次我加了一个界面跳转,以显示菜单透明后的上级页面。
2.3 菜单打开后退出当前Activity
ok,只剩最后一个,菜单打开后退出当前Activity,SlidingPaneLayout有一个监听菜单滑动的接口,设置上就行,问题不大。
paneLayout.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() {
@Override
public void onPanelSlide(@NonNull View view, float v) {
Log.i("test", "sliding>>>" + v);
}
@Override
public void onPanelOpened(@NonNull View view) {
Log.i("test", "sliding已打开");
finish();
}
@Override
public void onPanelClosed(@NonNull View view) {
Log.i("test", "sliding已关闭");
}
});
这个接口有三个方法,第一个方法的参数v是菜单打开的程度的数值,0为关闭,1为打开,在滑动打开的过程中从0向1变化。剩下两个方法是干嘛的就很显而易见了。
对了,记得再给Activity加上进场和退场的切换动画
fade_in
fade_out
这里我切换了两次,可以看出菜单打开的时候Activity确实退出了。这里的Activity的切换动画要说一下,因为Activity的主题用到了windowIsTranslucent这个属性,所以Activity的退场动画会受到影响,因为我这里的状态栏是透明的,所以从效果上看并没收到影响,那么对那些效果受到影响的,在退出的Activity的finish方法中加上overridePendingTransition()这个方法就好了。
到这里,一次偶尔的发现促使的仿Ios的右滑返回效果就完成啦,以前也接触过一些大牛写的仿Ios右滑返回的库,没想到Android自带的控件也能实现这样的效果,很惊喜,虽然有点取巧的意思,不过能实现的就是好方法嘛,哈哈!同时也发现Android其实有很多自带的优秀控件,能实现很多很棒的效果,其实Android也有自己的一套UI设计规范、UI交互体系,但是现在的设计知道Android的material design设计规范的太少了,全都向Ios看齐,倒想着省事,一套UI两端通用,全都照着Ios的效果来就是了,我本人其实很推崇Android自己的设计规范的,本来就是两个不同的端,结果在UI和交互上Android的特性和特色全都没有了,在这点上国内的知乎就做的比较不错,Android和Ios都是按照各自的规范来的,各有特色,区别明显,不愧是逼乎啊,最后还是希望以后像逼乎这样的例子越来越多吧。