部分可见的侧边菜单与交叉渐变效果的SlidingPaneLayout

部分可见的侧边菜单与交叉渐变效果的SlidingPaneLayout


Gmail的平板版本有一个特色的功能:

gmail.gif

侧边菜单面板总是可见的,当关闭的时候只显示图标,当打开的时候会显示更详细的内容,并且两个内容切换的时候有个交叉渐变效果,是如何实现的呢?

我观察到主面板是在侧边面板打开的时候滑动的,因此应该不是用的NavigationDrawer,那我们试试SlidingPaneLayout如何。

SlidingPaneLayout

 
 
  1. <android.support.v4.widget.SlidingPaneLayout
  2.     xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:id="@+id/sliding_pane_layout"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent">
  6.   <TextView
  7.       android:layout_width="240dp"
  8.       android:layout_height="match_parent"
  9.       android:background="@color/blue"
  10.       android:text="@string/pane_1"/>
  11.   <TextView
  12.       android:layout_width="400dp"
  13.       android:layout_height="match_parent"
  14.       android:layout_weight="1"
  15.       android:background="@color/light_blue"
  16.       android:text="@string/pane_2"/>
  17. </android.support.v4.widget.SlidingPaneLayout>

two_pane_gray.gif

看起来还不错,不过主面板会变灰,幸运的是我们可以通过setSliderFadeColor将渐变色设置为透明。

 
 
  1. SlidingPaneLayout layout = (SlidingPaneLayout) 
  2.     findViewById(R.id.sliding_pane_layout);
  3. layout.setSliderFadeColor(Color.TRANSPARENT);

two_pane.gif

部分展开的侧边

现在我想让侧边部分在关闭的时候是部分可见的,一开始摸不着头脑,但是一旦下手去做发现其实挺简单的:为主面板加一个margin(left)就可以了。

 
 
  1. <android.support.v4.widget.SlidingPaneLayout
  2.     xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:id="@+id/sliding_pane_layout"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent">
  6.   <TextView
  7.       android:layout_width="240dp"
  8.       android:layout_height="match_parent"
  9.       android:background="@color/blue"
  10.       android:text="@string/pane_1"/>
  11.   <TextView
  12.       android:layout_width="400dp"
  13.       android:layout_height="match_parent"
  14.       android:layout_weight="1"
  15.       android:layout_marginLeft="64dp"
  16.       android:background="@color/light_blue"
  17.       android:text="@string/pane_2"/>
  18. </android.support.v4.widget.SlidingPaneLayout>

With the margin, the side pane peeks from below when collapsed.

交叉渐变

 最后是交叉渐变效果的实现。我将侧边部分换成了FrameLayout(使用FrameLayout类是为了让部分侧边内容和完全展示内容重合在一起),FrameLayout下面的TextView是主面板。

 
 
  1. <com.sqisland.android.CrossFadeSlidingPaneLayout
  2.     xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:id="@+id/sliding_pane_layout"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent">
  6.   <FrameLayout
  7.       android:layout_width="240dp"
  8.       android:layout_height="match_parent"
  9.       android:background="@color/purple">
  10.     <TextView
  11.         android:layout_width="match_parent"
  12.         android:layout_height="match_parent"
  13.         android:text="@string/full"/>
  14.     <TextView
  15.         android:layout_width="64dp"
  16.         android:layout_height="match_parent"
  17.         android:background="@color/blue"
  18.         android:text="@string/partial"/>
  19.   </FrameLayout>
  20.   <TextView
  21.       android:layout_width="400dp"
  22.       android:layout_height="match_parent"
  23.       android:layout_weight="1"
  24.       android:layout_marginLeft="64dp"
  25.       android:background="@color/light_blue"
  26.       android:text="@string/pane_2"/>
  27. </com.sqisland.android.CrossFadeSlidingPaneLayout>

然后我写了一个SlidingPaneLayout的子类以实现侧边栏在部分显示与完全显示之间的交叉渐变效果,为此,我首先的获取到这两部分。

 
 
  1. @Override
  2. protected void onFinishInflate() {
  3.   super.onFinishInflate();
  4.  
  5.   if (getChildCount() < 1) {
  6.     return;
  7.   }
  8.  
  9.   View panel = getChildAt(0);
  10.   if (!(panel instanceof ViewGroup)) {
  11.     return;
  12.   }
  13.  
  14.   ViewGroup viewGroup = (ViewGroup) panel;
  15.   if (viewGroup.getChildCount() != 2) {
  16.     return;
  17.   }
  18.   fullView = viewGroup.getChildAt(0);
  19.   partialView = viewGroup.getChildAt(1);
  20.  
  21.   super.setPanelSlideListener(crossFadeListener);
  22. }

 SlidingPaneLayout的第一个子view是侧边,侧边的第一个子view是完整内容的侧边,第二个子view是部分显示的侧边,它们在这里分别是fullView 和 partialView。然后利用SlidingPaneLayout的listener来根据偏移距离设置两部分的透明度。

 
 
  1. private SimplePanelSlideListener crossFadeListener 
  2.     = new SimplePanelSlideListener() {
  3.   @Override
  4.   public void onPanelSlide(View panel, float slideOffset) {
  5.     super.onPanelSlide(panel, slideOffset);
  6.     if (partialView == null || fullView == null) {
  7.       return;
  8.     }
  9.  
  10.     partialView.setVisibility(isOpen() ? View.GONE : VISIBLE);
  11.     partialView.setAlpha(1 - slideOffset);
  12.     fullView.setAlpha(slideOffset);
  13.   }
  14. };

因为我不想在展开的时候部分显示的侧边内容区域响应触摸事件,因此在展开的时候将它设置为不可见。注意在平板上可能初始状态也是展开的,所以需要在onLayout中也判断一下,然后设置可见状态。

 
 
  1. @Override
  2. protected void onLayout(
  3.     boolean changed, int l, int t, int r, int b) {
  4.   super.onLayout(changed, l, t, r, b);
  5.  
  6.   if (partialView != null) {
  7.     partialView.setVisibility(isOpen() ? View.GONE : VISIBLE);
  8.   }
  9. }

cross_fade.gif

这就是gmail的那种效果了。

源码: https://github.com/chiuki/sliding-pane-layout


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值