我们在平常使用手机时可以看到很多的App的会有侧滑菜单栏的效果,这次我将使用SlidingPaneLayout来实现这个功能。
首先我们先看下最终效果:
SlidingPaneLayout
SlidingPaneLayout提供了一个水平的、多窗格的布局。使用该控件我们可以实现侧滑的效果,其布局文件下面的第一个子控件是作为一个导航视图(也就是滑动后左边视图),其余部分是内容视图。
可以简单的尝试一下
<?xml version="1.0" encoding="utf-8"?> <androidx.slidingpanelayout.widget.SlidingPaneLayout 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:gravity="center_horizontal" tools:context=".MainActivity"> <LinearLayout android:layout_width="150dp" android:layout_height="match_parent" android:background="@color/colorPrimary" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="LeftMenu" android:textSize="20sp" android:layout_margin="10dp"/> LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="main" android:textSize="30sp" android:layout_margin="10dp"/> LinearLayout> androidx.slidingpanelayout.widget.SlidingPaneLayout>
通过上面的布局,我们可以实现一个测滑的效果
左侧栏缩放
通过下面这段代码,使得左侧栏滑动时有一个缩放的效果
SlidingPaneLayout slidingPaneLayout = findViewById(R.id.sliding_layout); //获取到左侧导航栏 mLeftView = slidingPaneLayout.getChildAt(0); slidingPaneLayout.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() { @Override public void onPanelSlide(@NonNull View panel, float slideOffset) { //滑动窗格的位置更改时调用 //设置侧面栏缩放 mLeftView.setPivotX(-mLeftView.getWidth() / 6.0f); mLeftView.setPivotY(mLeftView.getHeight() / 2.0f); mLeftView.setScaleX(0.7f + 0.3f * slideOffset); mLeftView.setScaleY(0.7f + 0.3f * slideOffset); } @Override public void onPanelOpened(@NonNull View panel) { //在滑动窗格完全打开时调用 } @Override public void onPanelClosed(@NonNull View panel) { //当滑动窗格完全关闭时调用 } }); mLeftView = slidingPaneLayout.getChildAt(0); slidingPaneLayout.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() { @Override public void onPanelSlide(@NonNull View panel, float slideOffset) { //滑动窗格的位置更改时调用 //设置侧面栏缩放 mLeftView.setPivotX(-mLeftView.getWidth() / 6.0f); mLeftView.setPivotY(mLeftView.getHeight() / 2.0f); mLeftView.setScaleX(0.7f + 0.3f * slideOffset); mLeftView.setScaleY(0.7f + 0.3f * slideOffset); } @Override public void onPanelOpened(@NonNull View panel) { //在滑动窗格完全打开时调用 } @Override public void onPanelClosed(@NonNull View panel) { //当滑动窗格完全关闭时调用 } });
在onPaneSlide中有两个参数,第一个参数是被移动的view,第二个参数则是滑动时的偏移值,范围是0~1
当我们对一个View设置缩放动画时,缩放轴点默认是该View的中心点。如果我们想改变缩放轴点位置,可以通过setPivotX(float pivotX)设置缩放轴点X轴的坐标,通过setPivotY(float pivotY)设置缩放轴点Y轴的坐标。再通过setScaleX和setScaleY来实现最终的缩放效果。
实现效果:
在SlidingPaneLayout下添加个背景颜色效果会更好些
android:background="@color/colorPrimary"
主要内容(右侧)缩放
在onPanelSlide方法下加上下面一段代码,即可实现
mMainView.setScaleX(1f - 0.3f * slideOffset); mMainView.setScaleY(1f - 0.3f * slideOffset);
还可以再给右边设置个阴影的效果
mMainView.setElevation(6.0f * slideOffset);
自定义SlidingPaneLayout
上面就是最终要实现的侧滑栏的三个最主要的内容。理解上面三个其实就可以做出一开始给的那种效果。但有些时候,可能我们不希望通过滑动来显示出左边的导航栏,而是直接通过点击一个按钮来打开左边栏。在SlidingPaneLayout中并没这样的方法来禁止它滑动,这时候我们就需要自己来自定义。
public class CusSlidingPaneLayout extends SlidingPaneLayout { //是否禁止 private boolean isForbid = false; public CusSlidingPaneLayout(@NonNull Context context) { this(context, null); } public CusSlidingPaneLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public CusSlidingPaneLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 让外面可以调用此方法来禁止滑动 * * @param isForbid */ public void forbidSlide(boolean isForbid) { this.isForbid = isForbid; } /** * 拦截触屏事件 * * @param ev * @return */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_MOVE) { if (isForbid) { return false; } } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_MOVE) { if (isForbid) { return false; } } return super.onTouchEvent(ev); } }
Demo地址
https://github.com/barry-b/SlideMenuDemo