diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenu.java b/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenu.java index da8e3a72..67a13013 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenu.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenu.java @@ -76,7 +76,7 @@ public class CircularMenu implements Recorder.OnStateChangedListener, LayoutInsp private static final int IC_ACTION_VIEW = R.drawable.ic_android_eat_js; - CircularActionMenuFloatingWindow mWindow; + CircularMenuWindow mWindow; private int mState; private RoundedImageView mActionViewIcon; private Context mContext; @@ -110,17 +110,17 @@ public class CircularMenu implements Recorder.OnStateChangedListener, LayoutInsp } private void initFloaty() { - mWindow = new CircularActionMenuFloatingWindow(new CircularActionMenuFloaty() { + mWindow = new CircularMenuWindow(mContext, new CircularMenuFloaty() { @Override - public View inflateActionView(FloatyService service, CircularActionMenuFloatingWindow window) { + public View inflateActionView(FloatyService service, CircularMenuWindow window) { View actionView = View.inflate(service, R.layout.circular_action_view, null); mActionViewIcon = (RoundedImageView) actionView.findViewById(R.id.icon); return actionView; } @Override - public CircularActionMenu inflateMenuItems(FloatyService service, CircularActionMenuFloatingWindow window) { + public CircularActionMenu inflateMenuItems(FloatyService service, CircularMenuWindow window) { CircularActionMenu menu = (CircularActionMenu) View.inflate(new ContextThemeWrapper(service, R.style.AppTheme), R.layout.circular_action_menu, null); ButterKnife.bind(CircularMenu.this, menu); return menu; diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenuFloaty.java b/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenuFloaty.java new file mode 100644 index 00000000..96fa9b5a --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenuFloaty.java @@ -0,0 +1,13 @@ +package com.stardust.scriptdroid.ui.floating; + +import android.view.View; + +import com.stardust.enhancedfloaty.FloatyService; +import com.stardust.floatingcircularactionmenu.CircularActionMenu; + +public interface CircularMenuFloaty { + + View inflateActionView(FloatyService service, CircularMenuWindow window); + + CircularActionMenu inflateMenuItems(FloatyService service, CircularMenuWindow window); +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenuWindow.java b/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenuWindow.java new file mode 100644 index 00000000..657f7a0e --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/floating/CircularMenuWindow.java @@ -0,0 +1,202 @@ +package com.stardust.scriptdroid.ui.floating; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.view.OrientationEventListener; +import android.view.View; +import android.view.WindowManager; + +import com.stardust.enhancedfloaty.FloatyService; +import com.stardust.enhancedfloaty.FloatyWindow; +import com.stardust.enhancedfloaty.WindowBridge; +import com.stardust.floatingcircularactionmenu.CircularActionMenu; +import com.stardust.floatingcircularactionmenu.gesture.BounceDragGesture; + +public class CircularMenuWindow implements FloatyWindow, SensorEventListener { + + protected CircularMenuFloaty mFloaty; + protected WindowManager mWindowManager; + protected CircularActionMenu mCircularActionMenu; + protected View mCircularActionView; + protected BounceDragGesture mDragGesture; + protected OrientationAwareWindowBridge mActionViewWindowBridge; + protected WindowBridge mMenuWindowBridge; + protected WindowManager.LayoutParams mActionViewWindowLayoutParams; + protected WindowManager.LayoutParams mMenuWindowLayoutParams; + protected View.OnClickListener mActionViewOnClickListener; + protected float mKeepToSideHiddenWidthRadio; + protected float mActiveAlpha = 1.0F; + protected float mInactiveAlpha = 0.4F; + private Context mContext; + private OrientationEventListener mOrientationEventListener; + + public CircularMenuWindow(Context context, CircularMenuFloaty floaty) { + this.mFloaty = floaty; + mContext = context; + } + + public void onCreate(FloatyService service, WindowManager manager) { + this.mWindowManager = manager; + this.mActionViewWindowLayoutParams = this.createWindowLayoutParams(); + this.mMenuWindowLayoutParams = this.createWindowLayoutParams(); + this.inflateWindowViews(service); + this.initWindowBridge(); + this.initGestures(); + this.setListeners(); + this.setInitialState(); + mOrientationEventListener = new OrientationEventListener(mContext) { + @Override + public void onOrientationChanged(int orientation) { + if (mActionViewWindowBridge.isOrientationChanged(orientation)) { + mDragGesture.keepToEdge(); + } + } + }; + if (mOrientationEventListener.canDetectOrientation()) { + mOrientationEventListener.enable(); + } + } + + private void setInitialState() { + this.mDragGesture.keepToEdge(); + } + + private void initGestures() { + this.mDragGesture = new BounceDragGesture(this.mActionViewWindowBridge, this.mCircularActionView); + this.mDragGesture.setKeepToSideHiddenWidthRadio(this.mKeepToSideHiddenWidthRadio); + this.mDragGesture.setPressedAlpha(this.mActiveAlpha); + this.mDragGesture.setUnpressedAlpha(this.mInactiveAlpha); + } + + private void initWindowBridge() { + this.mActionViewWindowBridge = new OrientationAwareWindowBridge(this.mActionViewWindowLayoutParams, this.mWindowManager, this.mCircularActionView, mContext); + this.mMenuWindowBridge = new WindowBridge.DefaultImpl(this.mMenuWindowLayoutParams, this.mWindowManager, this.mCircularActionMenu); + } + + public void setKeepToSideHiddenWidthRadio(float keepToSideHiddenWidthRadio) { + this.mKeepToSideHiddenWidthRadio = keepToSideHiddenWidthRadio; + if (this.mDragGesture != null) { + this.mDragGesture.setKeepToSideHiddenWidthRadio(this.mKeepToSideHiddenWidthRadio); + } + + } + + private WindowManager.LayoutParams createWindowLayoutParams() { + WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(-2, -2, 2003, 520, -3); + layoutParams.gravity = 51; + return layoutParams; + } + + private void setListeners() { + this.setOnActionViewClickListener(v -> { + if (isExpanded()) { + collapse(); + } else { + expand(); + } + + }); + if (this.mActionViewOnClickListener != null) { + this.mDragGesture.setOnDraggedViewClickListener(this.mActionViewOnClickListener); + } + + this.mCircularActionMenu.addOnStateChangeListener(new CircularActionMenu.OnStateChangeListenerAdapter() { + public void onCollapsed(CircularActionMenu menu) { + mCircularActionView.setAlpha(mInactiveAlpha); + } + + public void onExpanded(CircularActionMenu menu) { + mCircularActionView.setAlpha(mActiveAlpha); + } + }); + } + + public void setOnActionViewClickListener(View.OnClickListener listener) { + if (this.mDragGesture == null) { + this.mActionViewOnClickListener = listener; + } else { + this.mDragGesture.setOnDraggedViewClickListener(listener); + } + } + + public void expand() { + this.mDragGesture.setEnabled(false); + this.setMenuPositionAtActionView(); + if (this.mActionViewWindowBridge.getX() > this.mActionViewWindowBridge.getScreenWidth() / 2) { + this.mCircularActionMenu.expand(3); + } else { + this.mCircularActionMenu.expand(5); + } + + } + + public void setActiveAlpha(float activeAlpha) { + this.mActiveAlpha = activeAlpha; + if (this.mDragGesture != null) { + this.mDragGesture.setPressedAlpha(activeAlpha); + } + + } + + public void setInactiveAlpha(float inactiveAlpha) { + this.mInactiveAlpha = inactiveAlpha; + if (this.mDragGesture != null) { + this.mDragGesture.setUnpressedAlpha(this.mInactiveAlpha); + } + + } + + public void collapse() { + this.mDragGesture.setEnabled(true); + this.setMenuPositionAtActionView(); + this.mCircularActionMenu.collapse(); + this.mCircularActionView.setAlpha(this.mDragGesture.getUnpressedAlpha()); + } + + public boolean isExpanded() { + return this.mCircularActionMenu.isExpanded(); + } + + private void setMenuPositionAtActionView() { + int y = this.mActionViewWindowBridge.getY() - this.mCircularActionMenu.getMeasuredHeight() / 2 + this.mCircularActionView.getMeasuredHeight() / 2; + int x; + if (this.mActionViewWindowBridge.getX() > this.mActionViewWindowBridge.getScreenWidth() / 2) { + x = this.mActionViewWindowBridge.getX() - this.mCircularActionMenu.getExpandedWidth() + this.mCircularActionView.getMeasuredWidth() / 2; + } else { + x = this.mActionViewWindowBridge.getX() - this.mCircularActionMenu.getExpandedWidth() + this.mCircularActionView.getMeasuredWidth(); + } + + this.mMenuWindowBridge.updatePosition(x, y); + } + + private void inflateWindowViews(FloatyService service) { + this.mCircularActionMenu = this.mFloaty.inflateMenuItems(service, this); + this.mCircularActionView = this.mFloaty.inflateActionView(service, this); + this.mCircularActionMenu.setVisibility(View.GONE); + this.mWindowManager.addView(this.mCircularActionMenu, this.mActionViewWindowLayoutParams); + this.mWindowManager.addView(this.mCircularActionView, this.mMenuWindowLayoutParams); + } + + public void onServiceDestroy(FloatyService floatyService) { + this.close(); + } + + public void close() { + mOrientationEventListener.disable(); + this.mWindowManager.removeView(this.mCircularActionMenu); + this.mWindowManager.removeView(this.mCircularActionView); + FloatyService.removeWindow(this); + } + + @Override + public void onSensorChanged(SensorEvent event) { + mDragGesture.keepToEdge(); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/floating/OrientationAwareWindowBridge.java b/app/src/main/java/com/stardust/scriptdroid/ui/floating/OrientationAwareWindowBridge.java new file mode 100644 index 00000000..23e604a9 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/floating/OrientationAwareWindowBridge.java @@ -0,0 +1,47 @@ +package com.stardust.scriptdroid.ui.floating; + +import android.content.Context; +import android.content.res.Configuration; +import android.view.View; +import android.view.WindowManager; + +import com.stardust.enhancedfloaty.WindowBridge; + +public class OrientationAwareWindowBridge extends WindowBridge.DefaultImpl { + + + private Context mContext; + private int mOrientation; + + public OrientationAwareWindowBridge(WindowManager.LayoutParams windowLayoutParams, WindowManager windowManager, View windowView, Context context) { + super(windowLayoutParams, windowManager, windowView); + mContext = context; + mOrientation = mContext.getResources().getConfiguration().orientation; + } + + public boolean isOrientationChanged(int newOrientation) { + if (mOrientation != newOrientation) { + mOrientation = newOrientation; + return true; + } + return false; + } + + @Override + public int getScreenHeight() { + if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + return super.getScreenWidth(); + } else { + return super.getScreenHeight(); + } + } + + @Override + public int getScreenWidth() { + if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + return super.getScreenHeight(); + } else { + return super.getScreenWidth(); + } + } +}