效果就不展示了,反正是真的可以用。效率高。
2、Glide自带的
想不到吧?
只要在导入:
api ‘com.github.bumptech.glide:glide:4.9.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.9.0’
api ‘jp.wasabeef:glide-transformations:4.0.1’ //高斯模糊api
然后在代码中引入:
Glide.with(this)
.load(coverUrl)
//第一个参数时模糊半径,范围在 0<radius<=25f,第二个参数是放大参数,默认是1
.apply(RequestOptions.bitmapTransform(new BlurTransformation(25, 1)))
.into(ivBg);
思路
上面的Api其实并不是最重要的,不要以为用了这些方法,就能在监听滑动的时候去用这些方法就可以达成效果了。
这是因为 你每次滑动,就要进行这些计算,如果图片精度、分辨率很高,一次计算达到了上百ms,那我们一次滑动至少产生15次以上的计算,这必然会产生卡顿。
所以我们要做的动态模糊,其实是一个幌子,我们不是根据监听滑动进行模糊,而是让视觉效果让它变得模糊,就像是欺骗的感觉。
√:我们拿一份已经模糊的图放在低层,再拿一张完全不模糊的放在上层覆盖它,然后随着滑动,上层的透明度逐渐减低,下层逐渐显现出来,这样的视觉效果,正是一个图片逐渐模糊。
设置图片透明度使用 setImageView(alpha)
,呜呜呜我之前不知道这个方法,结果一直找不到解决方法。
1、监听AppBarLayout滑动
因为AppBarLayou自带的api不太方便,我们需要再封装一层:
/**
- AppBarLayout的监听类
*/
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {
private static final String TAG = “AppBarStateChangeListen”;
public enum State {
EXPANDED,
COLLAPSED,
IDLE
}
private State mCurrentState = State.IDLE;
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
onOffsetChanged(appBarLayout);
if (i == 0) {
if (mCurrentState != State.EXPANDED) {
onStateChanged(appBarLayout, State.EXPANDED);
}
mCurrentState = State.EXPANDED;
} else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
if (mCurrentState != State.COLLAPSED) {
onStateChanged(appBarLayout, State.COLLAPSED);
}
mCurrentState = State.COLLAPSED;
} else {
if (mCurrentState != State.IDLE) {
onStateChanged(appBarLayout, State.IDLE);
}
mCurrentState = State.IDLE;
}
}
//状态发生了改变
public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
//发生了偏移
public abstract void onOffsetChanged(AppBarLayout appBarLayout);
}
2、XML文件
说来你们可能不信,我对圆角的处理是这样的:
蓝色和天蓝色都是属于AppBarLayout,上滑需要对圆角layout设置layout_collapseMode="parallax"
然后 AppBarLayout最底层仿两个ImageView,模糊的在下面,清晰的在上面。
并且 AppBarLayout的 app:elevation
要设置为 0dp,不然在折叠的时候会产生阴影,影响白色圆角的发挥
而且注意 是 app的elevation而不是 android的 elevation
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
app:elevation=“0dp”>
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width=“match_parent”
android:layout_height="@dimen/dp_200"
android:fitsSystemWindows=“true”
app:layout_scrollFlags=“scroll|exitUntilCollapsed”>
//低层模糊图片
<ImageView
android:id="@+id/iv_background"
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:scaleType=“centerCrop”
app:layout_collapseMode=“parallax” />
//上层做透明度变化的图片
<ImageView
android:id="@+id/iv_background_cover"
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:scaleType=“centerCrop”
app:layout_collapseMode=“parallax” />
//一些字体
<RelativeLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
app:layout_collapseMode=“parallax”>
<TextView
android:id="@+id/tv_day"
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>
<TextView
android:id="@+id/tv_month"
android:layout_width=“wrap_content”
android:layout_height=“wrap_content” />
//标题头
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/ClubToolbar"
android:layout_width=“match_parent”
android:layout_height="@dimen/dp_55"
android:layout_marginTop="@dimen/dp_30"
app:layout_collapseMode=“pin”>
<include
android:id="@+id/title"
layout="@layout/common_title" />
</android.support.v7.widget.Toolbar>
//哈哈哈哈哈这个就是一个圆角矩形
<RelativeLayout
android:layout_width=“match_parent”
android:layout_height="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_290"
android:background="@drawable/bg_dailyrecommend"
app:layout_collapseMode=“pin” />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:id="@+id/rl_play"
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:background="#ffffff"
android:paddingBottom="@dimen/dp_40"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:layout_width=“match_parent”
android:layout_height=“match_parent”/>
3、根据监听AppBarLayout来改变透明度
AppBarLayout的滑动监听是没有 偏移值 offsetX和offsetY的,所以滑动到一定距离,字体的透明度到一定值怎么弄呢,我这里借助的是包裹着RecyclerView的RelativeLayout距离顶部的距离做判断。
该layout的 getTop() 越接近顶部,说明AppBarLayout快要折叠,我根据这个值去计算。
从上图可以知道 我们处理getTop()返回在 Toobar高度~AppBarLayout高度.
如果在Toolbar设置了marginTop值,则也要在Toolbar高度里加上,我这里就设置了(因为使用了沉侵状态栏)。
首先在onCreate中初始化这些值:
//计算 getTop移动范围,和初始化图片
protected void initData() {
if (coverUrl != null) {
Glide.with(this)
.load(coverUrl)
.into(ivBgCover);
Glide.with(this)
.load(coverUrl)
.apply(RequestOptions.bitmapTransform(new BlurTransformation(25, 1)))
p()返回在 Toobar高度~AppBarLayout高度.
如果在Toolbar设置了marginTop值,则也要在Toolbar高度里加上,我这里就设置了(因为使用了沉侵状态栏)。
首先在onCreate中初始化这些值:
//计算 getTop移动范围,和初始化图片
protected void initData() {
if (coverUrl != null) {
Glide.with(this)
.load(coverUrl)
.into(ivBgCover);
Glide.with(this)
.load(coverUrl)
.apply(RequestOptions.bitmapTransform(new BlurTransformation(25, 1)))