实现滑动渐变的导航栏

最近在优化超模故事及新物页面的显示,需要实现导航的滑动渐变,先看下效果图

导航栏从透明色变成了白色,不知道大家有没有发现,返回按钮和分享按钮也有变色,在滑动到临界点后变成了灰色,主要是因为我们的导航栏是白色的原因,如果导航为其他颜色,返回按钮和分享按钮就不需要改变,直接改变Toolbar的背景就可以了

所以这里我们需要自定义一个导航栏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
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="wrap_content"
android:background="@drawable/shape_toolbar_vogue"
android:gravity="center"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rl_top_vogue"
android:layout_width="match_parent"
android:layout_height="@dimen/actionbar_height">
<FrameLayout
android:id="@+id/fl_back"
android:layout_width="@dimen/actionbar_height"
android:layout_height="@dimen/actionbar_height"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackgroundBorderless">
<ImageView
android:id="@+id/iv_back"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:background="@drawable/ic_arrow_left_w"/>
</FrameLayout>
<FrameLayout
android:id="@+id/fl_share"
android:layout_width="@dimen/actionbar_height"
android:layout_height="@dimen/actionbar_height"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackgroundBorderless">
<ImageView
android:id="@+id/iv_share"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:background="@drawable/ic_share"/>
</FrameLayout>
</RelativeLayout>
</android.support.design.widget.AppBarLayout>

那怎样监测滑动的距离呢,很简单,重写ScrollView的onScrollChanged方法就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class NestedScrollViewX extends NestedScrollView {
private OnScrollViewListener mOnScrollViewListener;
public NestedScrollViewX(Context context) {
super(context);
}
public NestedScrollViewX(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NestedScrollViewX(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public interface OnScrollViewListener {
void onScrollChanged(NestedScrollViewX v, int l, int t, int oldl, int oldt);
}
public void setOnScrollViewListener(OnScrollViewListener l) {
this.mOnScrollViewListener = l;
}
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
mOnScrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
super.onScrollChanged(l, t, oldl, oldt);
}
}

之后对其进行监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
final ColorDrawable cd = new ColorDrawable(Color.rgb(255, 255, 255));
mRlTop.setBackgroundDrawable(cd);
cd.setAlpha(0);
if (Build.VERSION.SDK_INT >= 21) {
mAppBar.setElevation(0f);
} else {
mDivide = findViewById(R.id.divider);//兼容4.4及以下系统,导航栏下加条细线
}
mScrollViewHelper.setOnScrollViewListener(new NestedScrollViewX.OnScrollViewListener() {
@Override
public void onScrollChanged(NestedScrollViewX v, int x, int y, int oldx, int oldy) {
cd.setAlpha(getAlpha(v.getScrollY(), 255f));
if (Build.VERSION.SDK_INT >= 21) {
mAppBar.setElevation(getAlpha(v.getScrollY(), 3f));
} else {
mDivide.setAlpha(getAlpha(v.getScrollY(), 1f));
mDivide.setVisibility(View.VISIBLE);
}
int alpha = getAlpha(v.getScrollY(), 1f);
if (alpha == 1) {
mIvBack.setBackgroundResource(R.drawable.ic_arrow_left);
mIvShare.setBackgroundResource(R.drawable.ic_share_black);
} else {
mIvBack.setAlpha(alpha);
mIvShare.setAlpha(alpha);
mIvBack.setBackgroundResource(R.drawable.ic_arrow_left_w);
mIvShare.setBackgroundResource(R.drawable.ic_share);
}
}
});

这里有一个很重要的获取当前滑动状态下透明度的方法

1
2
3
4
5
6
7
8
9
10
private int getAlpha(int scrollY, float max) {
int minDist = 0, maxDist = 400;
if (scrollY > maxDist) {
return (int) max;
} else if (scrollY < minDist) {
return 0;
} else {
return (int) ((max / maxDist) * scrollY);
}
}

scrollY表示当前View滑离顶部的距离,max表示临界点的最大值