package hk.hku.cs.srli.widget.util;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import hk.hku.cs.srli.widget.R;
import hk.hku.cs.srli.widget.util.HoverHandler.OnHoverMoveListener;
public class EdgeEffectHelper implements OnHoverMoveListener {
public static final int DEFAULT_COLOR = 0;
public static final int SCROLL_COLOR = R.color.scrollable_edge;
public static final int OVERSCROLL_COLOR = R.color.overscroll_edge;
private View view;
private EdgeEffect leftEdge;
private EdgeEffect rightEdge;
private EdgeEffect topEdge;
private EdgeEffect bottomEdge;
private boolean leftEdgeGlow = false;
private boolean rightEdgeGlow = false;
private boolean topEdgeGlow = false;
private boolean bottomEdgeGlow = false;
// use transparent color as default
private int leftEdgeColor = DEFAULT_COLOR;
private int rightEdgeColor = DEFAULT_COLOR;
private int topEdgeColor = DEFAULT_COLOR;
private int bottomEdgeColor = DEFAULT_COLOR;
public EdgeEffectHelper(View view) {
this.view = view;
leftEdge = new EdgeEffect(view.getContext());
rightEdge = new EdgeEffect(view.getContext());
topEdge = new EdgeEffect(view.getContext());
bottomEdge = new EdgeEffect(view.getContext());
}
public void applyStyledAttributes(AttributeSet attrs, int defStyle) {
// Load attributes
final TypedArray a = view.getContext().obtainStyledAttributes(
attrs, R.styleable.EdgeGlow, defStyle, 0);
try {
leftEdgeGlow = a.getBoolean(R.styleable.EdgeGlow_leftEdgeGlow, false);
rightEdgeGlow = a.getBoolean(R.styleable.EdgeGlow_rightEdgeGlow, false);
topEdgeGlow = a.getBoolean(R.styleable.EdgeGlow_topEdgeGlow, false);
bottomEdgeGlow = a.getBoolean(R.styleable.EdgeGlow_bottomEdgeGlow, false);
leftEdgeColor = a.getColor(R.styleable.EdgeGlow_leftEdgeColor, 0);
rightEdgeColor = a.getColor(R.styleable.EdgeGlow_rightEdgeColor, 0);
topEdgeColor = a.getColor(R.styleable.EdgeGlow_topEdgeColor, 0);
bottomEdgeColor = a.getColor(R.styleable.EdgeGlow_bottomEdgeColor, 0);
} finally {
a.recycle();
}
updateColors();
}
@Override
public void onHoverMove(View v, int x, int y) {
final float ratioX = (float) x / view.getWidth();
final float ratioY = (float) y / view.getHeight();
final float factor = 0.8f;
if (leftEdgeGlow) leftEdge.onDrift(ratioX * factor);
if (rightEdgeGlow) rightEdge.onDrift((1 - ratioX) * factor);
if (topEdgeGlow) topEdge.onDrift(ratioY * factor);
if (bottomEdgeGlow) bottomEdge.onDrift((1 - ratioY) * factor);
if (!areEdgeEffectsFinished()) {
// edge effects not finished, refresh UI
view.postInvalidateOnAnimation();
}
}
public void onHoverChanged(boolean hovered) {
if (hovered) {
if (leftEdgeGlow) leftEdge.onRampUp();
if (rightEdgeGlow) rightEdge.onRampUp();
if (topEdgeGlow) topEdge.onRampUp();
if (bottomEdgeGlow) bottomEdge.onRampUp();
} else {
// release all edge effects
if (leftEdgeGlow) leftEdge.onRampDown();
if (rightEdgeGlow) rightEdge.onRampDown();
if (topEdgeGlow) topEdge.onRampDown();
if (bottomEdgeGlow) bottomEdge.onRampDown();
}
if (!areEdgeEffectsFinished()) {
view.postInvalidateOnAnimation();
}
}
public void draw(Canvas canvas) {
boolean needsInvalidate = false;
final int outerHeight = view.getHeight();
final int outerWidth = view.getWidth();
final int innerHeight = outerHeight - view.getPaddingTop() - view.getPaddingBottom();
final int innerWidth = outerWidth - view.getPaddingLeft() - view.getPaddingRight();
if (topEdgeGlow && !topEdge.isFinished()) {
final int restoreCount = canvas.save();
canvas.translate(view.getPaddingLeft(), 0);
topEdge.setSize(innerWidth, outerHeight);
needsInvalidate |= topEdge.draw(canvas);
canvas.restoreToCount(restoreCount);
}
if (rightEdgeGlow && !rightEdge.isFinished()) {
final int restoreCount = canvas.save();
canvas.rotate(90);
canvas.translate(view.getPaddingTop(), -outerWidth);
rightEdge.setSize(innerHeight, outerWidth);
needsInvalidate |= rightEdge.draw(canvas);
canvas.restoreToCount(restoreCount);
}
if (bottomEdgeGlow && !bottomEdge.isFinished()) {
final int restoreCount = canvas.save();
canvas.rotate(180);
canvas.translate(-innerWidth - view.getPaddingLeft(), -outerHeight);
bottomEdge.setSize(innerWidth, outerHeight);
needsInvalidate |= bottomEdge.draw(canvas);
canvas.restoreToCount(restoreCount);
}
if (leftEdgeGlow && !leftEdge.isFinished()) {
final int restoreCount = canvas.save();
canvas.rotate(270);
canvas.translate(-innerHeight - view.getPaddingTop(), 0);
leftEdge.setSize(innerHeight, outerWidth);
needsInvalidate |= leftEdge.draw(canvas);
canvas.restoreToCount(restoreCount);
}
if (needsInvalidate) {
// Keep animating
view.postInvalidateOnAnimation();
}
}
public void setEdgeGlow(boolean left, boolean top, boolean right, boolean bottom) {
leftEdgeGlow = left;
rightEdgeGlow = right;
topEdgeGlow = top;
bottomEdgeGlow = bottom;
if (!left) leftEdge.finish();
if (!right) rightEdge.finish();
if (!top) topEdge.finish();
if (!bottom) bottomEdge.finish();
}
public void setEdgeGlowColorRes(int left, int top, int right, int bottom) {
if (left != 0) leftEdgeColor = getColor(left);
else leftEdgeColor = 0;
if (right != 0) rightEdgeColor = getColor(right);
else rightEdgeColor = 0;
if (top != 0) topEdgeColor = getColor(top);
else topEdgeColor = 0;
if (bottom != 0) bottomEdgeColor = getColor(bottom);
else bottomEdgeColor = 0;
updateColors();
}
public void setHorizontalScrollable(boolean leftScrollable, boolean rightScrollable) {
if (!leftScrollable && !rightScrollable) {
// not scrollable at all
leftEdgeGlow = false;
rightEdgeGlow = false;
leftEdge.finish();
rightEdge.finish();
} else {
leftEdgeGlow = true;
rightEdgeGlow = true;
leftEdgeColor = getColor(leftScrollable ?
EdgeEffectHelper.SCROLL_COLOR : EdgeEffectHelper.OVERSCROLL_COLOR);
rightEdgeColor = getColor(rightScrollable ?
EdgeEffectHelper.SCROLL_COLOR : EdgeEffectHelper.OVERSCROLL_COLOR);
updateColors();
}
}
public void setVerticalScrollable(boolean topScrollable, boolean bottomScrollable) {
if (!topScrollable && !bottomScrollable) {
topEdgeGlow = false;
bottomEdgeGlow = false;
topEdge.finish();
bottomEdge.finish();
} else {
topEdgeGlow = true;
bottomEdgeGlow = true;
topEdgeColor = getColor(topScrollable ?
EdgeEffectHelper.SCROLL_COLOR : EdgeEffectHelper.OVERSCROLL_COLOR);
bottomEdgeColor = getColor(bottomScrollable ?
EdgeEffectHelper.SCROLL_COLOR : EdgeEffectHelper.OVERSCROLL_COLOR);
updateColors();
}
}
private boolean areEdgeEffectsFinished() {
return leftEdge.isFinished() && rightEdge.isFinished()
&& topEdge.isFinished() && bottomEdge.isFinished();
}
private void updateColors() {
if (leftEdgeColor != 0) leftEdge.setColor(leftEdgeColor);
else leftEdge.clearColor();
if (rightEdgeColor != 0) rightEdge.setColor(rightEdgeColor);
else rightEdge.clearColor();
if (topEdgeColor != 0) topEdge.setColor(topEdgeColor);
else topEdge.clearColor();
if (bottomEdgeColor != 0) bottomEdge.setColor(bottomEdgeColor);
else bottomEdge.clearColor();
}
private int getColor(int res) {
return view.getResources().getColor(res);
}
}