diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryPreviewsScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryPreviewsScene.java
index 76b1abab9..031024cae 100644
--- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryPreviewsScene.java
+++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryPreviewsScene.java
@@ -36,6 +36,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.android.material.slider.Slider;
import com.hippo.easyrecyclerview.EasyRecyclerView;
import com.hippo.easyrecyclerview.MarginItemDecoration;
import com.hippo.ehviewer.EhApplication;
@@ -53,7 +54,6 @@ import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.SceneFragment;
import com.hippo.widget.ContentLayout;
import com.hippo.widget.LoadImageView;
-import com.hippo.widget.Slider;
import com.hippo.widget.recyclerview.AutoGridLayoutManager;
import com.hippo.yorozuya.AssertUtils;
import com.hippo.yorozuya.LayoutUtils;
@@ -209,7 +209,7 @@ public class GalleryPreviewsScene extends ToolbarScene {
return true;
}
int pages = mHelper.getPages();
- if (pages > 0 && mHelper.canGoTo()) {
+ if (pages > 1 && mHelper.canGoTo()) {
GoToDialogHelper helper = new GoToDialogHelper(pages, mHelper.getPageForTop());
AlertDialog dialog = new MaterialAlertDialogBuilder(context).setTitle(R.string.go_to)
.setView(R.layout.dialog_go_to)
@@ -418,8 +418,8 @@ public class GalleryPreviewsScene extends ToolbarScene {
((TextView) ViewUtils.$$(dialog, R.id.start)).setText(String.format(Locale.US, "%d", 1));
((TextView) ViewUtils.$$(dialog, R.id.end)).setText(String.format(Locale.US, "%d", mPages));
mSlider = (Slider) ViewUtils.$$(dialog, R.id.slider);
- mSlider.setRange(1, mPages);
- mSlider.setProgress(mCurrentPage + 1);
+ mSlider.setValueTo(mPages);
+ mSlider.setValue(mCurrentPage + 1);
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this);
dialog.setOnDismissListener(this);
@@ -431,7 +431,7 @@ public class GalleryPreviewsScene extends ToolbarScene {
return;
}
- int page = mSlider.getProgress() - 1;
+ int page = (int) (mSlider.getValue() - 1);
if (page >= 0 && page < mPages && mHelper != null) {
mHelper.goTo(page);
if (mDialog != null) {
diff --git a/app/src/main/java/com/hippo/widget/Slider.java b/app/src/main/java/com/hippo/widget/Slider.java
deleted file mode 100644
index 7c37eb3ad..000000000
--- a/app/src/main/java/com/hippo/widget/Slider.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright 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.animation.ValueAnimator;
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.widget.PopupWindow;
-import android.widget.RelativeLayout;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.widget.AppCompatImageView;
-import androidx.core.graphics.drawable.DrawableCompat;
-
-import com.hippo.ehviewer.R;
-import com.hippo.yorozuya.AnimationUtils;
-import com.hippo.yorozuya.LayoutUtils;
-import com.hippo.yorozuya.MathUtils;
-import com.hippo.yorozuya.SimpleHandler;
-
-public class Slider extends View {
-
- private static final char[] CHARACTERS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
- };
-
- private static final int BUBBLE_WIDTH = 26;
- private static final int BUBBLE_HEIGHT = 32;
- private final RectF mLeftRectF = new RectF();
- private final RectF mRightRectF = new RectF();
- private final int[] mTemp = new int[2];
- private Context mContext;
- private Paint mPaint;
- private Paint mBgPaint;
- private PopupWindow mPopup;
- private BubbleView mBubble;
- private int mStart;
- private int mEnd;
- private int mProgress;
- private float mPercent;
- private int mDrawProgress;
- private float mDrawPercent;
- private int mTargetProgress;
- private float mThickness;
- private float mRadius;
- private float mCharWidth;
- private float mCharHeight;
- private int mBubbleWidth;
- private int mBubbleHeight;
- private int mBubbleMinWidth;
- private int mBubbleMinHeight;
- private int mPopupX;
- private int mPopupY;
- private int mPopupWidth;
- private boolean mReverse = false;
-
- private boolean mShowBubble;
-
- private float mDrawBubbleScale = 0f;
-
- private ValueAnimator mProgressAnimation;
- private ValueAnimator mBubbleScaleAnimation;
-
- private OnSetProgressListener mListener;
-
- private CheckForShowBubble mCheckForShowBubble;
-
- public Slider(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context, attrs);
- }
-
- public Slider(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context, attrs);
- }
-
- @SuppressWarnings("deprecation")
- private void init(Context context, AttributeSet attrs) {
- mContext = context;
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- textPaint.setTextAlign(Paint.Align.CENTER);
-
- Resources resources = context.getResources();
- mBubbleMinWidth = resources.getDimensionPixelOffset(R.dimen.slider_bubble_width);
- mBubbleMinHeight = resources.getDimensionPixelOffset(R.dimen.slider_bubble_height);
-
- mBubble = new BubbleView(context, textPaint);
- mBubble.setScaleX(0.0f);
- mBubble.setScaleY(0.0f);
- RelativeLayout relativeLayout = new RelativeLayout(context);
- relativeLayout.addView(mBubble);
- relativeLayout.setBackgroundDrawable(null);
- mPopup = new PopupWindow(relativeLayout);
- mPopup.setOutsideTouchable(false);
- mPopup.setTouchable(false);
- mPopup.setFocusable(false);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Slider);
- textPaint.setColor(a.getColor(R.styleable.Slider_textColor, Color.WHITE));
- textPaint.setTextSize(a.getDimensionPixelSize(R.styleable.Slider_textSize, 12));
-
- updateTextSize();
-
- setRange(a.getInteger(R.styleable.Slider_start, 0), a.getInteger(R.styleable.Slider_end, 0));
- setProgress(a.getInteger(R.styleable.Slider_slider_progress, 0));
- mThickness = a.getDimension(R.styleable.Slider_thickness, 2);
- mRadius = a.getDimension(R.styleable.Slider_radius, 6);
-
- mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-
- a.recycle();
-
- mProgressAnimation = new ValueAnimator();
- mProgressAnimation.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR);
- mProgressAnimation.addUpdateListener(animation -> {
- float value = (Float) animation.getAnimatedValue();
- mDrawPercent = value;
- mDrawProgress = Math.round(MathUtils.lerp((float) mStart, mEnd, value));
- updateBubblePosition();
- mBubble.setProgress(mDrawProgress);
- invalidate();
- });
-
- mBubbleScaleAnimation = new ValueAnimator();
- mBubbleScaleAnimation.addUpdateListener(animation -> {
- float value = (Float) animation.getAnimatedValue();
- mDrawBubbleScale = value;
- mBubble.setScaleX(value);
- mBubble.setScaleY(value);
- invalidate();
- });
- }
-
- private void updateTextSize() {
- int length = CHARACTERS.length;
- float[] widths = new float[length];
- mPaint.getTextWidths(CHARACTERS, 0, length, widths);
- mCharWidth = 0.0f;
- for (float f : widths) {
- mCharWidth = Math.max(mCharWidth, f);
- }
-
- Paint.FontMetrics fm = mPaint.getFontMetrics();
- mCharHeight = fm.bottom - fm.top;
- }
-
- private void updateBubbleSize() {
- int oldWidth = mBubbleWidth;
- int oldHeight = mBubbleHeight;
- mBubbleWidth = (int) Math.max(mBubbleMinWidth,
- Integer.toString(mEnd).length() * mCharWidth + LayoutUtils.dp2pix(mContext, 8));
- mBubbleHeight = (int) Math.max(mBubbleMinHeight,
- mCharHeight + LayoutUtils.dp2pix(mContext, 8));
-
- if (oldWidth != mBubbleWidth && oldHeight != mBubbleHeight) {
- RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mBubble.getLayoutParams();
- lp.width = mBubbleWidth;
- lp.height = mBubbleHeight;
- mBubble.setLayoutParams(lp);
- }
- }
-
- private void updatePopup() {
- int width = getWidth();
- int paddingTop = getPaddingTop();
- int paddingBottom = getPaddingBottom();
-
- getLocationInWindow(mTemp);
-
- mPopupWidth = (int) (width - mRadius - mRadius + mBubbleWidth);
- int popupHeight = mBubbleHeight;
- mPopupX = (int) (mTemp[0] + mRadius - (mBubbleWidth / 2));
- mPopupY = (int) (mTemp[1] - popupHeight + paddingTop +
- ((getHeight() - paddingTop - paddingBottom) / 2) -
- mRadius - LayoutUtils.dp2pix(mContext, 2));
-
- mPopup.update(mPopupX, mPopupY, mPopupWidth, popupHeight, false);
- }
-
- private void updateBubblePosition() {
- float x = ((mPopupWidth - mBubbleWidth) * (mReverse ? (1.0f - mDrawPercent) : mDrawPercent));
- mBubble.setX(x);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- updatePopup();
- updateBubblePosition();
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- mPopup.showAtLocation(this, Gravity.TOP | Gravity.LEFT, mPopupX, mPopupY);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- mPopup.dismiss();
- }
-
- private void startProgressAnimation(float percent) {
- float currentValue;
- if (mProgressAnimation.isRunning()) {
- mProgressAnimation.setCurrentPlayTime(mProgressAnimation.getCurrentPlayTime());
- Object value = mProgressAnimation.getAnimatedValue();
- if (value instanceof Float) {
- currentValue = (float) value;
- } else {
- currentValue = mDrawPercent;
- }
- } else {
- currentValue = mDrawPercent;
- }
- mProgressAnimation.cancel();
- mProgressAnimation.setFloatValues(currentValue, percent);
- mProgressAnimation.setDuration(Math.min(500, (long) (50 * getWidth() * Math.abs(currentValue - percent))));
- mProgressAnimation.start();
- }
-
- private void startShowBubbleAnimation() {
- mBubbleScaleAnimation.cancel();
- mBubbleScaleAnimation.setFloatValues(mDrawBubbleScale, 1.0f);
- mBubbleScaleAnimation.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR);
- mBubbleScaleAnimation.setDuration((long) (300 * Math.abs(mDrawBubbleScale - 1.0f)));
- mBubbleScaleAnimation.start();
- }
-
- private void startHideBubbleAnimation() {
- mBubbleScaleAnimation.cancel();
- mBubbleScaleAnimation.setFloatValues(mDrawBubbleScale, 0.0f);
- mBubbleScaleAnimation.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR);
- mBubbleScaleAnimation.setDuration((long) (300 * Math.abs(mDrawBubbleScale - 0.0f)));
- mBubbleScaleAnimation.start();
- }
-
- public void setColor(int color) {
- mPaint.setColor(color);
- mBubble.setColor(color);
- invalidate();
- }
-
- public void setRange(int start, int end) {
- mStart = start;
- mEnd = end;
- setProgress(mProgress);
-
- updateBubbleSize();
- }
-
- public int getProgress() {
- return mProgress;
- }
-
- public void setProgress(int progress) {
- progress = MathUtils.clamp(progress, mStart, mEnd);
- int oldProgress = mProgress;
- if (mProgress != progress) {
- mProgress = progress;
- mPercent = MathUtils.delerp(mStart, mEnd, mProgress);
- mTargetProgress = progress;
-
- if (mProgressAnimation == null) {
- // For init
- mDrawPercent = mPercent;
- mDrawProgress = mProgress;
- updateBubblePosition();
- mBubble.setProgress(mDrawProgress);
- } else {
- startProgressAnimation(mPercent);
- }
- invalidate();
- }
- if (mListener != null) {
- mListener.onSetProgress(this, progress, oldProgress, false, true);
- }
- }
-
- public void setReverse(boolean reverse) {
- if (mReverse != reverse) {
- mReverse = reverse;
- invalidate();
- }
- }
-
- public void setOnSetProgressListener(OnSetProgressListener listener) {
- mListener = listener;
- }
-
- @Override
- protected void onDraw(@NonNull Canvas canvas) {
- int width = getWidth();
- int height = getHeight();
- if (width < LayoutUtils.dp2pix(mContext, 24)) {
- canvas.drawRect(0, 0, width, getHeight(), mPaint);
- } else {
- int paddingLeft = getPaddingLeft();
- int paddingTop = getPaddingTop();
- int paddingRight = getPaddingRight();
- int paddingBottom = getPaddingBottom();
- float thickness = mThickness;
- float radius = mRadius;
- float halfThickness = thickness / 2;
-
- int saved = canvas.save();
-
- canvas.translate(0, paddingTop + ((height - paddingTop - paddingBottom) / 2));
-
- float currentX = paddingLeft + radius + (width - radius - radius - paddingLeft - paddingRight) *
- (mReverse ? (1.0f - mDrawPercent) : mDrawPercent);
-
- mLeftRectF.set(paddingLeft + radius, -halfThickness, currentX, halfThickness);
- mRightRectF.set(currentX, -halfThickness, width - paddingRight - radius, halfThickness);
-
- // Draw bar
- if (mReverse) {
- canvas.drawRect(mRightRectF, mPaint);
- canvas.drawRect(mLeftRectF, mBgPaint);
- } else {
- canvas.drawRect(mLeftRectF, mPaint);
- canvas.drawRect(mRightRectF, mBgPaint);
- }
-
- // Draw controller
- float scale = 1.0f - mDrawBubbleScale;
- if (scale != 0.0f) {
- canvas.scale(scale, scale, currentX, 0);
- canvas.drawCircle(currentX, 0, radius, mPaint);
- }
-
- canvas.restoreToCount(saved);
- }
- }
-
- private void setShowBubble(boolean showBubble) {
- if (mShowBubble != showBubble) {
- mShowBubble = showBubble;
- if (showBubble) {
- startShowBubbleAnimation();
- } else {
- startHideBubbleAnimation();
- }
- }
- }
-
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public boolean onTouchEvent(@NonNull MotionEvent event) {
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_MOVE:
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
-
- if (mListener != null) {
- if (action == MotionEvent.ACTION_DOWN) {
- mListener.onFingerDown();
- } else if (action == MotionEvent.ACTION_UP) {
- mListener.onFingerUp();
- }
- }
-
- int paddingLeft = getPaddingLeft();
- int paddingRight = getPaddingRight();
- float radius = mRadius;
- float x = event.getX();
- int progress = Math.round(MathUtils.lerp((float) mStart, (float) mEnd,
- MathUtils.clamp((mReverse ? (getWidth() - paddingLeft - radius - x) : (x - radius - paddingLeft)) /
- (getWidth() - radius - radius - paddingLeft - paddingRight), 0.0f, 1.0f)));
- float percent = MathUtils.delerp(mStart, mEnd, progress);
-
- // ACTION_CANCEL not changed
- if (action == MotionEvent.ACTION_CANCEL) {
- progress = mProgress;
- percent = mPercent;
- }
-
- if (mTargetProgress != progress) {
- mTargetProgress = progress;
- startProgressAnimation(percent);
-
- if (mListener != null) {
- mListener.onSetProgress(this, mProgress, progress, true, false);
- }
- }
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- SimpleHandler.getInstance().removeCallbacks(mCheckForShowBubble);
- setShowBubble(false);
- } else if (action == MotionEvent.ACTION_DOWN) {
- if (mCheckForShowBubble == null) {
- mCheckForShowBubble = new CheckForShowBubble();
- }
- SimpleHandler.getInstance().postDelayed(mCheckForShowBubble, ViewConfiguration.getTapTimeout());
- }
-
- if (action == MotionEvent.ACTION_UP) {
- int oldProgress = mProgress;
- if (mProgress != progress) {
- mProgress = progress;
- mPercent = mDrawPercent;
- }
- if (mListener != null) {
- mListener.onSetProgress(this, progress, oldProgress, true, true);
- }
- }
- break;
- }
-
- return true;
- }
-
- public interface OnSetProgressListener {
-
- void onSetProgress(Slider slider, int newProgress, int oldProgress, boolean byUser, boolean confirm);
-
- void onFingerDown();
-
- void onFingerUp();
- }
-
- @SuppressLint("ViewConstructor")
- private static class BubbleView extends AppCompatImageView {
-
- private static final float TEXT_CENTER = (float) BUBBLE_WIDTH / 2.0f / BUBBLE_HEIGHT;
-
- private final Drawable mDrawable;
-
- private final Paint mTextPaint;
- private final Rect mRect = new Rect();
- private String mProgressStr = "";
-
- public BubbleView(Context context, Paint paint) {
- super(context);
- setImageResource(R.drawable.v_slider_bubble);
- mDrawable = DrawableCompat.wrap(getDrawable());
- setImageDrawable(mDrawable);
- mTextPaint = paint;
- }
-
- public void setColor(int color) {
- DrawableCompat.setTint(mDrawable, color);
- }
-
- public void setProgress(int progress) {
- String str = Integer.toString(progress);
- if (!str.equals(mProgressStr)) {
- mProgressStr = str;
- mTextPaint.getTextBounds(str, 0, str.length(), mRect);
- invalidate();
- }
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- setPivotX(w / 2);
- setPivotY(h);
- }
-
- @Override
- protected void onDraw(@NonNull Canvas canvas) {
- super.onDraw(canvas);
-
- int width = getWidth();
- int height = getHeight();
- int x = width / 2;
- int y = (int) ((height * TEXT_CENTER) + (mRect.height() / 2));
- canvas.drawText(mProgressStr, x, y, mTextPaint);
- }
- }
-
- private final class CheckForShowBubble implements Runnable {
-
- @Override
- public void run() {
- setShowBubble(true);
- }
- }
-}
diff --git a/app/src/main/res/layout/dialog_go_to.xml b/app/src/main/res/layout/dialog_go_to.xml
index 47512bbab..a3756a334 100644
--- a/app/src/main/res/layout/dialog_go_to.xml
+++ b/app/src/main/res/layout/dialog_go_to.xml
@@ -28,13 +28,14 @@
android:layout_gravity="center_vertical"
android:gravity="center_horizontal" />
-
+ android:layout_weight="1"
+ android:stepSize="1"
+ android:valueFrom="1" />
center_vertical
-
-