From 769d9e69e3472451fb557120cde53e727a6a70f0 Mon Sep 17 00:00:00 2001 From: jsbxyyx Date: Wed, 27 Nov 2024 12:29:18 +0800 Subject: [PATCH] 3.7 --- app/build.gradle | 4 +- .../jsbxyyx/xbook/GeckoWebViewActivity.java | 33 ++ .../github/jsbxyyx/xbook/HomeFragment.java | 3 +- .../com/github/jsbxyyx/xbook/WebProgress.java | 357 ++++++++++++++++++ app/src/main/res/layout/activity_webview.xml | 6 + 5 files changed, 400 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/github/jsbxyyx/xbook/WebProgress.java diff --git a/app/build.gradle b/app/build.gradle index 7b43fd8..b3d34fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,8 +26,8 @@ android { applicationId "com.github.jsbxyyx.xbook" minSdk 27 targetSdk 33 - versionCode 36 - versionName "3.6" + versionCode 37 + versionName "3.7" archivesBaseName = "xplay" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/github/jsbxyyx/xbook/GeckoWebViewActivity.java b/app/src/main/java/com/github/jsbxyyx/xbook/GeckoWebViewActivity.java index f3c4dff..35559df 100644 --- a/app/src/main/java/com/github/jsbxyyx/xbook/GeckoWebViewActivity.java +++ b/app/src/main/java/com/github/jsbxyyx/xbook/GeckoWebViewActivity.java @@ -3,6 +3,7 @@ import android.content.pm.ActivityInfo; import android.os.Bundle; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.github.jsbxyyx.xbook.common.Common; @@ -54,6 +55,9 @@ protected void onCreate(Bundle savedInstanceState) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } + WebProgress webProgress = findViewById(R.id.progress); + webProgress.setColor("#1AAD19"); + try { webView = findViewById(R.id.wv_html_view); GeckoSession session = new GeckoSession(); @@ -76,6 +80,34 @@ protected void onCreate(Bundle savedInstanceState) { settings.setAllowJavascript(true); settings.setUserAgentMode(GeckoSessionSettings.USER_AGENT_MODE_MOBILE); + session.setProgressDelegate(new GeckoSession.ProgressDelegate() { + @Override + public void onPageStart(@NonNull GeckoSession session, @NonNull String url) { + GeckoSession.ProgressDelegate.super.onPageStart(session, url); + } + + @Override + public void onPageStop(@NonNull GeckoSession session, boolean success) { + GeckoSession.ProgressDelegate.super.onPageStop(session, success); + } + + @Override + public void onProgressChange(@NonNull GeckoSession session, int progress) { + GeckoSession.ProgressDelegate.super.onProgressChange(session, progress); + webProgress.setProgress(progress); + } + + @Override + public void onSecurityChange(@NonNull GeckoSession session, @NonNull SecurityInformation securityInfo) { + GeckoSession.ProgressDelegate.super.onSecurityChange(session, securityInfo); + } + + @Override + public void onSessionStateChange(@NonNull GeckoSession session, @NonNull GeckoSession.SessionState sessionState) { + GeckoSession.ProgressDelegate.super.onSessionStateChange(session, sessionState); + } + }); + session.open(runtime); webView.setSession(session); @@ -84,6 +116,7 @@ protected void onCreate(Bundle savedInstanceState) { }); session.loadUri(url); + webProgress.show(); } catch (Exception e) { LogUtil.e(getClass().getSimpleName(), "onCreate: %s", LogUtil.getStackTraceString(e)); } diff --git a/app/src/main/java/com/github/jsbxyyx/xbook/HomeFragment.java b/app/src/main/java/com/github/jsbxyyx/xbook/HomeFragment.java index 3f7120f..c207910 100644 --- a/app/src/main/java/com/github/jsbxyyx/xbook/HomeFragment.java +++ b/app/src/main/java/com/github/jsbxyyx/xbook/HomeFragment.java @@ -168,10 +168,11 @@ public void call(JsonNode o, Throwable err) { double localName = Double.parseDouble(versionName); double cloudName = Double.parseDouble(update.get("name").asText().trim()); if (cloudName > localName) { + String message = "有新版本啦,前往 我的-设置 进行版本更新"; mActivity.runOnUiThread(() -> { new AlertDialog.Builder(mActivity) .setTitle("提示") - .setMessage("有新版本啦,前往 我的-设置 进行版本更新") + .setMessage(message) .setIcon(android.R.drawable.ic_dialog_alert) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { diff --git a/app/src/main/java/com/github/jsbxyyx/xbook/WebProgress.java b/app/src/main/java/com/github/jsbxyyx/xbook/WebProgress.java new file mode 100644 index 0000000..990576f --- /dev/null +++ b/app/src/main/java/com/github/jsbxyyx/xbook/WebProgress.java @@ -0,0 +1,357 @@ +package com.github.jsbxyyx.xbook; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; + +/** + * https://github.com/youlookwhat/WebProgress + */ +public class WebProgress extends FrameLayout { + + /** + * 默认匀速动画最大的时长 + */ + public static final int MAX_UNIFORM_SPEED_DURATION = 8 * 1000; + /** + * 默认加速后减速动画最大时长 + */ + public static final int MAX_DECELERATE_SPEED_DURATION = 450; + /** + * 95f-100f时,透明度1f-0f时长 + */ + public static final int DO_END_ALPHA_DURATION = 630; + /** + * 95f - 100f动画时长 + */ + public static final int DO_END_PROGRESS_DURATION = 500; + /** + * 当前匀速动画最大的时长 + */ + private static int CURRENT_MAX_UNIFORM_SPEED_DURATION = MAX_UNIFORM_SPEED_DURATION; + /** + * 当前加速后减速动画最大时长 + */ + private static int CURRENT_MAX_DECELERATE_SPEED_DURATION = MAX_DECELERATE_SPEED_DURATION; + /** + * 默认的高度(dp) + */ + public static int WEB_PROGRESS_DEFAULT_HEIGHT = 3; + /** + * 进度条颜色默认 + */ + public static String WEB_PROGRESS_COLOR = "#2483D9"; + /** + * 进度条颜色 + */ + private int mColor; + /** + * 进度条的画笔 + */ + private Paint mPaint; + /** + * 进度条动画 + */ + private Animator mAnimator; + /** + * 控件的宽度 + */ + private int mTargetWidth = 0; + /** + * 控件的高度 + */ + private int mTargetHeight; + /** + * 标志当前进度条的状态 + */ + private int TAG = 0; + /** + * 第一次过来进度show,后面就是setProgress + */ + private boolean isShow = false; + public static final int UN_START = 0; + public static final int STARTED = 1; + public static final int FINISH = 2; + private float mCurrentProgress = 0F; + + public WebProgress(Context context) { + this(context, null); + } + + public WebProgress(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public WebProgress(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr) { + mPaint = new Paint(); + mColor = Color.parseColor(WEB_PROGRESS_COLOR); + mPaint.setAntiAlias(true); + mPaint.setColor(mColor); + mPaint.setDither(true); + mPaint.setStrokeCap(Paint.Cap.SQUARE); + + mTargetWidth = context.getResources().getDisplayMetrics().widthPixels; + mTargetHeight = dip2px(WEB_PROGRESS_DEFAULT_HEIGHT); + } + + /** + * 设置单色进度条 + */ + public void setColor(int color) { + this.mColor = color; + mPaint.setColor(color); + } + + public void setColor(String color) { + this.setColor(Color.parseColor(color)); + } + + public void setColor(int startColor, int endColor) { + LinearGradient linearGradient = new LinearGradient(0, 0, mTargetWidth, mTargetHeight, startColor, endColor, Shader.TileMode.CLAMP); + mPaint.setShader(linearGradient); + } + + /** + * 设置渐变色进度条 + * + * @param startColor 开始颜色 + * @param endColor 结束颜色 + */ + public void setColor(String startColor, String endColor) { + this.setColor(Color.parseColor(startColor), Color.parseColor(endColor)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int wMode = MeasureSpec.getMode(widthMeasureSpec); + int w = MeasureSpec.getSize(widthMeasureSpec); + + int hMode = MeasureSpec.getMode(heightMeasureSpec); + int h = MeasureSpec.getSize(heightMeasureSpec); + + if (wMode == MeasureSpec.AT_MOST) { + w = Math.min(w, getContext().getResources().getDisplayMetrics().widthPixels); + } + if (hMode == MeasureSpec.AT_MOST) { + h = mTargetHeight; + } + this.setMeasuredDimension(w, h); + } + + @Override + protected void onDraw(Canvas canvas) { + + } + + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.drawRect(0, 0, mCurrentProgress / 100 * (float) this.getWidth(), this.getHeight(), mPaint); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + this.mTargetWidth = getMeasuredWidth(); + int screenWidth = getContext().getResources().getDisplayMetrics().widthPixels; + if (mTargetWidth >= screenWidth) { + CURRENT_MAX_DECELERATE_SPEED_DURATION = MAX_DECELERATE_SPEED_DURATION; + CURRENT_MAX_UNIFORM_SPEED_DURATION = MAX_UNIFORM_SPEED_DURATION; + } else { + //取比值 + float rate = this.mTargetWidth / (float) screenWidth; + CURRENT_MAX_UNIFORM_SPEED_DURATION = (int) (MAX_UNIFORM_SPEED_DURATION * rate); + CURRENT_MAX_DECELERATE_SPEED_DURATION = (int) (MAX_DECELERATE_SPEED_DURATION * rate); + } + } + + private void setFinish() { + isShow = false; + TAG = FINISH; + } + + private void startAnim(boolean isFinished) { + + float v = isFinished ? 100 : 95; + + if (mAnimator != null && mAnimator.isStarted()) { + mAnimator.cancel(); + } + mCurrentProgress = mCurrentProgress == 0 ? 0.00000001f : mCurrentProgress; + // 可能由于透明度造成突然出现的问题 + setAlpha(1); + + if (!isFinished) { + ValueAnimator mAnimator = ValueAnimator.ofFloat(mCurrentProgress, v); + float residue = 1f - mCurrentProgress / 100 - 0.05f; + mAnimator.setInterpolator(new LinearInterpolator()); + mAnimator.setDuration((long) (residue * CURRENT_MAX_UNIFORM_SPEED_DURATION)); + mAnimator.addUpdateListener(mAnimatorUpdateListener); + mAnimator.start(); + this.mAnimator = mAnimator; + } else { + + ValueAnimator segment95Animator = null; + if (mCurrentProgress < 95) { + segment95Animator = ValueAnimator.ofFloat(mCurrentProgress, 95); + float residue = 1f - mCurrentProgress / 100f - 0.05f; + segment95Animator.setInterpolator(new LinearInterpolator()); + segment95Animator.setDuration((long) (residue * CURRENT_MAX_DECELERATE_SPEED_DURATION)); + segment95Animator.setInterpolator(new DecelerateInterpolator()); + segment95Animator.addUpdateListener(mAnimatorUpdateListener); + } + + ObjectAnimator mObjectAnimator = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f); + mObjectAnimator.setDuration(DO_END_ALPHA_DURATION); + ValueAnimator mValueAnimatorEnd = ValueAnimator.ofFloat(95f, 100f); + mValueAnimatorEnd.setDuration(DO_END_PROGRESS_DURATION); + mValueAnimatorEnd.addUpdateListener(mAnimatorUpdateListener); + + AnimatorSet mAnimatorSet = new AnimatorSet(); + mAnimatorSet.playTogether(mObjectAnimator, mValueAnimatorEnd); + + if (segment95Animator != null) { + AnimatorSet mAnimatorSet1 = new AnimatorSet(); + mAnimatorSet1.play(mAnimatorSet).after(segment95Animator); + mAnimatorSet = mAnimatorSet1; + } + mAnimatorSet.addListener(mAnimatorListenerAdapter); + mAnimatorSet.start(); + mAnimator = mAnimatorSet; + } + + TAG = STARTED; + } + + private ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float t = (float) animation.getAnimatedValue(); + WebProgress.this.mCurrentProgress = t; + WebProgress.this.invalidate(); + } + }; + + private AnimatorListenerAdapter mAnimatorListenerAdapter = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + doEnd(); + } + }; + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + /** + * animator cause leak , if not cancel; + */ + if (mAnimator != null && mAnimator.isStarted()) { + mAnimator.cancel(); + mAnimator = null; + } + } + + private void doEnd() { + if (TAG == FINISH && mCurrentProgress == 100) { + setVisibility(GONE); + mCurrentProgress = 0f; + this.setAlpha(1f); + } + TAG = UN_START; + } + + public void reset() { + mCurrentProgress = 0; + if (mAnimator != null && mAnimator.isStarted()) { + mAnimator.cancel(); + } + } + + public void setProgress(int newProgress) { + setProgress(Float.valueOf(newProgress)); + } + + + public LayoutParams offerLayoutParams() { + return new LayoutParams(mTargetWidth, mTargetHeight); + } + + private int dip2px(float dpValue) { + final float scale = getContext().getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + public WebProgress setHeight(int heightDp) { + this.mTargetHeight = dip2px(heightDp); + return this; + } + + public void setProgress(float progress) { + // fix 同时返回两个 100,产生两次进度条的问题; + if (TAG == UN_START && progress == 100) { + setVisibility(View.GONE); + return; + } + + if (getVisibility() == View.GONE) { + setVisibility(View.VISIBLE); + } + if (progress < 95) { + return; + } + if (TAG != FINISH) { + startAnim(true); + } + } + + /** + * 显示进度条 + */ + public void show() { + isShow = true; + setVisibility(View.VISIBLE); + mCurrentProgress = 0f; + startAnim(false); + } + + /** + * 进度完成后消失 + */ + public void hide() { + setWebProgress(100); + } + + /** + * 为单独处理WebView进度条 + */ + public void setWebProgress(int newProgress) { + if (newProgress >= 0 && newProgress < 95) { + if (!isShow) { + show(); + } else { + setProgress(newProgress); + } + } else { + setProgress(newProgress); + setFinish(); + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_webview.xml b/app/src/main/res/layout/activity_webview.xml index d290d56..d6a01a9 100644 --- a/app/src/main/res/layout/activity_webview.xml +++ b/app/src/main/res/layout/activity_webview.xml @@ -7,6 +7,12 @@ android:orientation="vertical" tools:context=".GeckoWebViewActivity"> + +