部分可见的侧边菜单与交叉渐变效果的SlidingPaneLayout
Gmail的平板版本有一个特色的功能:
侧边菜单面板总是可见的,当关闭的时候只显示图标,当打开的时候会显示更详细的内容,并且两个内容切换的时候有个交叉渐变效果,是如何实现的呢?
我观察到主面板是在侧边面板打开的时候滑动的,因此应该不是用的NavigationDrawer
,那我们试试SlidingPaneLayout
如何。
SlidingPaneLayout
<android.support.v4.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sliding_pane_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="240dp"
android:layout_height="match_parent"
android:background="@color/blue"
android:text="@string/pane_1"/>
<TextView
android:layout_width="400dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/light_blue"
android:text="@string/pane_2"/>
</android.support.v4.widget.SlidingPaneLayout>
看起来还不错,不过主面板会变灰,幸运的是我们可以通过setSliderFadeColor将渐变色设置为透明。
SlidingPaneLayout layout = (SlidingPaneLayout)
findViewById(R.id.sliding_pane_layout);
layout.setSliderFadeColor(Color.TRANSPARENT);
部分展开的侧边
现在我想让侧边部分在关闭的时候是部分可见的,一开始摸不着头脑,但是一旦下手去做发现其实挺简单的:为主面板加一个margin(left)就可以了。
<android.support.v4.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sliding_pane_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="240dp"
android:layout_height="match_parent"
android:background="@color/blue"
android:text="@string/pane_1"/>
<TextView
android:layout_width="400dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="64dp"
android:background="@color/light_blue"
android:text="@string/pane_2"/>
</android.support.v4.widget.SlidingPaneLayout>
With the margin, the side pane peeks from below when collapsed.
交叉渐变
最后是交叉渐变效果的实现。我将侧边部分换成了FrameLayout(使用`FrameLayout`类是为了让部分侧边内容和完全展示内容重合在一起),`FrameLayout`下面的TextView是主面板。
<com.sqisland.android.CrossFadeSlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sliding_pane_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="240dp"
android:layout_height="match_parent"
android:background="@color/purple">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/full"/>
<TextView
android:layout_width="64dp"
android:layout_height="match_parent"
android:background="@color/blue"
android:text="@string/partial"/>
</FrameLayout>
<TextView
android:layout_width="400dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="64dp"
android:background="@color/light_blue"
android:text="@string/pane_2"/>
</com.sqisland.android.CrossFadeSlidingPaneLayout>
然后我写了一个SlidingPaneLayout
的子类以实现侧边栏在部分显示与完全显示之间的交叉渐变效果,为此,我首先的获取到这两部分。
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (getChildCount() < 1) {
return;
}
View panel = getChildAt(0);
if (!(panel instanceof ViewGroup)) {
return;
}
ViewGroup viewGroup = (ViewGroup) panel;
if (viewGroup.getChildCount() != 2) {
return;
}
fullView = viewGroup.getChildAt(0);
partialView = viewGroup.getChildAt(1);
super.setPanelSlideListener(crossFadeListener);
}
SlidingPaneLayout
的第一个子view是侧边,侧边的第一个子view是完整内容的侧边,第二个子view是部分显示的侧边,它们在这里分别是fullView 和 partialView。然后利用SlidingPaneLayout
的listener来根据偏移距离设置两部分的透明度。
private SimplePanelSlideListener crossFadeListener
= new SimplePanelSlideListener() {
@Override
public void onPanelSlide(View panel, float slideOffset) {
super.onPanelSlide(panel, slideOffset);
if (partialView == null || fullView == null) {
return;
}
partialView.setVisibility(isOpen() ? View.GONE : VISIBLE);
partialView.setAlpha(1 - slideOffset);
fullView.setAlpha(slideOffset);
}
};
因为我不想在展开的时候部分显示的侧边内容区域响应触摸事件,因此在展开的时候将它设置为不可见。
注意在平板上可能初始状态也是展开的,所以需要在onLayout中也判断一下,然后设置可见状态。
@Override
protected void onLayout(
boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (partialView != null) {
partialView.setVisibility(isOpen() ? View.GONE : VISIBLE);
}
}
这就是gmail的那种效果了。