mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 00:55:37 +00:00
131 lines
4.1 KiB
Java
131 lines
4.1 KiB
Java
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package org.mozilla.gecko.gfx;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.Canvas;
|
|
import android.os.Build;
|
|
import android.widget.EdgeEffect;
|
|
import android.view.View;
|
|
|
|
|
|
public class OverscrollEdgeEffect implements Overscroll {
|
|
// Used to index particular edges in the edges array
|
|
private static final int TOP = 0;
|
|
private static final int BOTTOM = 1;
|
|
private static final int LEFT = 2;
|
|
private static final int RIGHT = 3;
|
|
|
|
// All four edges of the screen
|
|
private final EdgeEffect[] mEdges = new EdgeEffect[4];
|
|
|
|
// The view we're showing this overscroll on.
|
|
private final View mView;
|
|
|
|
public OverscrollEdgeEffect(final View v) {
|
|
mView = v;
|
|
Context context = v.getContext();
|
|
for (int i = 0; i < 4; i++) {
|
|
mEdges[i] = new EdgeEffect(context);
|
|
}
|
|
}
|
|
|
|
public void setSize(final int width, final int height) {
|
|
mEdges[LEFT].setSize(height, width);
|
|
mEdges[RIGHT].setSize(height, width);
|
|
mEdges[TOP].setSize(width, height);
|
|
mEdges[BOTTOM].setSize(width, height);
|
|
}
|
|
|
|
private EdgeEffect getEdgeForAxisAndSide(final Axis axis, final float side) {
|
|
if (axis == Axis.Y) {
|
|
if (side < 0) {
|
|
return mEdges[TOP];
|
|
} else {
|
|
return mEdges[BOTTOM];
|
|
}
|
|
} else {
|
|
if (side < 0) {
|
|
return mEdges[LEFT];
|
|
} else {
|
|
return mEdges[RIGHT];
|
|
}
|
|
}
|
|
}
|
|
|
|
private void invalidate() {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
|
mView.postInvalidateOnAnimation();
|
|
} else {
|
|
mView.postInvalidateDelayed(10);
|
|
}
|
|
}
|
|
|
|
public void setVelocity(final float velocity, final Axis axis) {
|
|
final EdgeEffect edge = getEdgeForAxisAndSide(axis, velocity);
|
|
|
|
// If we're showing overscroll already, start fading it out.
|
|
if (!edge.isFinished()) {
|
|
edge.onRelease();
|
|
} else {
|
|
// Otherwise, show an absorb effect
|
|
edge.onAbsorb((int)velocity);
|
|
}
|
|
|
|
invalidate();
|
|
}
|
|
|
|
public void setDistance(final float distance, final Axis axis) {
|
|
// The first overscroll event often has zero distance. Throw it out
|
|
if (distance == 0.0f) {
|
|
return;
|
|
}
|
|
|
|
final EdgeEffect edge = getEdgeForAxisAndSide(axis, (int)distance);
|
|
edge.onPull(distance / (axis == Axis.X ? mView.getWidth() : mView.getHeight()));
|
|
invalidate();
|
|
}
|
|
|
|
public void draw(final Canvas canvas, final ImmutableViewportMetrics metrics) {
|
|
if (metrics == null) {
|
|
return;
|
|
}
|
|
|
|
// If we're pulling an edge, or fading it out, draw!
|
|
boolean invalidate = false;
|
|
if (!mEdges[TOP].isFinished()) {
|
|
invalidate |= draw(mEdges[TOP], canvas, metrics.marginLeft, metrics.marginTop, 0);
|
|
}
|
|
|
|
if (!mEdges[BOTTOM].isFinished()) {
|
|
invalidate |= draw(mEdges[BOTTOM], canvas, mView.getWidth(), mView.getHeight(), 180);
|
|
}
|
|
|
|
if (!mEdges[LEFT].isFinished()) {
|
|
invalidate |= draw(mEdges[LEFT], canvas, metrics.marginLeft, mView.getHeight(), 270);
|
|
}
|
|
|
|
if (!mEdges[RIGHT].isFinished()) {
|
|
invalidate |= draw(mEdges[RIGHT], canvas, mView.getWidth(), metrics.marginTop, 90);
|
|
}
|
|
|
|
// If the edge effect is animating off screen, invalidate.
|
|
if (invalidate) {
|
|
invalidate();
|
|
}
|
|
}
|
|
|
|
public boolean draw(final EdgeEffect edge, final Canvas canvas, final float translateX, final float translateY, final float rotation) {
|
|
final int state = canvas.save();
|
|
canvas.translate(translateX, translateY);
|
|
canvas.rotate(rotation);
|
|
boolean invalidate = edge.draw(canvas);
|
|
canvas.restoreToCount(state);
|
|
|
|
return invalidate;
|
|
}
|
|
}
|