From 352b2c1834d7a00dda97333dccbec41efd0d1a46 Mon Sep 17 00:00:00 2001 From: seven332 Date: Wed, 17 Jun 2015 15:23:19 +0800 Subject: [PATCH] Move Hotspot and RippleOld to submodule --- .gitmodules | 6 + app/build.gradle | 2 + app/proguard-rules.pro | 8 - .../java/com/hippo/effect/ripple/Ripple.java | 426 ------------- .../hippo/effect/ripple/RippleBackground.java | 289 --------- .../hippo/effect/ripple/RippleDrawable.java | 580 ------------------ .../com/hippo/effect/ripple/RippleOwner.java | 30 - .../com/hippo/effect/ripple/RippleSalon.java | 74 --- .../hippo/ehviewer/ui/scene/SignInScene.java | 2 +- .../ehviewer/widget/DrawerLeftPanel.java | 2 +- .../hippo/ehviewer/widget/SearchLayout.java | 2 +- .../widget/SelectSearchImageLayout.java | 2 +- .../java/com/hippo/scene/AppbarScene.java | 2 +- .../java/com/hippo/scene/SceneDialogView.java | 4 +- .../java/com/hippo/scene/SimpleDialog.java | 2 +- .../preference/PreferenceHeaderScene.java | 4 +- .../scene/preference/PreferenceScene.java | 4 +- .../java/com/hippo/util/DrawableUtils.java | 2 +- .../java/com/hippo/widget/CheckTextView.java | 2 + .../com/hippo/widget/HotspotTouchHelper.java | 300 --------- .../java/com/hippo/widget/Hotspotable.java | 22 - hotspot | 1 + rippleold | 1 + settings.gradle | 2 +- 24 files changed, 26 insertions(+), 1743 deletions(-) delete mode 100644 app/src/main/java/com/hippo/effect/ripple/Ripple.java delete mode 100644 app/src/main/java/com/hippo/effect/ripple/RippleBackground.java delete mode 100644 app/src/main/java/com/hippo/effect/ripple/RippleDrawable.java delete mode 100644 app/src/main/java/com/hippo/effect/ripple/RippleOwner.java delete mode 100644 app/src/main/java/com/hippo/effect/ripple/RippleSalon.java delete mode 100644 app/src/main/java/com/hippo/widget/HotspotTouchHelper.java delete mode 100644 app/src/main/java/com/hippo/widget/Hotspotable.java create mode 160000 hotspot create mode 160000 rippleold diff --git a/.gitmodules b/.gitmodules index beccb9bbb..6e283cf53 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "vectorold"] path = vectorold url = https://github.com/seven332/VectorOld +[submodule "hotspot"] + path = hotspot + url = https://github.com/seven332/Hotspot +[submodule "rippleold"] + path = rippleold + url = https://github.com/seven332/RippleOld diff --git a/app/build.gradle b/app/build.gradle index 3f1172854..474765201 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,4 +34,6 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':unifile') compile project(':vectorold') + compile project(':hotspot') + compile project(':rippleold') } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index f1d02f3b7..988b459fd 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -20,14 +20,6 @@ -keepattributes SourceFile,LineNumberTable # For ObjectAnimator --keepclassmembers class com.hippo.effect.ripple.Ripple { - void set*(***); - *** get*(); -} --keepclassmembers class com.hippo.effect.ripple.RippleBackground { - void set*(***); - *** get*(); -} -keepclassmembers public class * extends com.hippo.vectorold.drawable.VectorDrawable.VGroup { void set*(***); *** get*(); diff --git a/app/src/main/java/com/hippo/effect/ripple/Ripple.java b/app/src/main/java/com/hippo/effect/ripple/Ripple.java deleted file mode 100644 index e56835a62..000000000 --- a/app/src/main/java/com/hippo/effect/ripple/Ripple.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.effect.ripple; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ObjectAnimator; -import android.annotation.TargetApi; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.Rect; -import android.os.Build; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; - -import com.hippo.util.MathUtils; - -/** - * Draws a Material ripple. - */ -class Ripple { - @SuppressWarnings("unused") - private static final String TAG = Ripple.class.getSimpleName(); - - private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); - private static final Interpolator DECEL_INTERPOLATOR = new LogInterpolator(); - - private static final float GLOBAL_SPEED = 1.0f; - private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0f * GLOBAL_SPEED; - private static final float WAVE_TOUCH_UP_ACCELERATION = 3400.0f * GLOBAL_SPEED; - private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0f / GLOBAL_SPEED; - - private static final long RIPPLE_ENTER_DELAY = 80; - - private final RippleOwner mOwner; - - /** Bounds used for computing max radius. */ - private final Rect mBounds; - - /** Full-opacity color for drawing this ripple. */ - private int mColorOpaque; - - /** Maximum ripple radius. */ - private float mOuterRadius; - - /** Screen density used to adjust pixel-based velocities. */ - private float mDensity; - - private float mStartingX; - private float mStartingY; - private float mClampedStartingX; - private float mClampedStartingY; - - // Software animators. - private ObjectAnimator mAnimRadius; - private ObjectAnimator mAnimOpacity; - private ObjectAnimator mAnimX; - private ObjectAnimator mAnimY; - - // Software rendering properties. - private float mOpacity = 1; - private float mOuterX; - private float mOuterY; - - // Values used to tween between the start and end positions. - private float mTweenRadius = 0; - private float mTweenX = 0; - private float mTweenY = 0; - - /** Whether we have an explicit maximum radius. */ - private boolean mHasMaxRadius; - - /** Whether we were canceled externally and should avoid self-removal. */ - private boolean mCanceled; - - /** - * Creates a new ripple. - */ - public Ripple(RippleOwner owner, Rect bounds, float startingX, float startingY) { - mOwner = owner; - mBounds = bounds; - - mStartingX = startingX; - mStartingY = startingY; - } - - public void setup(int maxRadius, int color, float density) { - mColorOpaque = color | 0xFF000000; - mOpacity = Color.alpha(color) / 2 / 255.0f; - - if (maxRadius != RippleOwner.RADIUS_AUTO) { - mHasMaxRadius = true; - mOuterRadius = maxRadius; - } else { - final float halfWidth = mBounds.width() / 2.0f; - final float halfHeight = mBounds.height() / 2.0f; - mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); - } - - mOuterX = 0; - mOuterY = 0; - mDensity = density; - - clampStartingPosition(); - } - - private void clampStartingPosition() { - final float cX = mBounds.exactCenterX(); - final float cY = mBounds.exactCenterY(); - final float dX = mStartingX - cX; - final float dY = mStartingY - cY; - final float r = mOuterRadius; - if (dX * dX + dY * dY > r * r) { - // Point is outside the circle, clamp to the circumference. - final double angle = Math.atan2(dY, dX); - mClampedStartingX = cX + (float) (Math.cos(angle) * r); - mClampedStartingY = cY + (float) (Math.sin(angle) * r); - } else { - mClampedStartingX = mStartingX; - mClampedStartingY = mStartingY; - } - } - - public void onHotspotBoundsChanged() { - if (!mHasMaxRadius) { - final float halfWidth = mBounds.width() / 2.0f; - final float halfHeight = mBounds.height() / 2.0f; - mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); - - clampStartingPosition(); - } - } - - public void setOpacity(float a) { - mOpacity = a; - invalidateSelf(); - } - - public float getOpacity() { - return mOpacity; - } - - public void setRadiusGravity(float r) { - mTweenRadius = r; - invalidateSelf(); - } - - public float getRadiusGravity() { - return mTweenRadius; - } - - public void setXGravity(float x) { - mTweenX = x; - invalidateSelf(); - } - - public float getXGravity() { - return mTweenX; - } - - public void setYGravity(float y) { - mTweenY = y; - invalidateSelf(); - } - - public float getYGravity() { - return mTweenY; - } - - /** - * Draws the ripple centered at (0,0) using the specified paint. - */ - public boolean draw(Canvas c, Paint p) { - return drawSoftware(c, p); - } - - private boolean drawSoftware(Canvas c, Paint p) { - boolean hasContent = false; - - p.setColor(mColorOpaque); - final int alpha = MathUtils.clamp((int) (255 * mOpacity + 0.5f), 0, 255); - final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius); - if (alpha > 0 && radius > 0) { - final float x = MathUtils.lerp( - mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX); - final float y = MathUtils.lerp( - mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY); - p.setAlpha(alpha); - p.setStyle(Style.FILL); - c.drawCircle(x, y, radius, p); - hasContent = true; - } - - return hasContent; - } - - /** - * Returns the maximum bounds of the ripple relative to the ripple center. - */ - public void getBounds(Rect bounds) { - final int outerX = (int) mOuterX; - final int outerY = (int) mOuterY; - final int r = (int) mOuterRadius + 1; - bounds.set(outerX - r, outerY - r, outerX + r, outerY + r); - } - - /** - * Specifies the starting position relative to the drawable bounds. No-op if - * the ripple has already entered. - */ - public void move(float x, float y) { - mStartingX = x; - mStartingY = y; - - clampStartingPosition(); - } - - /** - * Starts the enter animation. - */ - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) - public void enter() { - cancel(); - - final int radiusDuration = (int) - (1000 * Math.sqrt(mOuterRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5); - - final ObjectAnimator radius = ObjectAnimator.ofFloat(this, "radiusGravity", 1); - radius.setDuration(radiusDuration); - radius.setInterpolator(LINEAR_INTERPOLATOR); - radius.setStartDelay(RIPPLE_ENTER_DELAY); - - final ObjectAnimator cX = ObjectAnimator.ofFloat(this, "xGravity", 1); - cX.setDuration(radiusDuration); - cX.setInterpolator(LINEAR_INTERPOLATOR); - cX.setStartDelay(RIPPLE_ENTER_DELAY); - - final ObjectAnimator cY = ObjectAnimator.ofFloat(this, "yGravity", 1); - cY.setDuration(radiusDuration); - cY.setInterpolator(LINEAR_INTERPOLATOR); - cY.setStartDelay(RIPPLE_ENTER_DELAY); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - radius.setAutoCancel(true); - cX.setAutoCancel(true); - cY.setAutoCancel(true); - } - - mAnimRadius = radius; - mAnimX = cX; - mAnimY = cY; - - // Enter animations always run on the UI thread, since it's unlikely - // that anything interesting is happening until the user lifts their - // finger. - radius.start(); - cX.start(); - cY.start(); - } - - /** - * Starts the exit animation. - */ - public void exit() { - cancel(); - - final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius); - final float remaining; - if (mAnimRadius != null && mAnimRadius.isRunning()) { - remaining = mOuterRadius - radius; - } else { - remaining = mOuterRadius; - } - - final int radiusDuration = (int) (1000 * Math.sqrt(remaining / (WAVE_TOUCH_UP_ACCELERATION - + WAVE_TOUCH_DOWN_ACCELERATION) * mDensity) + 0.5); - final int opacityDuration = (int) (1000 * 1 / WAVE_OPACITY_DECAY_VELOCITY + 0.5f); - - exitSoftware(radiusDuration, opacityDuration); - } - - /** - * Jump all animations to their end state. The caller is responsible for - * removing the ripple from the list of animating ripples. - */ - public void jump() { - mCanceled = true; - endSoftwareAnimations(); - mCanceled = false; - } - - private void endSoftwareAnimations() { - if (mAnimRadius != null) { - mAnimRadius.end(); - mAnimRadius = null; - } - - if (mAnimOpacity != null) { - mAnimOpacity.end(); - mAnimOpacity = null; - } - - if (mAnimX != null) { - mAnimX.end(); - mAnimX = null; - } - - if (mAnimY != null) { - mAnimY.end(); - mAnimY = null; - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) - private void exitSoftware(int radiusDuration, int opacityDuration) { - final ObjectAnimator radiusAnim = ObjectAnimator.ofFloat(this, "radiusGravity", 1); - radiusAnim.setDuration(radiusDuration); - radiusAnim.setInterpolator(DECEL_INTERPOLATOR); - - final ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity", 1); - xAnim.setDuration(radiusDuration); - xAnim.setInterpolator(DECEL_INTERPOLATOR); - - final ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity", 1); - yAnim.setDuration(radiusDuration); - yAnim.setInterpolator(DECEL_INTERPOLATOR); - - final ObjectAnimator opacityAnim = ObjectAnimator.ofFloat(this, "opacity", 0); - opacityAnim.setDuration(opacityDuration); - opacityAnim.setInterpolator(LINEAR_INTERPOLATOR); - opacityAnim.addListener(mAnimationListener); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - radiusAnim.setAutoCancel(true); - xAnim.setAutoCancel(true); - yAnim.setAutoCancel(true); - opacityAnim.setAutoCancel(true); - } - - mAnimRadius = radiusAnim; - mAnimOpacity = opacityAnim; - mAnimX = xAnim; - mAnimY = yAnim; - - radiusAnim.start(); - opacityAnim.start(); - xAnim.start(); - yAnim.start(); - } - - /** - * Cancels all animations. The caller is responsible for removing - * the ripple from the list of animating ripples. - */ - public void cancel() { - mCanceled = true; - cancelSoftwareAnimations(); - mCanceled = false; - } - - private void cancelSoftwareAnimations() { - if (mAnimRadius != null) { - mAnimRadius.cancel(); - mAnimRadius = null; - } - - if (mAnimOpacity != null) { - mAnimOpacity.cancel(); - mAnimOpacity = null; - } - - if (mAnimX != null) { - mAnimX.cancel(); - mAnimX = null; - } - - if (mAnimY != null) { - mAnimY.cancel(); - mAnimY = null; - } - } - - private void removeSelf() { - // The owner will invalidate itself. - if (!mCanceled) { - mOwner.removeRipple(this); - } - } - - private void invalidateSelf() { - mOwner.invalidateSelf(); - } - - private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - removeSelf(); - } - }; - - /** - * Interpolator with a smooth log deceleration - */ - private static final class LogInterpolator implements Interpolator { - @Override - public float getInterpolation(float input) { - return 1 - (float) Math.pow(400, -input * 1.4); - } - } -} diff --git a/app/src/main/java/com/hippo/effect/ripple/RippleBackground.java b/app/src/main/java/com/hippo/effect/ripple/RippleBackground.java deleted file mode 100644 index a7ab99696..000000000 --- a/app/src/main/java/com/hippo/effect/ripple/RippleBackground.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.effect.ripple; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ObjectAnimator; -import android.annotation.TargetApi; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.Rect; -import android.os.Build; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; - -import com.hippo.util.MathUtils; - -/** - * Draws a Material ripple. - */ -class RippleBackground { - private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); - - private static final float GLOBAL_SPEED = 1.0f; - private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0f / GLOBAL_SPEED; - private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MAX = 4.5f * GLOBAL_SPEED; - private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MIN = 1.5f * GLOBAL_SPEED; - private static final float WAVE_OUTER_OPACITY_ENTER_VELOCITY = 10.0f * GLOBAL_SPEED; - private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200f; - private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40f; - - private final RippleOwner mOwner; - - /** Bounds used for computing max radius. */ - private final Rect mBounds; - - /** Full-opacity color for drawing this ripple. */ - private int mColorOpaque; - - /** Maximum alpha value for drawing this ripple. */ - private int mColorAlpha; - - /** Maximum ripple radius. */ - private float mOuterRadius; - - /** Screen density used to adjust pixel-based velocities. */ - private float mDensity; - - // Software animators. - private ObjectAnimator mAnimOuterOpacity; - - // Software rendering properties. - private float mOuterOpacity = 0; - private float mOuterX; - private float mOuterY; - - /** Whether we have an explicit maximum radius. */ - private boolean mHasMaxRadius; - - /** - * Creates a new ripple. - */ - public RippleBackground(RippleOwner owner, Rect bounds) { - mOwner = owner; - mBounds = bounds; - } - - public void setup(int maxRadius, int color, float density) { - mColorOpaque = color | 0xFF000000; - mColorAlpha = Color.alpha(color) / 2; - - if (maxRadius != RippleOwner.RADIUS_AUTO) { - mHasMaxRadius = true; - mOuterRadius = maxRadius; - } else { - final float halfWidth = mBounds.width() / 2.0f; - final float halfHeight = mBounds.height() / 2.0f; - mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); - } - - mOuterX = 0; - mOuterY = 0; - mDensity = density; - } - - public void onHotspotBoundsChanged() { - if (!mHasMaxRadius) { - final float halfWidth = mBounds.width() / 2.0f; - final float halfHeight = mBounds.height() / 2.0f; - mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); - } - } - - public void setOuterOpacity(float a) { - mOuterOpacity = a; - invalidateSelf(); - } - - public float getOuterOpacity() { - return mOuterOpacity; - } - - /** - * Draws the ripple centered at (0,0) using the specified paint. - */ - public boolean draw(Canvas c, Paint p) { - return drawSoftware(c, p); - } - - public boolean shouldDraw() { - final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f); - return outerAlpha > 0 && mOuterRadius > 0; - } - - private boolean drawSoftware(Canvas c, Paint p) { - boolean hasContent = false; - - p.setColor(mColorOpaque); - final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f); - if (outerAlpha > 0 && mOuterRadius > 0) { - p.setAlpha(outerAlpha); - p.setStyle(Style.FILL); - c.drawCircle(mOuterX, mOuterY, mOuterRadius, p); - hasContent = true; - } - - return hasContent; - } - - /** - * Returns the maximum bounds of the ripple relative to the ripple center. - */ - public void getBounds(Rect bounds) { - final int outerX = (int) mOuterX; - final int outerY = (int) mOuterY; - final int r = (int) mOuterRadius + 1; - bounds.set(outerX - r, outerY - r, outerX + r, outerY + r); - } - - /** - * Starts the enter animation. - */ - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) - public void enter() { - cancel(); - - final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_ENTER_VELOCITY); - final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1); - outer.setDuration(outerDuration); - outer.setInterpolator(LINEAR_INTERPOLATOR); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - outer.setAutoCancel(true); - } - - mAnimOuterOpacity = outer; - - // Enter animations always run on the UI thread, since it's unlikely - // that anything interesting is happening until the user lifts their - // finger. - outer.start(); - } - - /** - * Starts the exit animation. - */ - public void exit() { - cancel(); - - // Scale the outer max opacity and opacity velocity based - // on the size of the outer radius. - final int opacityDuration = (int) (1000 / WAVE_OPACITY_DECAY_VELOCITY + 0.5f); - final float outerSizeInfluence = MathUtils.clamp( - (mOuterRadius - WAVE_OUTER_SIZE_INFLUENCE_MIN * mDensity) - / (WAVE_OUTER_SIZE_INFLUENCE_MAX * mDensity), 0, 1); - final float outerOpacityVelocity = MathUtils.lerp(WAVE_OUTER_OPACITY_EXIT_VELOCITY_MIN, - WAVE_OUTER_OPACITY_EXIT_VELOCITY_MAX, outerSizeInfluence); - - // Determine at what time the inner and outer opacity intersect. - // inner(t) = mOpacity - t * WAVE_OPACITY_DECAY_VELOCITY / 1000 - // outer(t) = mOuterOpacity + t * WAVE_OUTER_OPACITY_VELOCITY / 1000 - final int inflectionDuration = Math.max(0, (int) (1000 * (1 - mOuterOpacity) - / (WAVE_OPACITY_DECAY_VELOCITY + outerOpacityVelocity) + 0.5f)); - final int inflectionOpacity = (int) (mColorAlpha * (mOuterOpacity - + inflectionDuration * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f); - - exitSoftware(opacityDuration, inflectionDuration, inflectionOpacity); - } - - /** - * Jump all animations to their end state. The caller is responsible for - * removing the ripple from the list of animating ripples. - */ - public void jump() { - endSoftwareAnimations(); - } - - private void endSoftwareAnimations() { - if (mAnimOuterOpacity != null) { - mAnimOuterOpacity.end(); - mAnimOuterOpacity = null; - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) - private void exitSoftware(int opacityDuration, int inflectionDuration, int inflectionOpacity) { - final ObjectAnimator outerOpacityAnim; - if (inflectionDuration > 0) { - // Outer opacity continues to increase for a bit. - outerOpacityAnim = ObjectAnimator.ofFloat(this, - "outerOpacity", inflectionOpacity / 255.0f); - outerOpacityAnim.setDuration(inflectionDuration); - outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - outerOpacityAnim.setAutoCancel(true); - } - - // Chain the outer opacity exit animation. - final int outerDuration = opacityDuration - inflectionDuration; - if (outerDuration > 0) { - outerOpacityAnim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - final ObjectAnimator outerFadeOutAnim = ObjectAnimator.ofFloat( - RippleBackground.this, "outerOpacity", 0); - outerFadeOutAnim.setDuration(outerDuration); - outerFadeOutAnim.setInterpolator(LINEAR_INTERPOLATOR); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - outerFadeOutAnim.setAutoCancel(true); - } - - mAnimOuterOpacity = outerFadeOutAnim; - - outerFadeOutAnim.start(); - } - - @Override - public void onAnimationCancel(Animator animation) { - animation.removeListener(this); - } - }); - } - } else { - outerOpacityAnim = ObjectAnimator.ofFloat(this, "outerOpacity", 0); - outerOpacityAnim.setDuration(opacityDuration); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - outerOpacityAnim.setAutoCancel(true); - } - } - - mAnimOuterOpacity = outerOpacityAnim; - - outerOpacityAnim.start(); - } - - /** - * Cancel all animations. The caller is responsible for removing - * the ripple from the list of animating ripples. - */ - public void cancel() { - cancelSoftwareAnimations(); - } - - private void cancelSoftwareAnimations() { - if (mAnimOuterOpacity != null) { - mAnimOuterOpacity.cancel(); - mAnimOuterOpacity = null; - } - } - - private void invalidateSelf() { - mOwner.invalidateSelf(); - } -} diff --git a/app/src/main/java/com/hippo/effect/ripple/RippleDrawable.java b/app/src/main/java/com/hippo/effect/ripple/RippleDrawable.java deleted file mode 100644 index e6fe5f1f4..000000000 --- a/app/src/main/java/com/hippo/effect/ripple/RippleDrawable.java +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.effect.ripple; - -import android.annotation.TargetApi; -import android.content.res.ColorStateList; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.support.annotation.NonNull; - -import com.hippo.widget.Hotspotable; - -import java.util.Arrays; - -/** - * Drawable that shows a ripple effect in response to state changes. The - * anchoring position of the ripple for a given state may be specified by - * calling {@link #setHotspot(float, float)} with the corresponding state - * attribute identifier. - *

- * A touch feedback drawable may contain multiple child layers, including a - * special mask layer that is not drawn to the screen. A single layer may be set - * as the mask by specifying its android:id value as {@link android.R.id#mask}. - *

- * <!-- A red ripple masked against an opaque rectangle. --/>
- * <ripple android:color="#ffff0000">
- *   <item android:id="@android:id/mask"
- *         android:drawable="@android:color/white" />
- * <ripple />
- * 
- *

- * If a mask layer is set, the ripple effect will be masked against that layer - * before it is drawn over the composite of the remaining child layers. - *

- * If no mask layer is set, the ripple effect is masked against the composite - * of the child layers. - *

- * <!-- A blue ripple drawn atop a black rectangle. --/>
- * <ripple android:color="#ff00ff00">
- *   <item android:drawable="@android:color/black" />
- * <ripple />
- *
- * <!-- A red ripple drawn atop a drawable resource. --/>
- * <ripple android:color="#ff00ff00">
- *   <item android:drawable="@drawable/my_drawable" />
- * <ripple />
- * 
- *

- * If no child layers or mask is specified and the ripple is set as a View - * background, the ripple will be drawn atop the first available parent - * background within the View's hierarchy. In this case, the drawing region - * may extend outside of the Drawable bounds. - *

- * <!-- An unbounded green ripple. --/>
- * <ripple android:color="#ff0000ff" />
- * 
- * - * @attr ref android.R.styleable#RippleDrawable_color - */ -public class RippleDrawable extends Drawable implements RippleOwner, Hotspotable { - @SuppressWarnings("unused") - private static final String TAG = RippleDrawable.class.getSimpleName(); - - /** The maximum number of ripples supported. */ - private static final int MAX_RIPPLES = 10; - - /** Current ripple effect bounds, used to constrain ripple effects. */ - private final Rect mHotspotBounds = new Rect(); - - /** The current background. May be actively animating or pending entry. */ - private RippleBackground mBackground; - - /** Whether we expect to draw a background when visible. */ - private boolean mBackgroundActive; - - /** The current ripple. May be actively animating or pending entry. */ - private Ripple mRipple; - - /** Whether we expect to draw a ripple when visible. */ - private boolean mRippleActive; - - // Hotspot coordinates that are awaiting activation. - private float mPendingX; - private float mPendingY; - private boolean mHasPending; - - /** - * Lazily-created array of actively animating ripples. Inactive ripples are - * pruned during draw(). The locations of these will not change. - */ - private Ripple[] mExitingRipples; - private int mExitingRipplesCount = 0; - - /** Paint used to control appearance of ripples. */ - private Paint mRipplePaint; - - /** Target density of the display into which ripples are drawn. */ - private final float mDensity = 1.0f; - - /** Whether bounds are being overridden. */ - private boolean mOverrideBounds; - - /** - * Whether the next draw MUST draw something to canvas. Used to work around - * a bug in hardware invalidation following a render thread-accelerated - * animation. - */ - private boolean mNeedsDraw; - - private ColorStateList mColor = ColorStateList.valueOf(Color.MAGENTA); - - private int mMaxRadius = RADIUS_AUTO; - - private final Drawable mContent; - - RippleDrawable(ColorStateList color, Drawable content) { - setColor(color); - - mContent = content; - } - - @Override - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void jumpToCurrentState() { - if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { - super.jumpToCurrentState(); - } - - boolean needsDraw = false; - - if (mRipple != null) { - mRipple.jump(); - } - - if (mBackground != null) { - mBackground.jump(); - } - - needsDraw |= cancelExitingRipples(); - - mNeedsDraw = needsDraw; - invalidateSelf(); - } - - private boolean cancelExitingRipples() { - final int count = mExitingRipplesCount; - final Ripple[] ripples = mExitingRipples; - for (int i = 0; i < count; i++) { - ripples[i].cancel(); - } - - if (ripples != null) { - Arrays.fill(ripples, 0, count, null); - } - mExitingRipplesCount = 0; - - return false; - } - - @Override - public void setAlpha(int alpha) { - mColor.withAlpha(alpha); - } - - @Override - public int getAlpha() { - return Color.alpha(mColor.getDefaultColor()); - } - - @Override - public void setColorFilter(ColorFilter cf) { - //TODO Paint.setColorFilter(filter) ? - } - - @Override - public int getOpacity() { - // Worst-case scenario. - return PixelFormat.TRANSLUCENT; - } - - @Override - protected boolean onStateChange(int[] stateSet) { - boolean changed = false; - if (mContent != null) - changed |= mContent.setState(stateSet); - - boolean enabled = false; - boolean pressed = false; - boolean focused = false; - - for (int state : stateSet) { - if (state == android.R.attr.state_enabled) { - enabled = true; - } - if (state == android.R.attr.state_focused) { - focused = true; - } - if (state == android.R.attr.state_pressed) { - pressed = true; - } - } - - setRippleActive(enabled && pressed); - setBackgroundActive(focused || (enabled && pressed)); - - return changed; - } - - private void setRippleActive(boolean active) { - if (mRippleActive != active) { - mRippleActive = active; - if (active) { - tryRippleEnter(); - } else { - tryRippleExit(); - } - } - } - - private void setBackgroundActive(boolean active) { - if (mBackgroundActive != active) { - mBackgroundActive = active; - if (active) { - tryBackgroundEnter(); - } else { - tryBackgroundExit(); - } - } - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - - if (!mOverrideBounds) { - mHotspotBounds.set(bounds); - onHotspotBoundsChanged(); - } - - if (mContent != null) - mContent.setBounds(bounds); - - invalidateSelf(); - } - - @Override - public boolean setVisible(boolean visible, boolean restart) { - final boolean changed = super.setVisible(visible, restart); - - if (!visible) { - clearHotspots(); - } else if (changed) { - // If we just became visible, ensure the background and ripple - // visibilities are consistent with their internal states. - if (mRippleActive) { - tryRippleEnter(); - } - - if (mBackgroundActive) { - tryBackgroundEnter(); - } - } - - return changed; - } - - @Override - public boolean isStateful() { - return true; - } - - public void setColor(ColorStateList color) { - int alpha = Color.alpha(color.getDefaultColor()); - mColor = color.withAlpha((int) (alpha * (1 - 0.001f * alpha))); - invalidateSelf(); - } - - @Override - public void setHotspot(float x, float y) { - if (mRipple == null || mBackground == null) { - mPendingX = x; - mPendingY = y; - mHasPending = true; - } - - if (mRipple != null) { - mRipple.move(x, y); - } - } - - /** - * Creates an active hotspot at the specified location. - */ - private void tryBackgroundEnter() { - if (mBackground == null) { - mBackground = new RippleBackground(this, mHotspotBounds); - } - - final int color = mColor.getColorForState(getState(), Color.TRANSPARENT); - mBackground.setup(mMaxRadius, color, mDensity); - mBackground.enter(); - } - - private void tryBackgroundExit() { - if (mBackground != null) { - // Don't null out the background, we need it to draw! - mBackground.exit(); - } - } - - /** - * Attempts to start an enter animation for the active hotspot. Fails if - * there are too many animating ripples. - */ - private void tryRippleEnter() { - if (mExitingRipplesCount >= MAX_RIPPLES) { - // This should never happen unless the user is tapping like a maniac - // or there is a bug that's preventing ripples from being removed. - return; - } - - if (mRipple == null) { - final float x; - final float y; - if (mHasPending) { - mHasPending = false; - x = mPendingX; - y = mPendingY; - } else { - x = mHotspotBounds.exactCenterX(); - y = mHotspotBounds.exactCenterY(); - } - mRipple = new Ripple(this, mHotspotBounds, x, y); - } - - final int color = mColor.getColorForState(getState(), Color.TRANSPARENT); - mRipple.setup(mMaxRadius, color, mDensity); - mRipple.enter(); - } - - /** - * Attempts to start an exit animation for the active hotspot. Fails if - * there is no active hotspot. - */ - private void tryRippleExit() { - if (mRipple != null) { - if (mExitingRipples == null) { - mExitingRipples = new Ripple[MAX_RIPPLES]; - } - mExitingRipples[mExitingRipplesCount++] = mRipple; - mRipple.exit(); - mRipple = null; - } - } - - /** - * Cancels and removes the active ripple, all exiting ripples, and the - * background. Nothing will be drawn after this method is called. - */ - private void clearHotspots() { - boolean needsDraw = false; - - if (mRipple != null) { - mRipple.cancel(); - mRipple = null; - } - - if (mBackground != null) { - mBackground.cancel(); - mBackground = null; - } - - needsDraw |= cancelExitingRipples(); - - mNeedsDraw = needsDraw; - invalidateSelf(); - } - - @Override - public void setHotspotBounds(int left, int top, int right, int bottom) { - mOverrideBounds = true; - mHotspotBounds.set(left, top, right, bottom); - - onHotspotBoundsChanged(); - } - - /** @hide */ - public void getHotspotBounds(Rect outRect) { - outRect.set(mHotspotBounds); - } - - /** - * Notifies all the animating ripples that the hotspot bounds have changed. - */ - private void onHotspotBoundsChanged() { - final int count = mExitingRipplesCount; - final Ripple[] ripples = mExitingRipples; - for (int i = 0; i < count; i++) { - ripples[i].onHotspotBoundsChanged(); - } - - if (mRipple != null) { - mRipple.onHotspotBoundsChanged(); - } - - if (mBackground != null) { - mBackground.onHotspotBoundsChanged(); - } - } - - @Override - public void draw(@NonNull Canvas canvas) { - final boolean drawNonMaskContent = mContent != null; - final Rect bounds = getDirtyBounds(); - final int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG); - canvas.clipRect(bounds); - - // If we have content, draw it into a layer first. - if (drawNonMaskContent) { - drawContentLayer(canvas, bounds); - } - - // If we have a background and a non-opaque mask, draw the masking layer. - drawBackgroundLayer(canvas, bounds); - - // If we have ripples and a non-opaque mask, draw the masking layer. - drawRippleLayer(canvas, bounds); - - // If we failed to draw anything and we just canceled animations, at - // least draw a color so that hardware invalidation works correctly. - if (mNeedsDraw) { - canvas.drawColor(Color.TRANSPARENT); - - // Request another draw so we can avoid adding a transparent layer - // during the next display list refresh. - invalidateSelf(); - } - mNeedsDraw = false; - - canvas.restoreToCount(saveCount); - } - - /** - * Removes a ripple from the exiting ripple list. - * - * @param ripple the ripple to remove - */ - @Override - public void removeRipple(Ripple ripple) { - // Ripple ripple ripple ripple. Ripple ripple. - final Ripple[] ripples = mExitingRipples; - final int count = mExitingRipplesCount; - final int index = getRippleIndex(ripple); - if (index >= 0) { - System.arraycopy(ripples, index + 1, ripples, index, count - (index + 1)); - ripples[count - 1] = null; - mExitingRipplesCount--; - - invalidateSelf(); - } - } - - private int getRippleIndex(Ripple ripple) { - final Ripple[] ripples = mExitingRipples; - final int count = mExitingRipplesCount; - for (int i = 0; i < count; i++) { - if (ripples[i] == ripple) { - return i; - } - } - return -1; - } - - private void drawContentLayer(Canvas canvas, Rect bounds) { - mContent.draw(canvas); - } - - private void drawBackgroundLayer( - Canvas canvas, Rect bounds) { - if (mBackground != null && mBackground.shouldDraw()) { - final float x = mHotspotBounds.exactCenterX(); - final float y = mHotspotBounds.exactCenterY(); - canvas.translate(x, y); - mBackground.draw(canvas, getRipplePaint()); - canvas.translate(-x, -y); - } - } - - private void drawRippleLayer(Canvas canvas, Rect bounds) { - int restoreTranslate = -1; - - // Translate the canvas to the current hotspot bounds. - restoreTranslate = canvas.save(); - canvas.translate(mHotspotBounds.exactCenterX(), mHotspotBounds.exactCenterY()); - - // Draw ripples and update the animating ripples array. - final int count = mExitingRipplesCount; - final Ripple[] ripples = mExitingRipples; - for (int i = 0; i <= count; i++) { - final Ripple ripple; - if (i < count) { - ripple = ripples[i]; - } else if (mRipple != null) { - ripple = mRipple; - } else { - continue; - } - - ripple.draw(canvas, getRipplePaint()); - } - - // Always restore the translation. - if (restoreTranslate >= 0) { - canvas.restoreToCount(restoreTranslate); - } - } - - private Paint getRipplePaint() { - if (mRipplePaint == null) { - mRipplePaint = new Paint(); - mRipplePaint.setAntiAlias(true); - } - return mRipplePaint; - } - - @Override - public Rect getDirtyBounds() { - return getBounds(); - } - - /** - * Sets the maximum ripple radius in pixels. The default value of - * {@link #RADIUS_AUTO} defines the radius as the distance from the center - * of the drawable bounds (or hotspot bounds, if specified) to a corner. - * - * @param maxRadius the maximum ripple radius in pixels or - * {@link #RADIUS_AUTO} to automatically determine the maximum - * radius based on the bounds - * @see #getMaxRadius() - * @see #setHotspotBounds(int, int, int, int) - * @hide - */ - public void setMaxRadius(int maxRadius) { - if (maxRadius != RADIUS_AUTO && maxRadius < 0) { - throw new IllegalArgumentException("maxRadius must be RADIUS_AUTO or >= 0"); - } - - mMaxRadius = maxRadius; - } - - /** - * @return the maximum ripple radius in pixels, or {@link #RADIUS_AUTO} if - * the radius is determined automatically - * @see #setMaxRadius(int) - * @hide - */ - public int getMaxRadius() { - return mMaxRadius; - } -} diff --git a/app/src/main/java/com/hippo/effect/ripple/RippleOwner.java b/app/src/main/java/com/hippo/effect/ripple/RippleOwner.java deleted file mode 100644 index ebd986589..000000000 --- a/app/src/main/java/com/hippo/effect/ripple/RippleOwner.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.effect.ripple; - - -public interface RippleOwner { - /** - * Constant for automatically determining the maximum ripple radius. - */ - int RADIUS_AUTO = -1; - - void removeRipple(Ripple ripple); - - void invalidateSelf(); - -} diff --git a/app/src/main/java/com/hippo/effect/ripple/RippleSalon.java b/app/src/main/java/com/hippo/effect/ripple/RippleSalon.java deleted file mode 100644 index 353808a36..000000000 --- a/app/src/main/java/com/hippo/effect/ripple/RippleSalon.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.effect.ripple; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.view.View; - -import com.hippo.ehviewer.R; -import com.hippo.widget.HotspotTouchHelper; - -public final class RippleSalon { - - public static void addRipple(View c, boolean dark) { - Resources resources = c.getContext().getResources(); - ColorStateList color = ColorStateList.valueOf( - resources.getColor(dark ? R.color.ripple_material_dark : R.color.ripple_material_light)); - addRipple(c, color); - } - - public static void addRipple(View v, ColorStateList color) { - addRipple(v, color, v.getBackground()); - } - - @SuppressWarnings("deprecation") - public static void addRipple(View v, ColorStateList color, Drawable content) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - RippleDrawable rippleDrawable = new RippleDrawable(color, content); - v.setOnTouchListener(new HotspotTouchHelper(rippleDrawable)); - v.setBackgroundDrawable(rippleDrawable); - } else { - android.graphics.drawable.RippleDrawable rippleDrawable = - new android.graphics.drawable.RippleDrawable(color, content, new ColorDrawable(Color.BLACK)); - v.setBackground(rippleDrawable); - } - } - - public static Drawable generateRippleDrawable(Context context, boolean dark) { - ColorStateList color = ColorStateList.valueOf( - context.getResources().getColor(dark ? R.color.ripple_material_dark : R.color.ripple_material_light)); - return generateRippleDrawable(color); - } - - public static Drawable generateRippleDrawable(ColorStateList color) { - return generateRippleDrawable(color, null); - } - - public static Drawable generateRippleDrawable(ColorStateList color, Drawable content) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return new RippleDrawable(color, content); - } else { - return new android.graphics.drawable.RippleDrawable(color, content, new ColorDrawable(Color.BLACK)); - } - } -} diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/SignInScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/SignInScene.java index 591f8bb39..64b6939a1 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/SignInScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/SignInScene.java @@ -24,11 +24,11 @@ import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.TextView; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.Constants; import com.hippo.ehviewer.R; import com.hippo.ehviewer.client.EhClient; import com.hippo.ehviewer.util.Config; +import com.hippo.rippleold.RippleSalon; import com.hippo.scene.Scene; import com.hippo.util.Messenger; diff --git a/app/src/main/java/com/hippo/ehviewer/widget/DrawerLeftPanel.java b/app/src/main/java/com/hippo/ehviewer/widget/DrawerLeftPanel.java index 4c644d347..6297d181b 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/DrawerLeftPanel.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/DrawerLeftPanel.java @@ -29,10 +29,10 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.facebook.drawee.view.SimpleDraweeView; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.Constants; import com.hippo.ehviewer.R; import com.hippo.ehviewer.util.Config; +import com.hippo.rippleold.RippleSalon; import com.hippo.util.FrescoUtils; import com.hippo.util.Messenger; import com.hippo.widget.DrawerListView; diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java index 3bff7cf7b..f1cd0c92e 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java @@ -35,9 +35,9 @@ import android.widget.CompoundButton; import android.widget.FrameLayout; import android.widget.TextView; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.R; import com.hippo.ehviewer.data.ListUrlBuilder; +import com.hippo.rippleold.RippleSalon; import com.hippo.scene.SimpleDialog; import com.hippo.util.UiUtils; import com.hippo.util.ViewUtils; diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SelectSearchImageLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/SelectSearchImageLayout.java index 7bfed1907..c56ef60ab 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/SelectSearchImageLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/SelectSearchImageLayout.java @@ -31,8 +31,8 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.R; +import com.hippo.rippleold.RippleSalon; import com.hippo.util.ViewUtils; public class SelectSearchImageLayout extends LinearLayout implements View.OnClickListener{ diff --git a/app/src/main/java/com/hippo/scene/AppbarScene.java b/app/src/main/java/com/hippo/scene/AppbarScene.java index 409ddd740..2f3cb563f 100644 --- a/app/src/main/java/com/hippo/scene/AppbarScene.java +++ b/app/src/main/java/com/hippo/scene/AppbarScene.java @@ -26,8 +26,8 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.TextView; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.R; +import com.hippo.rippleold.RippleSalon; import com.hippo.util.ViewUtils; import com.hippo.widget.SimpleImageView; diff --git a/app/src/main/java/com/hippo/scene/SceneDialogView.java b/app/src/main/java/com/hippo/scene/SceneDialogView.java index 45a224851..0f502cd2b 100644 --- a/app/src/main/java/com/hippo/scene/SceneDialogView.java +++ b/app/src/main/java/com/hippo/scene/SceneDialogView.java @@ -22,9 +22,9 @@ import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; +import com.hippo.hotspot.HotspotTouchHelper; +import com.hippo.hotspot.Hotspotable; import com.hippo.util.ViewUtils; -import com.hippo.widget.HotspotTouchHelper; -import com.hippo.widget.Hotspotable; public class SceneDialogView extends SceneView implements View.OnClickListener, Hotspotable { diff --git a/app/src/main/java/com/hippo/scene/SimpleDialog.java b/app/src/main/java/com/hippo/scene/SimpleDialog.java index b90714e40..aac884fe7 100644 --- a/app/src/main/java/com/hippo/scene/SimpleDialog.java +++ b/app/src/main/java/com/hippo/scene/SimpleDialog.java @@ -33,8 +33,8 @@ import android.widget.ScrollView; import android.widget.Space; import android.widget.TextView; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.R; +import com.hippo.rippleold.RippleSalon; import com.hippo.util.ViewUtils; public class SimpleDialog extends SceneDialog implements View.OnClickListener, diff --git a/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java b/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java index 3cf89b073..1884767ec 100644 --- a/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java +++ b/app/src/main/java/com/hippo/scene/preference/PreferenceHeaderScene.java @@ -26,8 +26,8 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.R; +import com.hippo.rippleold.RippleSalon; import com.hippo.scene.AppbarScene; import com.hippo.scene.SimpleCurtain; import com.hippo.scene.StageActivity; @@ -73,7 +73,7 @@ public class PreferenceHeaderScene extends AppbarScene { } } }); - mRecyclerView.setSelector(RippleSalon.generateRippleDrawable(mActivity, false)); + mRecyclerView.setSelector(RippleSalon.generateRippleDrawable(false)); } @Override diff --git a/app/src/main/java/com/hippo/scene/preference/PreferenceScene.java b/app/src/main/java/com/hippo/scene/preference/PreferenceScene.java index d3dc9750b..e6f8b0471 100644 --- a/app/src/main/java/com/hippo/scene/preference/PreferenceScene.java +++ b/app/src/main/java/com/hippo/scene/preference/PreferenceScene.java @@ -22,8 +22,8 @@ import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; -import com.hippo.effect.ripple.RippleSalon; import com.hippo.ehviewer.R; +import com.hippo.rippleold.RippleSalon; import com.hippo.scene.AppbarScene; import com.hippo.util.ViewUtils; import com.hippo.widget.recyclerview.EasyRecyclerView; @@ -55,7 +55,7 @@ public class PreferenceScene extends AppbarScene { mRecyclerView.setAdapter(mAdapter); mRecyclerView.setLayoutManager(new LinearLayoutManager(getStageActivity())); mRecyclerView.setOnItemClickListener(new PreferenceItemClickListener()); - mRecyclerView.setSelector(RippleSalon.generateRippleDrawable(getStageActivity(), false)); + mRecyclerView.setSelector(RippleSalon.generateRippleDrawable(false)); mRecyclerView.setOnDrawSelectorListener(new PreferencesDrawSelectorListener()); mRecyclerView.setClipToPadding(false); } diff --git a/app/src/main/java/com/hippo/util/DrawableUtils.java b/app/src/main/java/com/hippo/util/DrawableUtils.java index fdf89b048..c8adcc13e 100644 --- a/app/src/main/java/com/hippo/util/DrawableUtils.java +++ b/app/src/main/java/com/hippo/util/DrawableUtils.java @@ -19,7 +19,7 @@ package com.hippo.util; import android.graphics.drawable.Drawable; import android.os.Build; -import com.hippo.widget.Hotspotable; +import com.hippo.hotspot.Hotspotable; public class DrawableUtils { diff --git a/app/src/main/java/com/hippo/widget/CheckTextView.java b/app/src/main/java/com/hippo/widget/CheckTextView.java index f90e40faf..b093d46cf 100644 --- a/app/src/main/java/com/hippo/widget/CheckTextView.java +++ b/app/src/main/java/com/hippo/widget/CheckTextView.java @@ -33,6 +33,8 @@ import android.widget.TextView; import com.hippo.animation.SimpleAnimatorListener; import com.hippo.ehviewer.R; +import com.hippo.hotspot.HotspotTouchHelper; +import com.hippo.hotspot.Hotspotable; import com.hippo.util.AnimationUtils; import com.hippo.util.MathUtils; diff --git a/app/src/main/java/com/hippo/widget/HotspotTouchHelper.java b/app/src/main/java/com/hippo/widget/HotspotTouchHelper.java deleted file mode 100644 index 9f7d70111..000000000 --- a/app/src/main/java/com/hippo/widget/HotspotTouchHelper.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.widget; - -import android.annotation.TargetApi; -import android.os.Build; -import android.view.MotionEvent; -import android.view.TouchDelegate; -import android.view.View; -import android.view.ViewConfiguration; - -public class HotspotTouchHelper implements View.OnTouchListener { - - private final Hotspotable mOwner; - - private boolean mPrePressed = false; - private boolean mHasPerformedLongPress = false; - - private CheckForLongPress mPendingCheckForLongPress = null; - private CheckForTap mPendingCheckForTap = null; - private PerformClick mPerformClick = null; - private UnsetPressedState mUnsetPressedState = null; - - /** - * Cache the touch slop from the context that created the view. - */ - private int mTouchSlop = -1; - - public HotspotTouchHelper(Hotspotable owner){ - mOwner = owner; - } - - @Override - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public boolean onTouch(View v, MotionEvent event) { - final float x = event.getX(); - final float y = event.getY(); - - if (event.getAction() == MotionEvent.ACTION_DOWN || - event.getAction() == MotionEvent.ACTION_MOVE) - mOwner.setHotspot(x, y); - - if (!v.isEnabled()) { - if (event.getAction() == MotionEvent.ACTION_UP && v.isPressed()) { - v.setPressed(false); - } - // A disabled view that is clickable still consumes the touch - // events, it just doesn't respond to them. - return (v.isClickable() || v.isLongClickable()); - } - - TouchDelegate touchDelegate = v.getTouchDelegate(); - if (touchDelegate != null) { - if (touchDelegate.onTouchEvent(event)) { - return true; - } - } - - if (v.isClickable() || v.isLongClickable()) { - switch (event.getAction()) { - case MotionEvent.ACTION_UP: - if (v.isPressed() || mPrePressed) { - // take focus if we don't have it already and we should in - // touch mode. - boolean focusTaken = false; - if (v.isFocusable() && v.isFocusableInTouchMode() && !v.isFocused()) { - focusTaken = v.requestFocus(); - } - - if (mPrePressed) { - // The button is being released before we actually - // showed it as pressed. Make it show the pressed - // state now (before scheduling the click) to ensure - // the user sees it. - setPressed(v, true, x, y); - } - - if (!mHasPerformedLongPress) { - // This is a tap, so remove the longpress check - removeLongPressCallback(v); - - // Only perform take click actions if we were in the pressed state - if (!focusTaken) { - // Use a Runnable and post this rather than calling - // performClick directly. This lets other visual state - // of the view update before click actions start. - if (mPerformClick == null) { - mPerformClick = new PerformClick(v); - } - if (!v.post(mPerformClick)) { - v.performClick(); - } - } - } - - if (mUnsetPressedState == null) { - mUnsetPressedState = new UnsetPressedState(v); - } - - if (mPrePressed) { - v.postDelayed(mUnsetPressedState, - ViewConfiguration.getPressedStateDuration()); - } else if (!v.post(mUnsetPressedState)) { - // If the post failed, unpress right now - mUnsetPressedState.run(); - } - - removeTapCallback(v); - } - break; - - case MotionEvent.ACTION_DOWN: - mHasPerformedLongPress = false; - - if (performButtonActionOnTouchDown(v, event)) { - break; - } - - mPrePressed = true; - if (mPendingCheckForTap == null) { - mPendingCheckForTap = new CheckForTap(v); - } - mPendingCheckForTap.x = event.getX(); - mPendingCheckForTap.y = event.getY(); - v.postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); - break; - - case MotionEvent.ACTION_CANCEL: - v.setPressed(false); - removeTapCallback(v); - removeLongPressCallback(v); - break; - - case MotionEvent.ACTION_MOVE: - mOwner.setHotspot(x, y); - - if (mTouchSlop == -1) - mTouchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop(); - - // Be lenient about moving outside of buttons - if (!pointInView(v, x, y, mTouchSlop)) { - // Outside button - removeTapCallback(v); - if (v.isPressed()) { - // Remove any future long press/tap checks - removeLongPressCallback(v); - - v.setPressed(false); - } - } - break; - } - - return true; - } - - return false; - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private void setPressed(View v, boolean pressed, float x, float y){ - v.setPressed(pressed); - mOwner.setHotspot(x, y); - } - - /** - * Utility method to determine whether the given point, in local coordinates, - * is inside the view, where the area of the view is expanded by the slop factor. - * This method is called while processing touch-move events to determine if the event - * is still within the view. - */ - public boolean pointInView(View v, float localX, float localY, float slop) { - return localX >= -slop && localY >= -slop && localX < ((v.getRight() - v.getLeft()) + slop) && - localY < ((v.getBottom() - v.getTop()) + slop); - } - - /** - * Performs button-related actions during a touch down event. - * - * @param event The event. - * @return True if the down was consumed. - */ - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) - protected boolean performButtonActionOnTouchDown(View v, MotionEvent event) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { - if (v.showContextMenu()) { - return true; - } - } - } - return false; - } - - /** - * Remove the longpress detection timer. - */ - private void removeLongPressCallback(View v) { - if (mPendingCheckForLongPress != null) { - v.removeCallbacks(mPendingCheckForLongPress); - } - } - - /** - * Remove the tap detection timer. - */ - private void removeTapCallback(View v) { - if (mPendingCheckForTap != null) { - mPrePressed = false; - v.removeCallbacks(mPendingCheckForTap); - } - } - - private void checkForLongClick(View v, int delayOffset) { - if (v.isLongClickable()) { - mHasPerformedLongPress = false; - - if (mPendingCheckForLongPress == null) { - mPendingCheckForLongPress = new CheckForLongPress(v); - } - v.postDelayed(mPendingCheckForLongPress, - ViewConfiguration.getLongPressTimeout() - delayOffset); - } - } - - private final class CheckForLongPress implements Runnable { - - private final View mView; - - public CheckForLongPress(View v) { - mView = v; - } - - @Override - public void run() { - if (mView.isPressed() && (mView.getParent() != null)) { - if (mView.performLongClick()) { - mHasPerformedLongPress = true; - } - } - } - } - - private final class CheckForTap implements Runnable { - public float x; - public float y; - private final View mView; - - public CheckForTap(View v) { - mView = v; - } - - @Override - public void run() { - mPrePressed = false; - setPressed(mView, true, x, y); - checkForLongClick(mView, ViewConfiguration.getTapTimeout()); - } - } - - private final class PerformClick implements Runnable { - private final View mView; - - public PerformClick(View v) { - mView = v; - } - - @Override - public void run() { - mView.performClick(); - } - } - - private final class UnsetPressedState implements Runnable { - private final View mView; - - public UnsetPressedState(View v) { - mView = v; - } - - @Override - public void run() { - mView.setPressed(false); - } - } -} diff --git a/app/src/main/java/com/hippo/widget/Hotspotable.java b/app/src/main/java/com/hippo/widget/Hotspotable.java deleted file mode 100644 index 32b9ce4f5..000000000 --- a/app/src/main/java/com/hippo/widget/Hotspotable.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.widget; - -public interface Hotspotable { - - void setHotspot(float x, float y); -} diff --git a/hotspot b/hotspot new file mode 160000 index 000000000..1c2b4d616 --- /dev/null +++ b/hotspot @@ -0,0 +1 @@ +Subproject commit 1c2b4d616029a128ea5300b26ff85425ee055ee5 diff --git a/rippleold b/rippleold new file mode 160000 index 000000000..0acfd74ab --- /dev/null +++ b/rippleold @@ -0,0 +1 @@ +Subproject commit 0acfd74abd353dbf69f3ec9916f6aa52b12e7b33 diff --git a/settings.gradle b/settings.gradle index 790ceba2b..8177c0aa2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':unifile', ':vectorold' +include ':app', ':unifile', ':vectorold', ':hotspot', ':rippleold'