6.7.0 - Alpha3 - 文件管理器浮动按钮展开后点击菜单项时优化菜单收起时机

This commit is contained in:
SuperMonster003
2025-07-16 15:35:54 +08:00
parent ef86f8aecc
commit 8273a394bf
5 changed files with 92 additions and 84 deletions

View File

@@ -22,6 +22,7 @@
"http 模块相关方法支持不安全选项参数 (isInsecure/insecure), 用于忽略证书相关异常 _[`issue #417`](http://issues.autojs6.com/417)_",
"android.graphics.Paint#setColor 支持正常解析 ColorInt/ColorHex/ColorName 等颜色参数",
"内置模块相关方法实参类型的异常消息增加类型摘要信息",
"文件管理器浮动按钮展开后点击菜单项时优化菜单收起时机",
"崩溃报告页面支持双指缩放调整字体大小并添加常用功能按钮",
"应用启动器图标支持自适应图标特性 _[`issue #405`](http://issues.autojs6.com/405)_"
],
@@ -782,7 +783,7 @@
"主题色增加更多 Material Design Color (材料设计颜色) 选项",
"文件管理器/任务面板等列表项图标适当轻量化并适配主题色",
"主页搜索框的提示文本颜色适配夜间模式",
"对话框/文本/Fab/AppBar/列表项等部件适配夜间模式",
"对话框/文本/FAB/AppBar/列表项等部件适配夜间模式",
"文档/设置/关于/主题色/布局分析等页面及浮动按钮菜单适配夜间模式",
"页面布局尽可能兼容 RTL (Right-To-Left) 布局",
"关于页面增加图标动画效果",

1
.gitignore vendored
View File

@@ -27,6 +27,7 @@ sync.ffs_db
/build/
/libs/**/build/
/modules/**/build/
/captures/
/release/
/releases/

View File

@@ -2,9 +2,11 @@ package org.autojs.autojs.ui.main;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -26,10 +28,6 @@ import org.autojs.autojs6.R;
*/
public class FloatingActionMenu extends FrameLayout implements View.OnClickListener {
public interface OnFloatingActionButtonClickListener {
void onClick(FloatingActionButton button, int pos);
}
private static final int[] ICONS = {
R.drawable.ic_floating_action_menu_dir,
R.drawable.ic_floating_action_menu_file,
@@ -42,16 +40,16 @@ public class FloatingActionMenu extends FrameLayout implements View.OnClickListe
R.string.text_import,
R.string.text_project};
private View mOverlay = null;
private static final int ANIMATION_INTERVAL = 30;
private static final int ANIMATION_DURATION = 250;
private final Interpolator mInterpolator = new FastOutSlowInInterpolator();
private final PublishSubject<Boolean> mState = PublishSubject.create();
private View mOverlay = null;
private FloatingActionButton[] mFabs;
private View[] mFabContainers;
private boolean mExpanded = false;
private boolean mShouldCheckExpanded = true;
private final int mInterval = 30;
private final int mDuration = 250;
private final Interpolator mInterpolator = new FastOutSlowInInterpolator();
private final PublishSubject<Boolean> mState = PublishSubject.create();
private OnFloatingActionButtonClickListener mOnFloatingActionButtonClickListener;
public FloatingActionMenu(@NonNull Context context) {
@@ -69,16 +67,12 @@ public class FloatingActionMenu extends FrameLayout implements View.OnClickListe
init();
}
private void init() {
buildFabs(ICONS, LABELS);
}
public boolean isExpanded() {
return mExpanded;
}
public boolean shouldCheckExpanded() {
return mShouldCheckExpanded;
public PublishSubject<Boolean> getState() {
return mState;
}
public void expand() {
@@ -86,38 +80,19 @@ public class FloatingActionMenu extends FrameLayout implements View.OnClickListe
setVisibility(VISIBLE);
int h = mFabs[0].getHeight();
for (int i = 0; i < mFabContainers.length; i++) {
animateY(mFabContainers[i], -(h + mInterval) * (i + 1), null);
animateY(mFabContainers[i], -(h + ANIMATION_INTERVAL) * (i + 1), null);
rotate(mFabs[i]);
}
mExpanded = true;
mState.onNext(true);
}
private void rotate(FloatingActionButton fab) {
fab.setRotation(0);
fab.animate()
.rotation(360)
.setDuration(mDuration)
.setInterpolator(mInterpolator)
.start();
}
private void animateY(View view, float y, Animator.AnimatorListener l) {
view.animate()
.translationY(y)
.setDuration(mDuration)
.setInterpolator(mInterpolator)
.setListener(l)
.start();
}
public void collapse() {
hideOverlay();
animateY(mFabContainers[0], 0, new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(INVISIBLE);
mShouldCheckExpanded = true;
}
});
for (int i = 1; i < mFabContainers.length; i++) {
@@ -128,6 +103,51 @@ public class FloatingActionMenu extends FrameLayout implements View.OnClickListe
mState.onNext(false);
}
public void setOnFloatingActionButtonClickListener(OnFloatingActionButtonClickListener listener) {
mOnFloatingActionButtonClickListener = listener;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
return;
}
int h = mFabContainers[0].getMeasuredHeight();
setMeasuredDimension(getMeasuredWidth(), (h + ANIMATION_INTERVAL) * mFabs.length + h);
}
@Override
public void onClick(View v) {
collapse();
if (mOnFloatingActionButtonClickListener != null) {
mOnFloatingActionButtonClickListener.onClick((FloatingActionButton) v, (int) v.getTag());
}
}
private void init() {
buildFabs(ICONS, LABELS);
}
private void rotate(FloatingActionButton fab) {
fab.setRotation(0);
fab.animate()
.rotation(360)
.setDuration(ANIMATION_DURATION)
.setInterpolator(mInterpolator)
.start();
}
private void animateY(View view, float y, Animator.AnimatorListener l) {
view.animate()
.translationY(y)
.setDuration(ANIMATION_DURATION)
.setInterpolator(mInterpolator)
.setListener(l)
.start();
}
@SuppressWarnings("SameParameterValue")
private void buildFabs(int[] icons, int[] labels) {
if (icons.length != labels.length) {
@@ -149,51 +169,33 @@ public class FloatingActionMenu extends FrameLayout implements View.OnClickListe
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// Call super.onMeasure to measure children and width
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
private void showOverlay() {
if (mOverlay != null) {
if (mOverlay.getVisibility() != VISIBLE) {
mOverlay.setVisibility(View.VISIBLE);
}
return;
}
int h = mFabContainers[0].getMeasuredHeight();
setMeasuredDimension(getMeasuredWidth(), (h + mInterval) * mFabs.length + h);
}
public PublishSubject<Boolean> getState() {
return mState;
}
@Override
public void onClick(View v) {
// collapse();
if (mOnFloatingActionButtonClickListener != null) {
mOnFloatingActionButtonClickListener.onClick((FloatingActionButton) v, (int) v.getTag());
}
}
public void setOnFloatingActionButtonClickListener(OnFloatingActionButtonClickListener onFloatingActionButtonClickListener) {
mOnFloatingActionButtonClickListener = onFloatingActionButtonClickListener;
}
private void showOverlay() {
if (mOverlay != null && mOverlay.getVisibility() == VISIBLE) return;
Context context = getContext();
if (!(context instanceof Activity activity)) return;
if (!(activity.findViewById(android.R.id.content) instanceof ViewGroup root)) return;
FloatingActionMenu thisMenu = this;
mOverlay = new View(context) {
private final int[] loc = new int[2];
private final Rect menuRect = new Rect();
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
mShouldCheckExpanded = false;
collapse();
root.post(() -> root.removeView(this));
var replay = MotionEvent.obtain(event);
root.post(() -> activity.getWindow().getDecorView().dispatchTouchEvent(replay));
thisMenu.getLocationOnScreen(loc);
menuRect.set(loc[0], loc[1], loc[0] + thisMenu.getWidth(), loc[1] + thisMenu.getHeight());
if (!isInMenuButtonsArea(menuRect, event)) {
var replay = MotionEvent.obtain(event);
root.post(() -> activity.getWindow().getDecorView().dispatchTouchEvent(replay));
collapse();
}
return false;
}
};
@@ -205,11 +207,16 @@ public class FloatingActionMenu extends FrameLayout implements View.OnClickListe
root.addView(mOverlay);
}
private void hideOverlay() {
if (mOverlay == null) return;
if (!(mOverlay.getParent() instanceof ViewGroup parent)) return;
parent.removeView(mOverlay);
mOverlay = null;
private boolean isInMenuButtonsArea(Rect menuRect, MotionEvent event) {
return menuRect.contains((int) event.getRawX(), (int) event.getRawY());
}
}
private void hideOverlay() {
if (mOverlay != null) mOverlay.setVisibility(View.GONE);
}
public interface OnFloatingActionButtonClickListener {
void onClick(FloatingActionButton button, int pos);
}
}

View File

@@ -119,8 +119,7 @@ class ExplorerFragment : ViewPagerFragment(0), OnFloatingActionButtonClickListen
}
override fun onFabClick(fab: FloatingActionButton) {
// initFloatingActionMenuIfNeeded(fab).run { if (isExpanded) collapse() else expand() }
initFloatingActionMenuIfNeeded(fab).run { if (shouldCheckExpanded() && !isExpanded) expand() }
initFloatingActionMenuIfNeeded(fab).run { if (isExpanded) collapse() else expand() }
}
private fun initFloatingActionMenuIfNeeded(fab: FloatingActionButton): FloatingActionMenu {

View File

@@ -1,5 +1,5 @@
#Thu Jul 03 14:14:37 CST 2025
BUILD_TIME=1751523277489
#Wed Jul 16 14:49:49 CST 2025
BUILD_TIME=1752648589445
COMPILE_SDK_VERSION=35
IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125
@@ -19,6 +19,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=35
TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3319
VERSION_BUILD=3323
VERSION_NAME=6.7.0 Alpha3
VSCODE_EXT_REQUIRED_VERSION=1.0.8