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'