зеркало из https://github.com/mozilla/gecko-dev.git
Bug 918079 - Show highlight when overscrolling. r=kats
This commit is contained in:
Родитель
1286b0b31d
Коммит
5edd4c1dab
|
@ -194,6 +194,7 @@ FENNEC_JAVA_FILES = \
|
|||
gfx/LayerView.java \
|
||||
gfx/NativePanZoomController.java \
|
||||
gfx/NinePatchTileLayer.java \
|
||||
gfx/Overscroll.java \
|
||||
gfx/PanningPerfAPI.java \
|
||||
gfx/PanZoomController.java \
|
||||
gfx/PanZoomTarget.java \
|
||||
|
|
|
@ -154,6 +154,10 @@ abstract class Axis {
|
|||
mRecentVelocities = new float[FLING_VELOCITY_POINTS];
|
||||
}
|
||||
|
||||
// Implementors can override these to show effects when the axis overscrolls
|
||||
protected void overscrollFling(float velocity) { }
|
||||
protected void overscrollPan(float displacement) { }
|
||||
|
||||
public void setOverScrollMode(int overscrollMode) {
|
||||
mOverscrollMode = overscrollMode;
|
||||
}
|
||||
|
@ -379,12 +383,22 @@ abstract class Axis {
|
|||
// getOverscroll which doesn't take into account any new displacment being applied.
|
||||
// If we using a subscroller, we don't want to alter the scrolling being done
|
||||
if (getOverScrollMode() == View.OVER_SCROLL_NEVER && !mSubscroller.scrolling()) {
|
||||
float originalDisplacement = mDisplacement;
|
||||
|
||||
if (mDisplacement + getOrigin() < getPageStart() - getMarginStart()) {
|
||||
mDisplacement = getPageStart() - getMarginStart() - getOrigin();
|
||||
stopFling();
|
||||
} else if (mDisplacement + getViewportEnd() > getPageEnd() + getMarginEnd()) {
|
||||
mDisplacement = getPageEnd() - getMarginEnd() - getViewportEnd();
|
||||
stopFling();
|
||||
}
|
||||
|
||||
// Return the amount of overscroll so that the overscroll controller can draw it for us
|
||||
if (originalDisplacement != mDisplacement) {
|
||||
if (mFlingState == FlingStates.FLINGING) {
|
||||
overscrollFling(mVelocity / MS_PER_FRAME * 1000);
|
||||
stopFling();
|
||||
} else if (mFlingState == FlingStates.PANNING) {
|
||||
overscrollPan(originalDisplacement - mDisplacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,6 +132,10 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
|
|||
mContentDocumentIsDisplayed = true;
|
||||
}
|
||||
|
||||
public void setOverscrollHandler(final Overscroll listener) {
|
||||
mPanZoomController.setOverscrollHandler(listener);
|
||||
}
|
||||
|
||||
/** Attaches to root layer so that Gecko appears. */
|
||||
public void notifyGeckoReady() {
|
||||
mGeckoIsReady = true;
|
||||
|
|
|
@ -129,6 +129,9 @@ class JavaPanZoomController
|
|||
/* Used to change the scrollY direction */
|
||||
private boolean mNegateWheelScrollY;
|
||||
|
||||
// Handler to be notified when overscroll occurs
|
||||
private Overscroll mOverscroll;
|
||||
|
||||
public JavaPanZoomController(PanZoomTarget target, View view, EventDispatcher eventDispatcher) {
|
||||
mTarget = target;
|
||||
mSubscroller = new SubdocumentScrollHelper(eventDispatcher);
|
||||
|
@ -1113,6 +1116,18 @@ class JavaPanZoomController
|
|||
RectF maxMargins = mTarget.getMaxMargins();
|
||||
return (metrics.marginLeft < maxMargins.left || metrics.marginRight < maxMargins.right);
|
||||
}
|
||||
@Override
|
||||
protected void overscrollFling(final float velocity) {
|
||||
if (mOverscroll != null) {
|
||||
mOverscroll.setVelocity(velocity, Overscroll.Axis.X);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void overscrollPan(final float distance) {
|
||||
if (mOverscroll != null) {
|
||||
mOverscroll.setDistance(distance, Overscroll.Axis.X);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AxisY extends Axis {
|
||||
|
@ -1135,6 +1150,18 @@ class JavaPanZoomController
|
|||
RectF maxMargins = mTarget.getMaxMargins();
|
||||
return (metrics.marginTop < maxMargins.top || metrics.marginBottom < maxMargins.bottom);
|
||||
}
|
||||
@Override
|
||||
protected void overscrollFling(final float velocity) {
|
||||
if (mOverscroll != null) {
|
||||
mOverscroll.setVelocity(velocity, Overscroll.Axis.Y);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void overscrollPan(final float distance) {
|
||||
if (mOverscroll != null) {
|
||||
mOverscroll.setDistance(distance, Overscroll.Axis.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1434,4 +1461,9 @@ class JavaPanZoomController
|
|||
public void updateScrollOffset(float cssX, float cssY) {
|
||||
// Nothing to update, this class doesn't store the scroll offset locally.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOverscrollHandler(final Overscroll handler) {
|
||||
mOverscroll = handler;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.mozilla.gecko.util.EventDispatcher;
|
|||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PointF;
|
||||
|
@ -67,6 +68,7 @@ public class LayerView extends FrameLayout {
|
|||
|
||||
/* This should only be modified on the Java UI thread. */
|
||||
private final ArrayList<TouchEventInterceptor> mTouchInterceptors;
|
||||
private final Overscroll mOverscroll;
|
||||
|
||||
/* Flags used to determine when to show the painted surface. */
|
||||
public static final int PAINT_START = 0;
|
||||
|
@ -104,10 +106,13 @@ public class LayerView extends FrameLayout {
|
|||
mBackgroundColor = Color.WHITE;
|
||||
|
||||
mTouchInterceptors = new ArrayList<TouchEventInterceptor>();
|
||||
mOverscroll = new Overscroll(this);
|
||||
}
|
||||
|
||||
public void initializeView(EventDispatcher eventDispatcher) {
|
||||
mLayerClient = new GeckoLayerClient(getContext(), this, eventDispatcher);
|
||||
mLayerClient.setOverscrollHandler(mOverscroll);
|
||||
|
||||
mPanZoomController = mLayerClient.getPanZoomController();
|
||||
mMarginsAnimator = mLayerClient.getLayerMarginsAnimator();
|
||||
|
||||
|
@ -218,6 +223,16 @@ public class LayerView extends FrameLayout {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchDraw(final Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
// We must have a layer client to get valid viewport metrics
|
||||
if (mLayerClient != null) {
|
||||
mOverscroll.draw(canvas, getViewportMetrics());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
|
@ -487,6 +502,8 @@ public class LayerView extends FrameLayout {
|
|||
if (mListener != null) {
|
||||
mListener.sizeChanged(width, height);
|
||||
}
|
||||
|
||||
mOverscroll.setSize(width, height);
|
||||
}
|
||||
|
||||
private void surfaceChanged(int width, int height) {
|
||||
|
@ -495,6 +512,8 @@ public class LayerView extends FrameLayout {
|
|||
if (mListener != null) {
|
||||
mListener.surfaceChanged(width, height);
|
||||
}
|
||||
|
||||
mOverscroll.setSize(width, height);
|
||||
}
|
||||
|
||||
private void onDestroyed() {
|
||||
|
|
|
@ -104,4 +104,7 @@ class NativePanZoomController implements PanZoomController, GeckoEventListener {
|
|||
}
|
||||
|
||||
public native void updateScrollOffset(float cssX, float cssY);
|
||||
|
||||
public void setOverscrollHandler(final Overscroll listener) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/* -*- 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.support.v4.widget.EdgeEffectCompat;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.view.View;
|
||||
|
||||
public class 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 EdgeEffectCompat[] mEdges = new EdgeEffectCompat[4];
|
||||
|
||||
// The view we're showing this overscroll on.
|
||||
private final View mView;
|
||||
|
||||
// The axis to show overscroll on.
|
||||
public enum Axis {
|
||||
X,
|
||||
Y,
|
||||
};
|
||||
|
||||
public Overscroll(final View v) {
|
||||
mView = v;
|
||||
Context context = v.getContext();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mEdges[i] = new EdgeEffectCompat(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 EdgeEffectCompat 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setVelocity(final float velocity, final Axis axis) {
|
||||
final EdgeEffectCompat 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);
|
||||
}
|
||||
|
||||
ViewCompat.postInvalidateOnAnimation(mView);
|
||||
}
|
||||
|
||||
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 EdgeEffectCompat edge = getEdgeForAxisAndSide(axis, (int)distance);
|
||||
edge.onPull(distance / (axis == Axis.X ? mView.getWidth() : mView.getHeight()));
|
||||
ViewCompat.postInvalidateOnAnimation(mView);
|
||||
}
|
||||
|
||||
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) {
|
||||
ViewCompat.postInvalidateOnAnimation(mView);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean draw(final EdgeEffectCompat 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;
|
||||
}
|
||||
}
|
|
@ -42,4 +42,6 @@ public interface PanZoomController {
|
|||
public int getOverScrollMode();
|
||||
|
||||
public void updateScrollOffset(float cssX, float cssY);
|
||||
|
||||
public void setOverscrollHandler(final Overscroll controller);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче