6.7.0 - Alpha3 - 文件管理器浮动按钮展开后点击菜单项时优化菜单收起时机
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user