package com.dodola.flip;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
public class DetailAnimViewGroup extends ViewGroup {
public static final int ANIMATION_DURATION = 540;
private float bottomFoldFactor;
final View child;
private RectF clip;
private Matrix firstHalfMatrix;
private Rect firstHalfRect;
private Paint firstShadowGradientPaint;
private Paint foldLinePaint;
private float halfPageFoldedHeight;
private float halfPageFoldedWidth;
private int halfPageHeight;
private int halfPageWidth;
private final int halfPages;
private int initialFoldCenter;
public int number;
private float[] polygonFlat;
private float[] polygonFolded;
protected boolean prepared;
boolean reversed;
private int scaledHeight;
private Matrix secondHalfMatrix;
private Rect secondHalfRect;
private Paint secondShadowGradientPaint;
private float topFoldFactor;
private RectF transformedClip;
public static final float DEFAULT_BACKOFF_MULT = 1.0f;
public DetailAnimViewGroup(Context context, @NonNull View child, int number) {
super(context);
this.reversed = true;
this.halfPages = 2;
this.bottomFoldFactor = 0.0f;
this.topFoldFactor = 0.0f;
this.clip = new RectF();
this.transformedClip = new RectF();
this.child = child;
if (child != null) {
addView(child);
}
this.number = number;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
protected void onLayout(boolean arg0, int x1, int y1, int x2, int y2) {
int width = x2 - x1;
int height = y2 - y1;
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).layout(0, 0, width, height);
}
if (!this.prepared) {
prepareFold();
}
}
public void setReversed(boolean reversed) {
this.reversed = reversed;
}
public void setBottomFoldFactor(float foldFactor) {
foldFactor = ViewUtil.clamp(foldFactor, 0.0f, DEFAULT_BACKOFF_MULT);
if (foldFactor != this.bottomFoldFactor) {
this.bottomFoldFactor = foldFactor;
calculateMatrix(false);
invalidate();
}
updateVisibility();
}
private void updateVisibility() {
if (this.topFoldFactor == DEFAULT_BACKOFF_MULT && this.bottomFoldFactor == DEFAULT_BACKOFF_MULT) {
if (getVisibility() != View.GONE) {
setVisibility(View.GONE);
}
} else if (getVisibility() != View.VISIBLE) {
setVisibility(View.VISIBLE);
}
}
public void setTopFoldFactor(float foldFactor) {
foldFactor = ViewUtil.clamp(foldFactor, 0.0f, DEFAULT_BACKOFF_MULT);
if (foldFactor != this.topFoldFactor) {
this.topFoldFactor = foldFactor;
calculateMatrix(true);
invalidate();
}
updateLayer(this.child);
updateVisibility();
}
public float getTopFoldFactor() {
return this.topFoldFactor;
}
protected void prepareFold() {
this.polygonFlat = new float[8];
this.polygonFlat[0] = 0.0f;
this.polygonFlat[1] = 0.0f;
this.polygonFlat[2] = 0.0f;
this.polygonFlat[5] = 0.0f;
this.polygonFolded = new float[8];
this.firstShadowGradientPaint = new Paint();
this.firstShadowGradientPaint.setStyle(Style.FILL);
this.secondShadowGradientPaint = new Paint();
this.secondShadowGradientPaint.setStyle(Style.FILL);
this.foldLinePaint = new Paint();
this.foldLinePaint.setStrokeWidth(getResources().getDisplayMetrics().density * 2.0f);
this.foldLinePaint.setColor(-1);
this.foldLinePaint.setAlpha(0);
int height = Math.round(((float) getMeasuredHeight()) / 2.0f);
LinearGradient firstShadowGradient = new LinearGradient(0.0f, 0.0f, 0.0f, (float) height, 0x3f000000, 0xbb000000, TileMode.CLAMP);
LinearGradient secondShadowGradient = new LinearGradient(0.0f, 0.0f, 0.0f, (float) height, 0xbb000000, 0, TileMode.CLAMP);
this.firstShadowGradientPaint.setShader(firstShadowGradient);
this.secondShadowGradientPaint.setShader(secondShadowGradient);
this.firstHalfRect = new Rect();
this.secondHalfRect = new Rect();
this.firstHalfMatrix = new Matrix();
this.secondHalfMatrix = new Matrix();
this.firstHalfRect = new Rect(0, 0, getMeasuredWidth(), Math.round(((float) getMeasuredHeight()) / 2.0f));
this.secondHalfRect = new Rect(0, Math.round(((float) getMeasuredHeight()) / 2.0f), getMeasuredWidth(), getMeasuredHeight());
this.halfPageHeight = (int) Math.ceil((double) (((float) getMeasuredHeight()) / 2.0f));
this.halfPageWidth = getMeasuredWidth();
this.prepared = true;
calculateMatrix(true);
calculateMatrix(false);
}
void calculateMatrix(boolean first) {
if (this.prepared) {
float f;
float translationFactor = DEFAULT_BACKOFF_MULT - (first ? this.topFoldFactor : this.bottomFoldFactor);
float translatedDistancePerFold = (float) Math.round((((float) getMeasuredHeight()) * translationFactor) / 2.0f);
this.halfPageFoldedWidth = ((float) this.halfPageWidth) < translatedDistancePerFold ? translatedDistancePerFold : (float) this.halfPageWidth;
if (((float) this.halfPageHeight) < translatedDistancePerFold) {
f = translatedDistancePerFold;
} else {
f = (float) this.halfPageHeight;
}
this.halfPageFoldedHeight = f;
this.polygonFlat[3] = this.halfPageFoldedHeight;
this.polygonFlat[4] = this.halfPageFoldedWidth;
this.polygonFlat[6] = this.halfPageFoldedWidth;
this.polygonFlat[7] = this.halfPageFoldedHeight;
int scaledWidth = (int) Math.ceil((double) (this.halfPageFoldedWidth * (DEFAULT_BACKOFF_MULT * (3600.0f / (3600.0f + ((float) Math.sqrt((double) ((this.halfPageFoldedHeight * this.halfPageFoldedHeight) - (translatedDistancePerFold * translatedDistancePerFold)))))))));
this.scaledHeight = (int) Math.ceil((double) (this.halfPageFoldedHeight * translationFactor));
int anchorPoint = (int) ((((float) this.initialFoldCenter) * this.topFoldFactor) + ((((float) getHeight()) / 2.0f) * (DEFAULT_BACKOFF_MULT - this.topFoldFactor)));
if (first) {
calculateFirstHalf((float) anchorPoint, (float) scaledWidth, (float) this.scaledHeight);
} else {
calculateSecondHalf((float) anchorPoint, (float) scaledWidth, (float) this.scaledHeight);
}
}
}
void calculateFirstHalf(float anchorPoint, float scaledWidth, float scaledHeight) {
float leftScaledPoint = (this.halfPageFoldedWidth - scaledWidth) / 2.0f;
float rightScaledPoint = leftScaledPoint + scaledWidth;
if (!this.reversed) {
this.polygonFolded[0] = 0.0f;
this.polygonFolded[1] = anchorPoint - scaledHeight;
this.polygonFolded[2] = leftScaledPoint;
this.polygonFolded[3] = anchorPoint;
this.polygonFolded[4] = (float) getMeasuredWidth();
this.polygonFolded[5] = this.polygonFolded[1];
this.polygonFolded[6] = rightScaledPoint;
this.polygonFolded[7] = this.polygonFolded[3];
}
int shadowAlpha = (int) (255.0f - ((255.0f * scaledHeight) / (((float) getMeasuredHeight()) / 2.0f)));
this.firstHalfMatrix.reset();
this.firstHalfMatrix.setPolyToPoly(this.polygonFlat, 0, this.polygonFolded, 0, 4);
this.firstShadowGradientPaint.setAlpha(shadowAlpha);
}
void calculateSecondHalf(float anchorPoint, float scaledWidth, float scaledHeight) {
float leftScaledPoint = (this.halfPageFoldedWidth - scaledWidth) / 2.0f;
float rightScaledPoint = leftScaledPoint + scaledWidth;
if (!this.reversed) {
this.polygonFolded[0] = leftScaledPoint;
this.polygonFolded[1] = anchorPoint;
this.polygonFolded[2] = 0.0f;
this.polygonFolded[3] = anchorPoint + scaledHeight;
this.polygonFolded[4] = rightScaledPoint;
this.polygonFolded[5] = this.polygonFolded[1];
this.polygonFolded[6] = (float) getMeasuredWidth();
this.polygonFolded[7] = this.polygonFolded[3];
}
int shadowAlpha = (int) (255.0f - ((255.0f * scaledHeight) / (((float) getMeasuredHeight()) / 2.0f)));
this.secondHalfMatrix.reset();
this.secondHalfMatrix.setPolyToPoly(this.polygonFlat, 0, this.polygonFolded, 0, 4);
this.secondShadowGradientPaint.setAlpha(shadowAlpha);
this.foldLinePaint.setAlpha((int) (Math.min(DEFAULT_BACKOFF_MULT, this.bottomFoldFactor * 2.0f) * 255.0f));
}
boolean hasFold() {
return this.topFoldFactor > 0.0f;
}
protected void dispatchDraw(Canvas canvas) {
if (this.prepared && hasFold()) {
if (this.topFoldFactor < DEFAULT_BACKOFF_MULT) {
drawHalf(canvas, this.firstHalfRect, this.firstHalfMatrix, this.firstShadowGradientPaint, true);
}
if (this.bottomFoldFactor < DEFAULT_BACKOFF_MULT) {
drawHalf(canvas, this.secondHalfRect, this.secondHalfMatrix, this.secondShadowGradientPaint, false);
return;
}
return;
}
super.dispatchDraw(canvas);
}
void drawHalf(Canvas canvas, @NonNull Rect src, @NonNull Matrix transform, Paint shadowPaint, boolean top) {
canvas.save();
if (this.reversed) {
canvas.save();
canvas.translate(0.0f, (float) ((int) (((float) (top ? -1 : 1)) * (this.topFoldFactor * ((float) src.height())))));
canvas.clipRect(src);
} else {
this.clip.set(0.0f, 0.0f, (float) (src.right - src.left), (float) (src.bottom - src.top));
transform.mapRect(this.transformedClip, this.clip);
canvas.clipRect(this.transformedClip);
canvas.concat(transform);
canvas.save();
canvas.translate(0.0f, (float) (-src.top));
}
super.dispatchDraw(canvas);
if (this.reversed) {
int y = this.initialFoldCenter;
canvas.drawLine(0.0f, (float) y, (float) getWidth(), (float) y, this.foldLinePaint);
}
canvas.restore();
if (!this.reversed) {
canvas.drawRect(0.0f, 0.0f, (float) getMeasuredWidth(), (float) getMeasuredHeight(), shadowPaint);
}
canvas.restore();
}
public void setInitialFoldCenter(int initialFoldCenter) {
this.initialFoldCenter = initialFoldCenter;
this.firstHalfRect = new Rect(0, 0, getMeasuredWidth(), initialFoldCenter);
this.secondHalfRect = new Rect(0, initialFoldCenter, getMeasuredWidth(), getMeasuredHeight());
}
private void updateLayer(@NonNull View view) {
if (hasFold() && view.getLayerType() != 2) {
view.setLayerType(2, null);
} else if (!hasFold() && view.getLayerType() != 0) {
view.setLayerType(0, null);
}
}
}