package com.tencent.tws.assistant.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.ImageView;
import android.widget.ScrollView;
import com.tencent.tws.assistant.gaussblur.GlassBlur;
import com.tencent.tws.assistant.gaussblur.GlassBlurTask;
import com.tencent.tws.assistant.gaussblur.GlassBlurUtil;
import com.tencent.tws.assistant.widget.TwsScrollView.OnScrollChangedListener;
import com.tencent.tws.sharelib.R;
public class TwsScrollWrapper implements OnGlobalLayoutListener, OnScrollChangedListener, GlassBlurTask.Listener {
private int contentLayout;
private FrameLayout frame;
private ImageView headerView, footerView;
private int headerHeight, footerHeight;
private int width, height;
private Bitmap headerBitmap, footerBitmap;
private int blurRadius = GlassBlurUtil.DEFAULT_BLUR_RADIUS;
private GlassBlurTask blurTask;
private int lastScrollPosition = -1;
private TwsScrollView scrollView;
private int downSampling = GlassBlurUtil.DEFAULT_DOWNSAMPLING;
private Drawable windowBackground;
public TwsScrollWrapper contentLayout(Context context, int layout) {
this.contentLayout = layout;
frame = new FrameLayout(context);
frame.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
scrollView = (TwsScrollView)LayoutInflater.from(context).inflate(contentLayout, (ViewGroup) frame, false);
headerView = new ImageView(context);
footerView = new ImageView(context);
headerHeight = (int) context.getResources().getDimension(R.dimen.tws_action_bar_height);
footerHeight = (int) context.getResources().getDimension(R.dimen.tws_actionbar_split_height);
LayoutParams headerLP = new LayoutParams(LayoutParams.MATCH_PARENT, headerHeight);
LayoutParams footerLP = new LayoutParams(LayoutParams.MATCH_PARENT, footerHeight);
headerLP.gravity = Gravity.TOP;
footerLP.gravity = Gravity.BOTTOM;
headerView.setLayoutParams(headerLP);
footerView.setLayoutParams(footerLP);
scrollView.statusbarFlag = false;
return this;
}
public TwsScrollWrapper contentLayoutWithStatusbar(Context context, int layout) {
this.contentLayout = layout;
frame = new FrameLayout(context);
frame.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
scrollView = (TwsScrollView)LayoutInflater.from(context).inflate(contentLayout, (ViewGroup) frame, false);
headerView = new ImageView(context);
footerView = new ImageView(context);
headerHeight = (int) context.getResources().getDimension(R.dimen.tws_action_bar_height);
footerHeight = (int) context.getResources().getDimension(R.dimen.tws_actionbar_split_height);
LayoutParams headerLP = new LayoutParams(LayoutParams.MATCH_PARENT, headerHeight);
LayoutParams footerLP = new LayoutParams(LayoutParams.MATCH_PARENT, footerHeight);
headerLP.gravity = Gravity.TOP;
footerLP.gravity = Gravity.BOTTOM;
headerView.setLayoutParams(headerLP);
footerView.setLayoutParams(footerLP);
scrollView.statusbarFlag = true;
return this;
}
public TwsScrollWrapper contentLayoutWithStatusbar(Context context, TwsScrollView view) {
frame = new FrameLayout(context);
frame.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
scrollView = view;
headerView = new ImageView(context);
footerView = new ImageView(context);
headerHeight = (int) context.getResources().getDimension(R.dimen.tws_action_bar_height);
footerHeight = (int) context.getResources().getDimension(R.dimen.tws_actionbar_split_height);
LayoutParams headerLP = new LayoutParams(LayoutParams.MATCH_PARENT, headerHeight);
LayoutParams footerLP = new LayoutParams(LayoutParams.MATCH_PARENT, footerHeight);
headerLP.gravity = Gravity.TOP;
footerLP.gravity = Gravity.BOTTOM;
headerView.setLayoutParams(headerLP);
footerView.setLayoutParams(footerLP);
scrollView.statusbarFlag = true;
return this;
}
public View createView(Context context) {
int[] attrs = { android.R.attr.windowBackground };
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.windowBackground, outValue, true);
TypedArray style = context.getTheme().obtainStyledAttributes(outValue.resourceId, attrs);
windowBackground = style.getDrawable(0);
style.recycle();
frame.addView(scrollView, 0);
frame.addView(headerView, 1);
frame.addView(footerView, 2);
frame.getViewTreeObserver().addOnGlobalLayoutListener(this);
scrollView.setOnScrollChangedListener(this);
return frame;
}
public void invalidate() {
headerBitmap = null;
footerBitmap = null;
computeBlurOverlay();
updateBlurOverlay(lastScrollPosition, true);
}
public void setBlurRadius(int newValue) {
if (!GlassBlurUtil.isValidBlurRadius(newValue)) {
throw new IllegalArgumentException("Invalid blur radius");
}
if (blurRadius == newValue) {
return;
}
blurRadius = newValue;
invalidate();
}
public int getBlurRadius() {
return blurRadius;
}
public void setDownsampling(int newValue) {
if (!GlassBlurUtil.isValidDownsampling(newValue)) {
throw new IllegalArgumentException("Invalid downsampling");
}
if (downSampling == newValue) {
return;
}
downSampling = newValue;
invalidate();
}
public int getDownsampling() {
return downSampling;
}
@Override
public void onGlobalLayout() {
if (width != 0) {
return;
}
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(frame.getWidth(), MeasureSpec.AT_MOST);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.UNSPECIFIED);
scrollView.measure(widthMeasureSpec, heightMeasureSpec);
width = frame.getWidth();
height = scrollView.getMeasuredHeight();
lastScrollPosition = scrollView != null ? scrollView.getScrollY() : 0;
invalidate();
}
private void computeBlurOverlay() {
if (headerBitmap != null || footerBitmap != null) {
return;
}
int scrollPosition = 0;
if (scrollView != null) {
scrollPosition = scrollView.getScrollY();
}
headerBitmap = drawViewToBitmap(headerBitmap, scrollView, width, height, downSampling, windowBackground);
footerBitmap = drawViewToBitmap(footerBitmap, scrollView, width, height, downSampling, windowBackground);
startBlurTask();
if (scrollView != null) {
scrollView.scrollTo(0, scrollPosition);
}
}
private void startBlurTask() {
if (blurTask != null) {
blurTask.cancel();
}
blurTask = new GlassBlurTask(frame.getContext(), this, headerBitmap, blurRadius);
blurTask = new GlassBlurTask(frame.getContext(), this, footerBitmap, blurRadius);
}
private void updateBlurOverlay(int top, boolean force) {
if (headerBitmap == null || footerBitmap == null) {
return;
}
if (top < 0) {
top = 0;
}
if (!force && lastScrollPosition == top) {
return;
}
lastScrollPosition = top;
Bitmap headerSection, footerSection;
headerSection = Bitmap.createBitmap(headerBitmap, 0, top / downSampling, width / downSampling, headerHeight / downSampling);
footerSection = Bitmap.createBitmap(footerBitmap, 0,
(top + scrollView.getHeight() - footerHeight) / downSampling < (footerBitmap.getHeight() - footerHeight / downSampling) ?
(top + scrollView.getHeight() - footerHeight) / downSampling : (footerBitmap.getHeight() - footerHeight / downSampling),
width / downSampling, footerHeight / downSampling);
Bitmap headerBlur, footerBlur;
if (isBlurTaskFinished()) {
headerBlur = headerSection;
footerBlur = footerSection;
} else {
headerBlur = GlassBlur.apply(frame.getContext(), headerSection);
footerBlur = GlassBlur.apply(frame.getContext(), footerSection);
}
Bitmap headerEnlarged = Bitmap.createScaledBitmap(headerBlur, width, headerHeight, false);
Bitmap footerEnlarged = Bitmap.createScaledBitmap(footerBlur, width, footerHeight, false);
headerBlur.recycle();
headerSection.recycle();
footerBlur.recycle();
footerSection.recycle();
headerView.setImageBitmap(headerEnlarged);
footerView.setImageBitmap(footerEnlarged);
}
private boolean isBlurTaskFinished() {
return blurTask == null;
}
@Override
public void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt) {
onNewScroll(t);
}
private void onNewScroll(int t) {
updateBlurOverlay(t, false);
}
@Override
public void onBlurOperationFinished() {
blurTask = null;
updateBlurOverlay(lastScrollPosition, true);
}
private Bitmap drawViewToBitmap(Bitmap dest, View view, int width, int height, int downSampling, Drawable drawable) {
float scale = 1f / downSampling;
int heightCopy = view.getHeight();
view.layout(0, 0, width, height);
int bmpWidth = (int)(width * scale);
int bmpHeight = (int)(height * scale);
if (dest == null || dest.getWidth() != bmpWidth || dest.getHeight() != bmpHeight) {
dest = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
}
Canvas c = new Canvas(dest);
drawable.setBounds(new Rect(0, 0, width, height));
drawable.draw(c);
if (downSampling > 1) {
c.scale(scale, scale);
}
view.draw(c);
view.layout(0, 0, width, heightCopy);
return dest;
}
public void setHeaderBlank(boolean flag) {
headerView.setVisibility(flag ? View.VISIBLE : View.GONE);
scrollView.setHeaderHeight(flag ? headerHeight : 0);
}
public void setFooterBlank(boolean flag) {
footerView.setVisibility(flag ? View.VISIBLE : View.GONE);
scrollView.setFooterHeight(flag ? footerHeight : 0);
}
}