最近在技术群里面看到有人发了一个很炫酷的效果gif图,然后再问实现的方法,看了一下效果然后自己写了一个小demo
先上人家的原图效果:
下面上我模仿的gif图,效果没有全部模仿完,界面很粗糙,只模仿效果
如下是实现代码:
package com.test.mteffect;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.ScriptIntrinsicBlur;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.view.animation.Transformation;
import android.view.animation.Animation.AnimationListener;
import android.widget.LinearLayout.LayoutParams;
public class MainActivity extends Activity {
private View bg_ll_flur;
private View bg_ll_bg;
private ImageView mt_flur_btnimg;
private LinearLayout mt_flur_ll;
private ListView mt_flur_lvm;
private ListView mt_flur_lv;
private static int HEADHEIGHT = 0;
private boolean expandable = false;
private MtAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bg_ll_flur = this.findViewById(R.id.bg_ll_flur);
bg_ll_bg = this.findViewById(R.id.bg_ll_bg);
mt_flur_btnimg = (ImageView) this.findViewById(R.id.mt_flur_btnimg);
mt_flur_ll = (LinearLayout) this.findViewById(R.id.mt_flur_ll);
mt_flur_lvm = (ListView) this.findViewById(R.id.mt_flur_lvm);
mt_flur_lv = (ListView) this.findViewById(R.id.mt_flur_lv);
initView();
}
private void initView() {
mt_flur_lvm.setAdapter(new LMtAdapter());
adapter = new MtAdapter();
mt_flur_lv.setAdapter(adapter);
mt_flur_btnimg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (expandable) {
collapse(mt_flur_ll);
} else {
expand(mt_flur_ll);
}
}
});
}
private void applyBlur() {
bg_ll_flur.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
bg_ll_flur.getViewTreeObserver()
.removeOnPreDrawListener(this);
bg_ll_flur.buildDrawingCache();
Bitmap bmp = bg_ll_flur.getDrawingCache();
blurRS(bmp, bg_ll_bg);
return true;
}
});
}
/**
* 根据图片压缩放大模糊原理 效果较差,但能够兼容2.3+
*
* @param bkg
* @param view
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void blur(Bitmap bkg, View view) {
float scaleFactor = 1;
float radius = 20;
// ====快速模糊
scaleFactor = 8;
radius = 2;
// ====
Bitmap overlay = Bitmap.createBitmap(
(int) (view.getMeasuredWidth() / scaleFactor),
(int) (view.getMeasuredHeight() / scaleFactor),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.translate(-view.getLeft() / scaleFactor, -view.getTop()
/ scaleFactor);
canvas.scale(1 / scaleFactor, 1 / scaleFactor);
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bkg, 0, 0, paint);
overlay = FastBlur.doBlur(overlay, (int) radius, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(new BitmapDrawable(getResources(), overlay));
} else {
view.setBackgroundDrawable(new BitmapDrawable(getResources(),
overlay));
}
}
/**
* 根据Android自己的兼容包,如果使用系统自带的需要4.4+,使用V8兼容包,能够兼容4.2+
*
* @param bkg
* @param view
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void blurRS(Bitmap bkg, View view) {
float scaleFactor = 1;
float radius = 20;
// ====快速模糊
scaleFactor = 8;
radius = 2;
// ====
Bitmap overlay = Bitmap.createBitmap(
(int) (view.getMeasuredWidth() / scaleFactor),
(int) (view.getMeasuredHeight() / scaleFactor),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.translate(-view.getLeft() / scaleFactor, -view.getTop()
/ scaleFactor);
canvas.scale(1 / scaleFactor, 1 / scaleFactor);
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bkg, 0, 0, paint);
RenderScript rs = RenderScript.create(getApplicationContext());
Allocation overlayAlloc = Allocation.createFromBitmap(rs, overlay);
ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs,
overlayAlloc.getElement());
blur.setInput(overlayAlloc);
blur.setRadius(radius);
blur.forEach(overlayAlloc);
overlayAlloc.copyTo(overlay);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(new BitmapDrawable(getResources(), overlay));
} else {
view.setBackgroundDrawable(new BitmapDrawable(getResources(),
overlay));
}
rs.destroy();
}
public void expand(final View v) {
if (adapter.getCount() > 4) {
HEADHEIGHT = dip2px(4 * 50 + 30 + 70 + 10);
} else {
HEADHEIGHT = dip2px(adapter.getCount() * 50 + 30 + 70);
}
v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
final int targtetHeight = HEADHEIGHT;
v.getLayoutParams().height = 0;
v.setVisibility(View.VISIBLE);
Animation a = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1 ? targtetHeight
: (int) (targtetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration(150);
v.startAnimation(a);
a.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation arg0) {
bg_ll_flur.setVisibility(View.INVISIBLE);
bg_ll_bg.setVisibility(View.VISIBLE);
applyBlur();
}
@Override
public void onAnimationRepeat(Animation arg0) {
}
@Override
public void onAnimationEnd(Animation arg0) {
expandable = true;
}
});
}
public void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
if (initialHeight > HEADHEIGHT) {
HEADHEIGHT = initialHeight;
}
Animation a = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
if (interpolatedTime == 1) {
v.setVisibility(View.GONE);
} else {
v.getLayoutParams().height = initialHeight
- (int) (initialHeight * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration(150);
v.startAnimation(a);
a.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation arg0) {
bg_ll_flur.setVisibility(View.VISIBLE);
bg_ll_bg.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation arg0) {
}
@Override
public void onAnimationEnd(Animation arg0) {
expandable = false;
}
});
}
private class LMtAdapter extends BaseAdapter {
private ViewHolder holder;
@Override
public int getCount() {
return 15;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getApplicationContext())
.inflate(R.layout.mm_item, parent, false);
holder = new ViewHolder(convertView);
}
switch (position % 3) {
case 0:
holder.img.setImageResource(R.drawable.ter);
break;
case 1:
holder.img.setImageResource(R.drawable.sfas);
break;
case 2:
holder.img.setImageResource(R.drawable.swq);
break;
default:
holder.img.setImageResource(R.drawable.swq);
break;
}
return convertView;
}
class ViewHolder {
private ImageView img;
ViewHolder(View view) {
img = (ImageView) view.findViewById(R.id.mm_img);
}
}
}
private class MtAdapter extends BaseAdapter {
@Override
public int getCount() {
return 5;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getApplicationContext())
.inflate(R.layout.mt_item, parent, false);
}
return convertView;
}
}
public int dip2px(float dipValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}