replace hover with custom circular menu
This commit is contained in:
@@ -120,11 +120,11 @@ dependencies {
|
|||||||
//
|
//
|
||||||
compile 'com.github.hyb1996:android-multi-level-listview:1.1'
|
compile 'com.github.hyb1996:android-multi-level-listview:1.1'
|
||||||
compile 'de.psdev.licensesdialog:licensesdialog:1.8.1'
|
compile 'de.psdev.licensesdialog:licensesdialog:1.8.1'
|
||||||
compile 'io.mattcarroll.hover:hover:0.9.7'
|
|
||||||
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
|
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
|
||||||
compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'
|
compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'
|
||||||
compile 'com.wang.avi:library:2.1.3'
|
compile 'com.wang.avi:library:2.1.3'
|
||||||
compile 'org.apache.commons:commons-lang3:3.5'
|
compile 'org.apache.commons:commons-lang3:3.5'
|
||||||
|
compile 'com.github.hyb1996:FloatingCircularActionMenu:0.0.1'
|
||||||
// RxJava
|
// RxJava
|
||||||
compile "io.reactivex.rxjava2:rxjava:2.1.0"
|
compile "io.reactivex.rxjava2:rxjava:2.1.0"
|
||||||
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
package com.stardust.hover;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
|
|
||||||
import io.mattcarroll.hover.HoverMenu;
|
|
||||||
import io.mattcarroll.hover.HoverMenuAdapter;
|
|
||||||
import io.mattcarroll.hover.Navigator;
|
|
||||||
import io.mattcarroll.hover.defaulthovermenu.view.ViewHoverMenu;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class HoverMenuBuilder {
|
|
||||||
|
|
||||||
public static final int DISPLAY_MODE_WINDOW = 1; // Display directly in a window.
|
|
||||||
public static final int DISPLAY_MODE_VIEW = 2; // Display within View hierarchy.
|
|
||||||
|
|
||||||
private Context mContext;
|
|
||||||
private int mDisplayMode = DISPLAY_MODE_WINDOW;
|
|
||||||
private WindowManager mWindowManager;
|
|
||||||
private Navigator mNavigator;
|
|
||||||
private HoverMenuAdapter mAdapter;
|
|
||||||
private String mSavedVisualState = null;
|
|
||||||
|
|
||||||
public HoverMenuBuilder(@NonNull Context context) {
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HoverMenuBuilder displayWithinWindow() {
|
|
||||||
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
|
|
||||||
mDisplayMode = DISPLAY_MODE_WINDOW;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HoverMenuBuilder displayWithinView(@NonNull ViewGroup container) {
|
|
||||||
mDisplayMode = DISPLAY_MODE_VIEW;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HoverMenuBuilder useNavigator(@Nullable Navigator navigator) {
|
|
||||||
mNavigator = navigator;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HoverMenuBuilder useAdapter(@Nullable HoverMenuAdapter adapter) {
|
|
||||||
mAdapter = adapter;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HoverMenuBuilder restoreVisualState(@NonNull String visualState) {
|
|
||||||
mSavedVisualState = visualState;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HoverMenu build() {
|
|
||||||
if (DISPLAY_MODE_WINDOW == mDisplayMode) {
|
|
||||||
WindowHoverMenu windowHoverMenu = new WindowHoverMenu(mContext, mWindowManager, mNavigator, mSavedVisualState);
|
|
||||||
windowHoverMenu.setAdapter(mAdapter);
|
|
||||||
return windowHoverMenu;
|
|
||||||
} else {
|
|
||||||
ViewHoverMenu viewHoverMenu = new ViewHoverMenu(mContext);
|
|
||||||
viewHoverMenu.setAdapter(mAdapter);
|
|
||||||
return viewHoverMenu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.stardust.hover;
|
|
||||||
|
|
||||||
import io.mattcarroll.hover.defaulthovermenu.*;
|
|
||||||
import io.mattcarroll.hover.defaulthovermenu.HoverMenuView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/12.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class SimpleHoverMenuTransitionListener implements HoverMenuView.HoverMenuTransitionListener {
|
|
||||||
@Override
|
|
||||||
public void onCollapsing() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCollapsed() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExpanding() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExpanded() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
package com.stardust.hover;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.PointF;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.view.ViewConfiguration;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.mattcarroll.hover.HoverMenu;
|
|
||||||
import io.mattcarroll.hover.HoverMenuAdapter;
|
|
||||||
import io.mattcarroll.hover.Navigator;
|
|
||||||
import io.mattcarroll.hover.defaulthovermenu.HoverMenuView;
|
|
||||||
import io.mattcarroll.hover.defaulthovermenu.window.InWindowDragger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class WindowHoverMenu implements HoverMenu {
|
|
||||||
|
|
||||||
private HoverMenuView.HoverMenuTransitionListener mHoverMenuTransitionListener;
|
|
||||||
|
|
||||||
private static final String TAG = "WindowHoverMenu";
|
|
||||||
|
|
||||||
public WindowViewController getWindowViewController() {
|
|
||||||
return mWindowViewController;
|
|
||||||
}
|
|
||||||
|
|
||||||
private WindowViewController mWindowViewController; // Shows/hides/positions Views in a Window.
|
|
||||||
|
|
||||||
|
|
||||||
private HoverMenuView mHoverMenuView; // The visual presentation of the Hover menu.
|
|
||||||
private boolean mIsShowingHoverMenu; // Are we currently display mHoverMenuView?
|
|
||||||
private boolean mIsInDragMode; // If we're not in drag mode then we're in menu mode.
|
|
||||||
private Set<OnExitListener> mOnExitListeners = new HashSet<>();
|
|
||||||
|
|
||||||
private HoverMenuView.HoverMenuTransitionListener mHoverMenuTransitionListenerProxy = new HoverMenuView.HoverMenuTransitionListener() {
|
|
||||||
@Override
|
|
||||||
public void onCollapsing() {
|
|
||||||
if (mHoverMenuTransitionListener != null)
|
|
||||||
mHoverMenuTransitionListener.onCollapsing();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCollapsed() {
|
|
||||||
mIsInDragMode = true;
|
|
||||||
// When collapsed, we make mHoverMenuView untouchable so that the WindowDragWatcher can
|
|
||||||
// take over. We do this so that touch events outside the drag area can propagate to
|
|
||||||
// applications on screen.
|
|
||||||
mWindowViewController.makeUntouchable(mHoverMenuView);
|
|
||||||
if (mHoverMenuTransitionListener != null)
|
|
||||||
mHoverMenuTransitionListener.onCollapsed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExpanding() {
|
|
||||||
mIsInDragMode = false;
|
|
||||||
if (mHoverMenuTransitionListener != null)
|
|
||||||
mHoverMenuTransitionListener.onExpanding();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExpanded() {
|
|
||||||
mWindowViewController.makeTouchable(mHoverMenuView);
|
|
||||||
if (mHoverMenuTransitionListener != null)
|
|
||||||
mHoverMenuTransitionListener.onExpanded();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private HoverMenuView.HoverMenuExitRequestListener mMenuExitRequestListener = new HoverMenuView.HoverMenuExitRequestListener() {
|
|
||||||
@Override
|
|
||||||
public void onExitRequested() {
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public WindowHoverMenu(@NonNull Context context, @NonNull WindowManager windowManager, @Nullable Navigator navigator, @Nullable String savedVisualState) {
|
|
||||||
mWindowViewController = new WindowViewController(windowManager);
|
|
||||||
|
|
||||||
InWindowDragger inWindowDragger = new InWindowDragger(
|
|
||||||
context,
|
|
||||||
mWindowViewController,
|
|
||||||
ViewConfiguration.get(context).getScaledTouchSlop()
|
|
||||||
);
|
|
||||||
|
|
||||||
PointF anchorState = new PointF(2, 0.5f); // Default to right side, half way down. See CollapsedMenuAnchor.
|
|
||||||
if (null != savedVisualState) {
|
|
||||||
try {
|
|
||||||
VisualStateMemento visualStateMemento = VisualStateMemento.fromJsonString(savedVisualState);
|
|
||||||
anchorState.set(visualStateMemento.getAnchorSide(), visualStateMemento.getNormalizedPositionY());
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mHoverMenuView = new HoverMenuView(context, navigator, inWindowDragger, anchorState);
|
|
||||||
mHoverMenuView.setHoverMenuExitRequestListener(mMenuExitRequestListener);
|
|
||||||
mHoverMenuView.setHoverMenuTransitionListener(mHoverMenuTransitionListenerProxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setHoverMenuTransitionListener(HoverMenuView.HoverMenuTransitionListener hoverMenuTransitionListener) {
|
|
||||||
mHoverMenuTransitionListener = hoverMenuTransitionListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HoverMenuView getHoverMenuView() {
|
|
||||||
return mHoverMenuView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getVisualState() {
|
|
||||||
PointF anchor = mHoverMenuView.getAnchorState();
|
|
||||||
return new VisualStateMemento((int) anchor.x, anchor.y).toJsonString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void restoreVisualState(@NonNull String savedVisualState) {
|
|
||||||
try {
|
|
||||||
VisualStateMemento memento = VisualStateMemento.fromJsonString(savedVisualState);
|
|
||||||
mHoverMenuView.setAnchorState(new PointF(memento.getAnchorSide(), memento.getNormalizedPositionY()));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAdapter(@Nullable HoverMenuAdapter adapter) {
|
|
||||||
mHoverMenuView.setAdapter(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes and displays the Hover menu. To destroy and remove the Hover menu, use {@link #hide()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void show() {
|
|
||||||
if (!mIsShowingHoverMenu) {
|
|
||||||
mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, false, mHoverMenuView);
|
|
||||||
|
|
||||||
// Sync our control state with the HoverMenuView state.
|
|
||||||
if (mHoverMenuView.isExpanded()) {
|
|
||||||
mWindowViewController.makeTouchable(mHoverMenuView);
|
|
||||||
} else {
|
|
||||||
collapseMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
mIsShowingHoverMenu = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exits the Hover menu system. This method is the inverse of {@link #show()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void hide() {
|
|
||||||
if (mIsShowingHoverMenu) {
|
|
||||||
mIsShowingHoverMenu = false;
|
|
||||||
|
|
||||||
// Notify our exit listeners that we're exiting.
|
|
||||||
notifyOnExitListeners();
|
|
||||||
|
|
||||||
// Cleanup the control structures and Views.
|
|
||||||
mWindowViewController.removeView(mHoverMenuView);
|
|
||||||
mHoverMenuView.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expands the Hover menu to show all of its tabs and a content area for the selected tab. To
|
|
||||||
* collapse the menu down a single active tab, use {@link #collapseMenu()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void expandMenu() {
|
|
||||||
if (mIsInDragMode) {
|
|
||||||
mHoverMenuView.expand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collapses the Hover menu down to its single active tab and allows the tab to be dragged
|
|
||||||
* around the display. This method is the inverse of {@link #expandMenu()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void collapseMenu() {
|
|
||||||
if (!mIsInDragMode) {
|
|
||||||
mHoverMenuView.collapse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addOnExitListener(@NonNull OnExitListener onExitListener) {
|
|
||||||
mOnExitListeners.add(onExitListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeOnExitListener(@NonNull OnExitListener onExitListener) {
|
|
||||||
mOnExitListeners.remove(onExitListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyOnExitListeners() {
|
|
||||||
for (OnExitListener listener : mOnExitListeners) {
|
|
||||||
listener.onExitByUserRequest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class VisualStateMemento {
|
|
||||||
|
|
||||||
private static final String JSON_KEY_ANCHOR_SIDE = "anchor_side";
|
|
||||||
private static final String JSON_KEY_NORMALIZED_POSITION_Y = "normalized_position_y";
|
|
||||||
|
|
||||||
public static VisualStateMemento fromJsonString(@NonNull String jsonString) throws JSONException {
|
|
||||||
JSONObject jsonObject = new JSONObject(jsonString);
|
|
||||||
int anchorSide = jsonObject.getInt(JSON_KEY_ANCHOR_SIDE);
|
|
||||||
float normalizedPositionY = (float) jsonObject.getDouble(JSON_KEY_NORMALIZED_POSITION_Y);
|
|
||||||
return new VisualStateMemento(anchorSide, normalizedPositionY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int mAnchorSide;
|
|
||||||
private float mNormalizedPositionY;
|
|
||||||
|
|
||||||
public VisualStateMemento(int anchorSide, float normalizedPositionY) {
|
|
||||||
mAnchorSide = anchorSide;
|
|
||||||
mNormalizedPositionY = normalizedPositionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAnchorSide() {
|
|
||||||
return mAnchorSide;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getNormalizedPositionY() {
|
|
||||||
return mNormalizedPositionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toJsonString() {
|
|
||||||
try {
|
|
||||||
JSONObject jsonObject = new JSONObject();
|
|
||||||
jsonObject.put(JSON_KEY_ANCHOR_SIDE, mAnchorSide);
|
|
||||||
jsonObject.put(JSON_KEY_NORMALIZED_POSITION_Y, mNormalizedPositionY);
|
|
||||||
return jsonObject.toString();
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package com.stardust.hover;
|
|
||||||
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/7/2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class WindowViewController extends io.mattcarroll.hover.defaulthovermenu.window.WindowViewController {
|
|
||||||
|
|
||||||
private WindowManager mWindowManager;
|
|
||||||
|
|
||||||
public WindowViewController(@NonNull WindowManager windowManager) {
|
|
||||||
super(windowManager);
|
|
||||||
mWindowManager = windowManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addView(int width, int height, boolean isTouchable, @NonNull View view) {
|
|
||||||
int touchableFlag = isTouchable ? 0 : WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
|
||||||
|
|
||||||
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
WindowManager.LayoutParams.TYPE_PHONE,
|
|
||||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | touchableFlag,
|
|
||||||
PixelFormat.TRANSLUCENT
|
|
||||||
);
|
|
||||||
params.gravity = Gravity.TOP | Gravity.LEFT;
|
|
||||||
params.x = 0;
|
|
||||||
params.y = 0;
|
|
||||||
|
|
||||||
mWindowManager.addView(view, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,13 +2,16 @@ package com.stardust.scriptdroid.external.floatingwindow;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.stardust.enhancedfloaty.FloatyService;
|
import com.stardust.enhancedfloaty.FloatyService;
|
||||||
import com.stardust.enhancedfloaty.FloatyWindow;
|
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||||
import com.stardust.enhancedfloaty.util.FloatingWindowPermissionUtil;
|
import com.stardust.enhancedfloaty.util.FloatingWindowPermissionUtil;
|
||||||
|
import com.stardust.scriptdroid.App;
|
||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
|
import com.stardust.scriptdroid.ui.floating.CircularMenu;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
import ezy.assist.compat.SettingsCompat;
|
import ezy.assist.compat.SettingsCompat;
|
||||||
|
|
||||||
@@ -18,6 +21,8 @@ import ezy.assist.compat.SettingsCompat;
|
|||||||
|
|
||||||
public class FloatyWindowManger {
|
public class FloatyWindowManger {
|
||||||
|
|
||||||
|
private static WeakReference<CircularMenu> sCircularMenu;
|
||||||
|
|
||||||
public static void addWindow(Context context, FloatyWindow window) {
|
public static void addWindow(Context context, FloatyWindow window) {
|
||||||
context.startService(new Intent(context, FloatyService.class));
|
context.startService(new Intent(context, FloatyService.class));
|
||||||
if (!SettingsCompat.canDrawOverlays(context)) {
|
if (!SettingsCompat.canDrawOverlays(context)) {
|
||||||
@@ -49,4 +54,23 @@ public class FloatyWindowManger {
|
|||||||
public static void closeWindow(FloatyWindow window) {
|
public static void closeWindow(FloatyWindow window) {
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isCircularMenuShowing() {
|
||||||
|
return sCircularMenu != null && sCircularMenu.get() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showCircularMenu() {
|
||||||
|
App.getApp().startService(new Intent(App.getApp(), FloatyService.class));
|
||||||
|
CircularMenu menu = new CircularMenu(App.getApp());
|
||||||
|
sCircularMenu = new WeakReference<>(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void hideCircularMenu() {
|
||||||
|
if (sCircularMenu == null)
|
||||||
|
return;
|
||||||
|
CircularMenu menu = sCircularMenu.get();
|
||||||
|
menu.close();
|
||||||
|
sCircularMenu = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.support.annotation.RequiresApi;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.stardust.scriptdroid.App;
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
|
||||||
import com.stardust.util.IntentUtil;
|
|
||||||
|
|
||||||
import ezy.assist.compat.SettingsCompat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/10.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class HoverMenuManger {
|
|
||||||
|
|
||||||
private static final String KEY_FLOATING_WINDOW_PERMISSION = "May we go back..I...miss..you..Eating..17.5.9";
|
|
||||||
private static final String TAG = "HoverMenuManger";
|
|
||||||
|
|
||||||
public static void showHoverMenu() {
|
|
||||||
if (!HoverMenuService.isServiceRunning()) {
|
|
||||||
if (!SettingsCompat.canDrawOverlays(App.getApp())) {
|
|
||||||
Toast.makeText(App.getApp(), R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show();
|
|
||||||
try {
|
|
||||||
SettingsCompat.manageDrawOverlays(App.getApp());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
IntentUtil.goToAppDetailSettings(App.getApp());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
HoverMenuService.startService(App.getApp());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isHoverMenuShowing() {
|
|
||||||
return HoverMenuService.isServiceRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void hideHoverMenu() {
|
|
||||||
App.getApp().stopService(new Intent(App.getApp(), HoverMenuService.class));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.ShapeDrawable;
|
|
||||||
import android.graphics.drawable.shapes.OvalShape;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.support.annotation.ColorInt;
|
|
||||||
import android.support.annotation.DrawableRes;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.content.MainMenuNavigatorContent;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.content.RecordNavigatorContent;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.content.ScriptListNavigatorContent;
|
|
||||||
import com.stardust.theme.ThemeColorManagerCompat;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.mattcarroll.hover.NavigatorContent;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class HoverMenuAdapter implements io.mattcarroll.hover.HoverMenuAdapter {
|
|
||||||
|
|
||||||
|
|
||||||
public static final String ID_MAIN = "main";
|
|
||||||
public static final String ID_RECORD = "record";
|
|
||||||
public static final String ID_SCRIPT_LIST = "script_list";
|
|
||||||
|
|
||||||
private final Context mContext;
|
|
||||||
private final List<String> mTabIds;
|
|
||||||
private final Map<String, NavigatorContent> mData = new LinkedHashMap<>();
|
|
||||||
private final Set<io.mattcarroll.hover.HoverMenuAdapter.ContentChangeListener> mContentChangeListeners = new HashSet<>();
|
|
||||||
private View[] mViews;
|
|
||||||
|
|
||||||
public HoverMenuAdapter(@NonNull HoverMenuService context) {
|
|
||||||
mContext = context;
|
|
||||||
|
|
||||||
mData.put(HoverMenuAdapter.ID_MAIN, new MainMenuNavigatorContent(context));
|
|
||||||
mData.put(HoverMenuAdapter.ID_RECORD, new RecordNavigatorContent(context));
|
|
||||||
mData.put(HoverMenuAdapter.ID_SCRIPT_LIST, new ScriptListNavigatorContent(context));
|
|
||||||
|
|
||||||
mTabIds = new ArrayList<>();
|
|
||||||
for (String tabId : mData.keySet()) {
|
|
||||||
mTabIds.add(tabId);
|
|
||||||
}
|
|
||||||
mViews = new View[mTabIds.size()];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getTabCount() {
|
|
||||||
return mTabIds.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getTabView(int index) {
|
|
||||||
mViews[index] = getTabViewInner(index);
|
|
||||||
return mViews[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
private View getTabViewInner(int index) {
|
|
||||||
String menuItemId = mTabIds.get(index);
|
|
||||||
if (ID_MAIN.equals(menuItemId)) {
|
|
||||||
return createTabView(R.drawable.ic_android_eat_js_64);
|
|
||||||
} else if (ID_RECORD.equals(menuItemId)) {
|
|
||||||
return createTabView(R.drawable.ic_ali_record);
|
|
||||||
} else if (ID_SCRIPT_LIST.equals(menuItemId)) {
|
|
||||||
return createTabView(R.drawable.ic_menu);
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Unknown tab selected: " + index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getTabId(int position) {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NavigatorContent getNavigatorContent(int index) {
|
|
||||||
String tabId = mTabIds.get(index);
|
|
||||||
return mData.get(tabId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addContentChangeListener(@NonNull ContentChangeListener listener) {
|
|
||||||
mContentChangeListeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeContentChangeListener(@NonNull ContentChangeListener listener) {
|
|
||||||
mContentChangeListeners.remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void selectTab(String id) {
|
|
||||||
int i = mTabIds.indexOf(id);
|
|
||||||
mViews[i].performClick();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void notifyDataSetChanged() {
|
|
||||||
for (ContentChangeListener listener : mContentChangeListeners) {
|
|
||||||
listener.onContentChange(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private View createTabView(@DrawableRes int tabBitmapRes) {
|
|
||||||
return createTabView(tabBitmapRes, ThemeColorManagerCompat.getColorPrimary(), Color.WHITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private View createTabView(@DrawableRes int tabBitmapRes, @ColorInt int backgroundColor, @ColorInt Integer iconColor) {
|
|
||||||
Resources resources = mContext.getResources();
|
|
||||||
int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, resources.getDisplayMetrics());
|
|
||||||
|
|
||||||
DemoTabView view = new DemoTabView(mContext, getCircleDrawable(), resources.getDrawable(tabBitmapRes));
|
|
||||||
view.setTabBackgroundColor(backgroundColor);
|
|
||||||
view.setTabForegroundColor(iconColor);
|
|
||||||
view.setPadding(padding, padding, padding, padding);
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
view.setElevation(padding);
|
|
||||||
}
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Drawable getCircleDrawable() {
|
|
||||||
ShapeDrawable oval = new ShapeDrawable(new OvalShape());
|
|
||||||
return oval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class DemoTabView extends View {
|
|
||||||
|
|
||||||
private int mBackgroundColor;
|
|
||||||
private Integer mForegroundColor;
|
|
||||||
|
|
||||||
private Drawable mCircleDrawable;
|
|
||||||
private Drawable mIconDrawable;
|
|
||||||
private int mIconInsetLeft, mIconInsetTop, mIconInsetRight, mIconInsetBottom;
|
|
||||||
|
|
||||||
public DemoTabView(Context context, Drawable backgroundDrawable, Drawable iconDrawable) {
|
|
||||||
super(context);
|
|
||||||
mCircleDrawable = backgroundDrawable;
|
|
||||||
mIconDrawable = iconDrawable;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
int insetsDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getContext().getResources().getDisplayMetrics());
|
|
||||||
mIconInsetLeft = mIconInsetTop = mIconInsetRight = mIconInsetBottom = insetsDp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTabBackgroundColor(@ColorInt int backgroundColor) {
|
|
||||||
mBackgroundColor = backgroundColor;
|
|
||||||
mCircleDrawable.setColorFilter(mBackgroundColor, PorterDuff.Mode.SRC_ATOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTabForegroundColor(@ColorInt Integer foregroundColor) {
|
|
||||||
mForegroundColor = foregroundColor;
|
|
||||||
if (null != mForegroundColor) {
|
|
||||||
mIconDrawable.setColorFilter(mForegroundColor, PorterDuff.Mode.SRC_ATOP);
|
|
||||||
} else {
|
|
||||||
mIconDrawable.setColorFilter(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIcon(@Nullable Drawable icon) {
|
|
||||||
mIconDrawable = icon;
|
|
||||||
if (null != mForegroundColor && null != mIconDrawable) {
|
|
||||||
mIconDrawable.setColorFilter(mForegroundColor, PorterDuff.Mode.SRC_ATOP);
|
|
||||||
}
|
|
||||||
updateIconBounds();
|
|
||||||
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
|
||||||
mCircleDrawable.setBounds(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom());
|
|
||||||
updateIconBounds();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateIconBounds() {
|
|
||||||
if (null != mIconDrawable) {
|
|
||||||
Rect bounds = new Rect(mCircleDrawable.getBounds());
|
|
||||||
bounds.set(bounds.left + mIconInsetLeft, bounds.top + mIconInsetTop, bounds.right - mIconInsetRight, bounds.bottom - mIconInsetBottom);
|
|
||||||
mIconDrawable.setBounds(bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDraw(Canvas canvas) {
|
|
||||||
mCircleDrawable.draw(canvas);
|
|
||||||
if (null != mIconDrawable) {
|
|
||||||
mIconDrawable.draw(canvas);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu;
|
|
||||||
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.view.ContextThemeWrapper;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.stardust.hover.HoverMenuBuilder;
|
|
||||||
import com.stardust.hover.SimpleHoverMenuTransitionListener;
|
|
||||||
import com.stardust.hover.WindowHoverMenu;
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
|
||||||
import com.stardust.view.accessibility.NodeInfo;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView;
|
|
||||||
import com.stardust.theme.ThemeColorManagerCompat;
|
|
||||||
import com.stardust.util.IntentUtil;
|
|
||||||
import com.stardust.util.MessageEvent;
|
|
||||||
import com.stardust.util.MessageIntent;
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import ezy.assist.compat.SettingsCompat;
|
|
||||||
import io.mattcarroll.hover.HoverMenu;
|
|
||||||
import io.mattcarroll.hover.defaulthovermenu.window.WindowViewController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/11.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class HoverMenuService extends Service {
|
|
||||||
|
|
||||||
|
|
||||||
public static class ServiceStateChangedEvent {
|
|
||||||
ServiceStateChangedEvent(boolean state) {
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String ACTION_SHOW_AND_EXPAND_MENU = "ACTION_SHOW_AND_EXPAND_MENU";
|
|
||||||
public static final String ACTION_SHOW_LAYOUT_HIERARCHY = "ACTION_SHOW_LAYOUT_HIERARCHY";
|
|
||||||
public static final String ACTION_SHOW_LAYOUT_BOUNDS = "ACTION_SHOW_LAYOUT_BOUNDS";
|
|
||||||
public static final String ACTION_COLLAPSE_MENU = "ACTION_COLLAPSE_MENU";
|
|
||||||
public static final String ACTION_MENU_COLLAPSING = "ACTION_MENU_COLLAPSING";
|
|
||||||
public static final String ACTION_MENU_EXPANDING = "ACTION_MENU_EXPANDING";
|
|
||||||
public static final String ACTION_MENU_EXIT = "ACTION_MENU_EXIT";
|
|
||||||
public static final String ACTION_SHOW_NODE_LAYOUT_HIERARCHY = "ACTION_SHOW_NODE_LAYOUT_HIERARCHY";
|
|
||||||
public static final String ACTION_SHOW_NODE_LAYOUT_BOUNDS = "ACTION_SHOW_NODE_LAYOUT_BOUNDS";
|
|
||||||
|
|
||||||
public static final String EXTRA_NODE_INFO = "EXTRA_NODE_INFO";
|
|
||||||
|
|
||||||
|
|
||||||
private static boolean sIsRunning;
|
|
||||||
private static EventBus eventBus = new EventBus();
|
|
||||||
|
|
||||||
public static void startService(Context context) {
|
|
||||||
context.startService(new Intent(context, HoverMenuService.class));
|
|
||||||
setIsRunning(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isServiceRunning() {
|
|
||||||
return sIsRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setIsRunning(boolean isRunning) {
|
|
||||||
sIsRunning = isRunning;
|
|
||||||
eventBus.post(new ServiceStateChangedEvent(sIsRunning));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void postIntent(Intent intent) {
|
|
||||||
eventBus.post(new MessageIntent(intent));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void postMessageIntent(MessageIntent intent) {
|
|
||||||
eventBus.post(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static EventBus getEventBus() {
|
|
||||||
return eventBus;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String TAG = "HoverMenuService";
|
|
||||||
|
|
||||||
private static final String PREF_FILE = "hover_menu";
|
|
||||||
private static final String PREF_HOVER_MENU_VISUAL_STATE = "hover_menu_visual_state";
|
|
||||||
|
|
||||||
private SharedPreferences mPrefs;
|
|
||||||
|
|
||||||
private WindowViewController mWindowViewController;
|
|
||||||
|
|
||||||
private ContextThemeWrapper mThemeWrapper;
|
|
||||||
private FloatingLayoutHierarchyView mFloatingLayoutHierarchyView;
|
|
||||||
private FloatingLayoutBoundsView mFloatingLayoutBoundsView;
|
|
||||||
|
|
||||||
private WindowHoverMenu mWindowHoverMenu;
|
|
||||||
private HoverMenu.OnExitListener mWindowHoverMenuMenuExitListener = new HoverMenu.OnExitListener() {
|
|
||||||
@Override
|
|
||||||
public void onExitByUserRequest() {
|
|
||||||
eventBus.post(new MessageEvent(ACTION_MENU_EXIT));
|
|
||||||
savePreferredLocation();
|
|
||||||
mWindowHoverMenu.hide();
|
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
eventBus.register(this);
|
|
||||||
mPrefs = getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
|
|
||||||
tryInitViews();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryInitViews() {
|
|
||||||
try {
|
|
||||||
initViews();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Toast.makeText(this, R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show();
|
|
||||||
try {
|
|
||||||
SettingsCompat.manageDrawOverlays(this);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
IntentUtil.goToAppDetailSettings(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initViews() {
|
|
||||||
mThemeWrapper = new ContextThemeWrapper(this, R.style.AppTheme);
|
|
||||||
mFloatingLayoutHierarchyView = new FloatingLayoutHierarchyView(mThemeWrapper);
|
|
||||||
mFloatingLayoutBoundsView = new FloatingLayoutBoundsView(mThemeWrapper);
|
|
||||||
initWindowMenu();
|
|
||||||
mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutHierarchyView);
|
|
||||||
mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutBoundsView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initWindowMenu() {
|
|
||||||
mWindowHoverMenu = (WindowHoverMenu) new HoverMenuBuilder(mThemeWrapper)
|
|
||||||
.displayWithinWindow()
|
|
||||||
.useAdapter(new HoverMenuAdapter(this))
|
|
||||||
.restoreVisualState(loadPreferredLocation())
|
|
||||||
.build();
|
|
||||||
mWindowHoverMenu.getHoverMenuView().setContentBackgroundColor(ThemeColorManagerCompat.getColorPrimary());
|
|
||||||
mWindowHoverMenu.addOnExitListener(mWindowHoverMenuMenuExitListener);
|
|
||||||
mWindowViewController = mWindowHoverMenu.getWindowViewController();
|
|
||||||
mWindowHoverMenu.setHoverMenuTransitionListener(new SimpleHoverMenuTransitionListener() {
|
|
||||||
@Override
|
|
||||||
public void onExpanding() {
|
|
||||||
eventBus.post(new MessageEvent(ACTION_MENU_EXPANDING));
|
|
||||||
captureCurrentWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCollapsing() {
|
|
||||||
AutoJs.getInstance().getLayoutInspector().clearCapture();
|
|
||||||
eventBus.post(new MessageEvent(ACTION_MENU_COLLAPSING));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void captureCurrentWindow() {
|
|
||||||
AutoJs.getInstance().getLayoutInspector().captureCurrentWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
if (mWindowHoverMenu == null)
|
|
||||||
tryInitViews();
|
|
||||||
if (mWindowHoverMenu != null)
|
|
||||||
mWindowHoverMenu.show();
|
|
||||||
return START_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
if (mWindowHoverMenu != null)
|
|
||||||
mWindowHoverMenu.hide();
|
|
||||||
if (eventBus.isRegistered(this))
|
|
||||||
eventBus.unregister(this);
|
|
||||||
setIsRunning(false);
|
|
||||||
if (mWindowViewController == null)
|
|
||||||
return;
|
|
||||||
mWindowViewController.removeView(mFloatingLayoutBoundsView);
|
|
||||||
mWindowViewController.removeView(mFloatingLayoutHierarchyView);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void savePreferredLocation() {
|
|
||||||
String memento = mWindowHoverMenu.getVisualState();
|
|
||||||
mPrefs.edit().putString(PREF_HOVER_MENU_VISUAL_STATE, memento).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String loadPreferredLocation() {
|
|
||||||
return mPrefs.getString(PREF_HOVER_MENU_VISUAL_STATE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void handleMessageIntent(MessageIntent intent) {
|
|
||||||
switch (intent.getAction()) {
|
|
||||||
case ACTION_SHOW_AND_EXPAND_MENU:
|
|
||||||
showAndExpandMenu();
|
|
||||||
break;
|
|
||||||
case ACTION_SHOW_LAYOUT_HIERARCHY:
|
|
||||||
showLayoutHierarchy();
|
|
||||||
break;
|
|
||||||
case ACTION_SHOW_LAYOUT_BOUNDS:
|
|
||||||
showLayoutBounds();
|
|
||||||
break;
|
|
||||||
case ACTION_COLLAPSE_MENU:
|
|
||||||
mWindowHoverMenu.collapseMenu();
|
|
||||||
break;
|
|
||||||
case ACTION_SHOW_NODE_LAYOUT_BOUNDS:
|
|
||||||
mFloatingLayoutHierarchyView.setVisibility(View.GONE);
|
|
||||||
showLayoutBounds();
|
|
||||||
mFloatingLayoutBoundsView.setSelectedNode((NodeInfo) intent.getObjectExtra(EXTRA_NODE_INFO));
|
|
||||||
break;
|
|
||||||
case ACTION_SHOW_NODE_LAYOUT_HIERARCHY:
|
|
||||||
mFloatingLayoutBoundsView.setVisibility(View.GONE);
|
|
||||||
showLayoutHierarchy();
|
|
||||||
mFloatingLayoutHierarchyView.setSelectedNode((NodeInfo) intent.getObjectExtra(EXTRA_NODE_INFO));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showLayoutBounds() {
|
|
||||||
mFloatingLayoutBoundsView.setRootNode(AutoJs.getInstance().getLayoutInspector().getCapture());
|
|
||||||
mWindowHoverMenu.getHoverMenuView().setVisibility(View.GONE);
|
|
||||||
showView(mFloatingLayoutBoundsView);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showLayoutHierarchy() {
|
|
||||||
mFloatingLayoutHierarchyView.setRootNode(AutoJs.getInstance().getLayoutInspector().getCapture());
|
|
||||||
mWindowHoverMenu.getHoverMenuView().setVisibility(View.GONE);
|
|
||||||
showView(mFloatingLayoutHierarchyView);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showAndExpandMenu() {
|
|
||||||
showView(mWindowHoverMenu.getHoverMenuView());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void showView(View view) {
|
|
||||||
view.setVisibility(View.VISIBLE);
|
|
||||||
mWindowViewController.makeTouchable(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.content;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.stardust.scriptdroid.App;
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
|
||||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
|
||||||
import com.stardust.scriptdroid.ui.main.MainActivity_;
|
|
||||||
import com.stardust.util.ClipboardUtil;
|
|
||||||
import com.stardust.util.MessageEvent;
|
|
||||||
import com.stardust.view.accessibility.AccessibilityService;
|
|
||||||
import com.stardust.view.accessibility.LayoutInspector;
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.OnClick;
|
|
||||||
import io.mattcarroll.hover.Navigator;
|
|
||||||
import io.mattcarroll.hover.NavigatorContent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/12.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MainMenuNavigatorContent implements NavigatorContent {
|
|
||||||
|
|
||||||
private View mView;
|
|
||||||
@BindView(R.id.current_package)
|
|
||||||
TextView mCurrentPackageTextView;
|
|
||||||
@BindView(R.id.current_activity)
|
|
||||||
TextView mCurrentActivityTextView;
|
|
||||||
private String mCurrentPackage, mCurrentActivity;
|
|
||||||
private Context mContext;
|
|
||||||
|
|
||||||
public MainMenuNavigatorContent(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
mView = View.inflate(context, R.layout.floating_window_main_menu, null);
|
|
||||||
ButterKnife.bind(this, mView);
|
|
||||||
HoverMenuService.getEventBus().register(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.layout_hierarchy)
|
|
||||||
void showLayoutHierarchy() {
|
|
||||||
if (!ensureCapture()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_LAYOUT_HIERARCHY));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean ensureCapture() {
|
|
||||||
LayoutInspector inspector = AutoJs.getInstance().getLayoutInspector();
|
|
||||||
if (inspector.isDumping()) {
|
|
||||||
Toast.makeText(mView.getContext(), R.string.text_layout_inspector_is_dumping, Toast.LENGTH_SHORT).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (AccessibilityService.getInstance() == null) {
|
|
||||||
Toast.makeText(mView.getContext(), R.string.text_no_accessibility_permission_to_capture, Toast.LENGTH_SHORT).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (inspector.getCapture() == null) {
|
|
||||||
Toast.makeText(mView.getContext(), R.string.text_inspect_failed, Toast.LENGTH_SHORT).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.layout_bounds)
|
|
||||||
void showLayoutBounds() {
|
|
||||||
if (!ensureCapture()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_LAYOUT_BOUNDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.stop_all_running_scripts)
|
|
||||||
void stopAllRunningScripts() {
|
|
||||||
AutoJs.getInstance().getScriptEngineService().stopAllAndToast();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.open_launcher)
|
|
||||||
void openMainActivity() {
|
|
||||||
App.getApp().startActivity(new Intent(App.getApp(), MainActivity_.class)
|
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.open_accessibility_settings)
|
|
||||||
void openAccessibilitySettings() {
|
|
||||||
AccessibilityServiceTool.enableAccessibilityService();
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public View getView() {
|
|
||||||
return mView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShown(@NonNull Navigator navigator) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
private void syncCurrentInfo() {
|
|
||||||
mCurrentPackage = AutoJs.getInstance().getInfoProvider().getLatestPackage();
|
|
||||||
mCurrentActivity = AutoJs.getInstance().getInfoProvider().getLatestActivity();
|
|
||||||
mCurrentActivityTextView.setText(mContext.getString(R.string.text_current_activity) + mCurrentActivity);
|
|
||||||
mCurrentPackageTextView.setText(mContext.getString(R.string.text_current_package) + mCurrentPackage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.current_activity)
|
|
||||||
void copyCurrentActivity() {
|
|
||||||
ClipboardUtil.setClip(mContext, mCurrentActivity);
|
|
||||||
Toast.makeText(mContext, R.string.text_copied, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.current_package)
|
|
||||||
void copyCurrentPackage() {
|
|
||||||
ClipboardUtil.setClip(mContext, mCurrentPackage);
|
|
||||||
Toast.makeText(mContext, R.string.text_copied, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onHidden() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onMessageEvent(MessageEvent event) {
|
|
||||||
if (event.message.equals(HoverMenuService.ACTION_MENU_EXPANDING)) {
|
|
||||||
syncCurrentInfo();
|
|
||||||
} else if (event.message.equals(HoverMenuService.ACTION_MENU_EXIT)) {
|
|
||||||
HoverMenuService.getEventBus().unregister(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.content;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.v7.widget.SwitchCompat;
|
|
||||||
import android.view.ContextThemeWrapper;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.DialogAction;
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
|
||||||
import com.stardust.app.DialogUtils;
|
|
||||||
import com.stardust.autojs.core.record.Recorder;
|
|
||||||
import com.stardust.autojs.core.record.accessibility.AccessibilityActionRecorder;
|
|
||||||
import com.stardust.autojs.core.inputevent.InputEventObserver;
|
|
||||||
import com.stardust.autojs.core.inputevent.ShellKeyObserver;
|
|
||||||
import com.stardust.autojs.core.record.inputevent.TouchRecorder;
|
|
||||||
import com.stardust.scriptdroid.App;
|
|
||||||
import com.stardust.scriptdroid.Pref;
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.accessibility.AccessibilityEventHelper;
|
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
|
||||||
import com.stardust.scriptdroid.autojs.key.GlobalKeyObserver;
|
|
||||||
import com.stardust.scriptdroid.autojs.record.GlobalRecorder;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
|
||||||
import com.stardust.scriptdroid.ui.common.ScriptOperations;
|
|
||||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
|
||||||
import com.stardust.util.ClipboardUtil;
|
|
||||||
import com.stardust.util.MessageEvent;
|
|
||||||
import com.stardust.view.accessibility.AccessibilityService;
|
|
||||||
import com.stardust.view.accessibility.OnKeyListener;
|
|
||||||
import com.stardust.widget.PrefSwitch;
|
|
||||||
import com.stardust.widget.ViewSwitcher;
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.OnClick;
|
|
||||||
import io.mattcarroll.hover.Navigator;
|
|
||||||
import io.mattcarroll.hover.NavigatorContent;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/12.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStateChangedListener, GlobalKeyObserver.OnVolumeDownListener {
|
|
||||||
|
|
||||||
private View mView;
|
|
||||||
@BindView(R.id.sw_recorded_by_root)
|
|
||||||
PrefSwitch mRecordedByRootSwitch;
|
|
||||||
|
|
||||||
@BindView(R.id.sw_record_toast)
|
|
||||||
PrefSwitch mRecordToastSwitch;
|
|
||||||
|
|
||||||
@BindView(R.id.img_pause_or_resume)
|
|
||||||
ImageView mPauseOrResumeImage;
|
|
||||||
|
|
||||||
@BindView(R.id.text_pause_or_resume)
|
|
||||||
TextView mPauseOrResumeText;
|
|
||||||
|
|
||||||
@BindView(R.id.view_switcher)
|
|
||||||
ViewSwitcher mViewSwitcher;
|
|
||||||
|
|
||||||
private GlobalRecorder mRecorder;
|
|
||||||
private Context mContext;
|
|
||||||
private long mLastVolumeDownEventTime;
|
|
||||||
|
|
||||||
public RecordNavigatorContent(Context context) {
|
|
||||||
mContext = new ContextThemeWrapper(context, R.style.AppTheme);
|
|
||||||
mView = View.inflate(mContext, R.layout.floating_window_record, null);
|
|
||||||
ButterKnife.bind(this, mView);
|
|
||||||
HoverMenuService.getEventBus().register(this);
|
|
||||||
mRecorder = GlobalRecorder.getSingleton(context);
|
|
||||||
mRecorder.addOnStateChangedListener(this);
|
|
||||||
setState(mRecorder.getState());
|
|
||||||
GlobalKeyObserver.getSingleton().addVolumeDownListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onVolumeDown() {
|
|
||||||
if (!Pref.isRecordVolumeControlEnable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (System.currentTimeMillis() - mLastVolumeDownEventTime < 300) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mLastVolumeDownEventTime = System.currentTimeMillis();
|
|
||||||
int state = mRecorder.getState();
|
|
||||||
if (state == Recorder.STATE_RECORDING || state == Recorder.STATE_PAUSED) {
|
|
||||||
mRecorder.stop();
|
|
||||||
} else {
|
|
||||||
mRecorder.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public View getView() {
|
|
||||||
return mView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShown(@NonNull Navigator navigator) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onHidden() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sw_root_container)
|
|
||||||
void toggleRecordedByRootSwitch() {
|
|
||||||
mRecordedByRootSwitch.toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sw_record_toast_container)
|
|
||||||
void toggleRecordToastSwitch() {
|
|
||||||
mRecordToastSwitch.toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.start_record)
|
|
||||||
void startRecord() {
|
|
||||||
mRecorder.start();
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.discard_record)
|
|
||||||
void discardRecord() {
|
|
||||||
mRecorder.discard();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@OnClick(R.id.pause_or_resume_record)
|
|
||||||
void pauseOrResumeRecord() {
|
|
||||||
if (mRecorder.getState() == Recorder.STATE_PAUSED) {
|
|
||||||
mRecorder.resume();
|
|
||||||
} else {
|
|
||||||
mRecorder.pause();
|
|
||||||
}
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setState(int state) {
|
|
||||||
if (state == Recorder.STATE_NOT_START || state == Recorder.STATE_STOPPED) {
|
|
||||||
mViewSwitcher.showFirst();
|
|
||||||
} else {
|
|
||||||
mViewSwitcher.showSecond();
|
|
||||||
}
|
|
||||||
mPauseOrResumeImage.setImageResource(state == Recorder.STATE_RECORDING ? R.drawable.ic_pause_white_24dp :
|
|
||||||
R.drawable.ic_play_arrow_white_48dp);
|
|
||||||
mPauseOrResumeText.setText(
|
|
||||||
state == Recorder.STATE_RECORDING ? R.string.text_pause_record : R.string.text_resume_record);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.stop_record)
|
|
||||||
void stopRecord() {
|
|
||||||
mRecorder.stop();
|
|
||||||
setState(Recorder.STATE_STOPPED);
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onMessageEvent(MessageEvent event) {
|
|
||||||
if (event.message.equals(HoverMenuService.ACTION_MENU_EXPANDING)) {
|
|
||||||
if (mRecorder.getState() == Recorder.STATE_RECORDING)
|
|
||||||
mRecorder.pause();
|
|
||||||
} else if (event.message.equals(HoverMenuService.ACTION_MENU_EXIT)) {
|
|
||||||
onMenuExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMenuExit() {
|
|
||||||
HoverMenuService.getEventBus().unregister(this);
|
|
||||||
mRecorder.removeOnStateChangedListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStart() {
|
|
||||||
setState(Recorder.STATE_RECORDING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStop() {
|
|
||||||
setState(Recorder.STATE_STOPPED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
setState(Recorder.STATE_PAUSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
setState(Recorder.STATE_RECORDING);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.content;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.view.ContextThemeWrapper;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.workground.WrapContentLinearLayoutManager;
|
|
||||||
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
|
||||||
import com.stardust.scriptdroid.script.ScriptFile;
|
|
||||||
import com.stardust.scriptdroid.script.Scripts;
|
|
||||||
import com.stardust.scriptdroid.script.StorageFileProvider;
|
|
||||||
import com.stardust.scriptdroid.ui.common.ScriptLoopDialog;
|
|
||||||
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
|
||||||
import com.stardust.scriptdroid.ui.main.scripts.ScriptListRecyclerView;
|
|
||||||
import com.stardust.scriptdroid.ui.main.scripts.ScriptListWithProgressBarView;
|
|
||||||
import com.stardust.widget.ViewHolderSupplier;
|
|
||||||
|
|
||||||
import io.mattcarroll.hover.Navigator;
|
|
||||||
import io.mattcarroll.hover.NavigatorContent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/12.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class ScriptListNavigatorContent implements NavigatorContent {
|
|
||||||
|
|
||||||
private ViewHolderSupplier<ScriptListRecyclerView.ViewHolder> mViewHolderSupplier = new ViewHolderSupplier<ScriptListRecyclerView.ViewHolder>() {
|
|
||||||
@Override
|
|
||||||
public ScriptListRecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) {
|
|
||||||
switch (viewType) {
|
|
||||||
case ScriptListRecyclerView.VIEW_TYPE_FILE:
|
|
||||||
return new FileViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.floating_script_list_recycler_view_file, parent, false));
|
|
||||||
case ScriptListRecyclerView.VIEW_TYPE_DIRECTORY:
|
|
||||||
return new DirectoryViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.floating_script_list_recycler_view_directory, parent, false));
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private ScriptListRecyclerView mFloatingScriptFileListView;
|
|
||||||
private ScriptListWithProgressBarView mScriptListWithProgressBarView;
|
|
||||||
|
|
||||||
public ScriptListNavigatorContent(Context context) {
|
|
||||||
mScriptListWithProgressBarView = new ScriptListWithProgressBarView(new ContextThemeWrapper(context, R.style.AppTheme));
|
|
||||||
mFloatingScriptFileListView = mScriptListWithProgressBarView.getScriptAndFolderListRecyclerView();
|
|
||||||
mFloatingScriptFileListView.setViewHolderSupplier(mViewHolderSupplier);
|
|
||||||
mFloatingScriptFileListView.setLayoutManager(new WrapContentLinearLayoutManager(context));
|
|
||||||
mFloatingScriptFileListView.setStorageFileProvider(StorageFileProvider.getDefault());
|
|
||||||
mFloatingScriptFileListView.setOnItemClickListener(new ScriptListRecyclerView.OnScriptFileClickListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(ScriptFile file, int position) {
|
|
||||||
Scripts.run(file);
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public View getView() {
|
|
||||||
return mScriptListWithProgressBarView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShown(@NonNull Navigator navigator) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onHidden() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DirectoryViewHolder extends ScriptListRecyclerView.ViewHolder {
|
|
||||||
|
|
||||||
DirectoryViewHolder(View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
itemView.setOnClickListener(mFloatingScriptFileListView.getOnItemClickListenerProxy());
|
|
||||||
itemView.setOnLongClickListener(mFloatingScriptFileListView.getOnItemLongClickListenerProxy());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FileViewHolder extends DirectoryViewHolder {
|
|
||||||
|
|
||||||
private ImageView mIcon;
|
|
||||||
private View mEdit;
|
|
||||||
|
|
||||||
FileViewHolder(final View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
mIcon = (ImageView) itemView.findViewById(R.id.icon);
|
|
||||||
mEdit = itemView.findViewById(R.id.edit);
|
|
||||||
mEdit.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
EditActivity.editFile(v.getContext(), getScriptFile());
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
itemView.setOnLongClickListener(new View.OnLongClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View v) {
|
|
||||||
new ScriptLoopDialog(v.getContext(), getScriptFile())
|
|
||||||
.windowType(WindowManager.LayoutParams.TYPE_PHONE)
|
|
||||||
.show();
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind(ScriptFile file) {
|
|
||||||
super.bind(file);
|
|
||||||
mIcon.setImageResource(file.getType() == ScriptFile.TYPE_AUTO ? R.drawable.record_icon_18
|
|
||||||
: R.drawable.ic_node_js_black);
|
|
||||||
mEdit.setVisibility(file.getType() == ScriptFile.TYPE_JAVA_SCRIPT ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScriptFile getScriptFile() {
|
|
||||||
return mFloatingScriptFileListView.getAdapter().getScriptFileAt(getAdapterPosition());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
|
||||||
import com.afollestad.materialdialogs.Theme;
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
|
||||||
import com.stardust.view.accessibility.NodeInfo;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutBoundsView;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.NodeInfoView;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.OnNodeInfoSelectListener;
|
|
||||||
import com.stardust.util.MessageIntent;
|
|
||||||
import com.stardust.widget.BubblePopupMenu;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/12.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FloatingLayoutBoundsView extends LayoutBoundsView {
|
|
||||||
|
|
||||||
private MaterialDialog mNodeInfoDialog;
|
|
||||||
private BubblePopupMenu mBubblePopMenu;
|
|
||||||
private NodeInfoView mNodeInfoView;
|
|
||||||
private NodeInfo mSelectedNode;
|
|
||||||
|
|
||||||
public FloatingLayoutBoundsView(Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
setOnNodeInfoSelectListener(new OnNodeInfoSelectListener() {
|
|
||||||
@Override
|
|
||||||
public void onNodeSelect(NodeInfo info) {
|
|
||||||
mSelectedNode = info;
|
|
||||||
ensureOperationPopMenu();
|
|
||||||
if (mBubblePopMenu.getContentView().getMeasuredWidth() <= 0)
|
|
||||||
mBubblePopMenu.preMeasure();
|
|
||||||
mBubblePopMenu.showAsDropDownAtLocation(FloatingLayoutBoundsView.this, info.getBoundsInScreen().height(), info.getBoundsInScreen().centerX() - mBubblePopMenu.getContentView().getMeasuredWidth() / 2, info.getBoundsInScreen().bottom - getStatusBarHeight());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setVisibility(GONE);
|
|
||||||
getBoundsPaint().setStrokeWidth(2f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void showNodeInfo() {
|
|
||||||
ensureDialog();
|
|
||||||
mNodeInfoView.setNodeInfo(mSelectedNode);
|
|
||||||
mNodeInfoDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureOperationPopMenu() {
|
|
||||||
if (mBubblePopMenu != null)
|
|
||||||
return;
|
|
||||||
mBubblePopMenu = new BubblePopupMenu(getContext(), Arrays.asList(
|
|
||||||
getResources().getString(R.string.text_show_widget_infomation),
|
|
||||||
getResources().getString(R.string.text_show_layout_hierarchy)));
|
|
||||||
mBubblePopMenu.setOnItemClickListener(new BubblePopupMenu.OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view, int position) {
|
|
||||||
mBubblePopMenu.dismiss();
|
|
||||||
if (position == 0) {
|
|
||||||
showNodeInfo();
|
|
||||||
} else {
|
|
||||||
HoverMenuService.postMessageIntent(new MessageIntent(HoverMenuService.ACTION_SHOW_NODE_LAYOUT_HIERARCHY)
|
|
||||||
.putExtra(HoverMenuService.EXTRA_NODE_INFO, mSelectedNode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mBubblePopMenu.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
mBubblePopMenu.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureDialog() {
|
|
||||||
if (mNodeInfoDialog == null) {
|
|
||||||
mNodeInfoView = new NodeInfoView(getContext());
|
|
||||||
mNodeInfoDialog = new MaterialDialog.Builder(getContext())
|
|
||||||
.customView(mNodeInfoView, false)
|
|
||||||
.theme(Theme.LIGHT)
|
|
||||||
.build();
|
|
||||||
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
|
||||||
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_AND_EXPAND_MENU));
|
|
||||||
setVisibility(GONE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.dispatchKeyEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
|
||||||
import com.afollestad.materialdialogs.Theme;
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
|
||||||
import com.stardust.view.accessibility.NodeInfo;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutHierarchyView;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.NodeInfoView;
|
|
||||||
import com.stardust.util.MessageIntent;
|
|
||||||
import com.stardust.widget.BubblePopupMenu;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/12.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FloatingLayoutHierarchyView extends LayoutHierarchyView {
|
|
||||||
|
|
||||||
private static final String TAG = "FloatingHierarchyView";
|
|
||||||
private static final int COLOR_SHADOW = 0xddffffff;
|
|
||||||
|
|
||||||
private MaterialDialog mNodeInfoDialog;
|
|
||||||
private BubblePopupMenu mBubblePopMenu;
|
|
||||||
private NodeInfoView mNodeInfoView;
|
|
||||||
private NodeInfo mSelectedNodeInfo;
|
|
||||||
|
|
||||||
public FloatingLayoutHierarchyView(Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
setBackgroundColor(COLOR_SHADOW);
|
|
||||||
setVisibility(GONE);
|
|
||||||
setShowClickedNodeBounds(true);
|
|
||||||
getBoundsPaint().setStrokeWidth(3);
|
|
||||||
getBoundsPaint().setColor(0xFFD32F2F);
|
|
||||||
setOnItemLongClickListener(new OnItemLongClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemLongClick(View view, NodeInfo nodeInfo) {
|
|
||||||
mSelectedNodeInfo = nodeInfo;
|
|
||||||
ensureOperationPopMenu();
|
|
||||||
if (mBubblePopMenu.getContentView().getMeasuredWidth() <= 0)
|
|
||||||
mBubblePopMenu.preMeasure();
|
|
||||||
mBubblePopMenu.showAsDropDown(view, view.getWidth() / 2 - mBubblePopMenu.getContentView().getMeasuredWidth() / 2, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureOperationPopMenu() {
|
|
||||||
if (mBubblePopMenu != null)
|
|
||||||
return;
|
|
||||||
mBubblePopMenu = new BubblePopupMenu(getContext(), Arrays.asList(
|
|
||||||
getResources().getString(R.string.text_show_widget_infomation),
|
|
||||||
getResources().getString(R.string.text_show_layout_bounds)));
|
|
||||||
mBubblePopMenu.setOnItemClickListener(new BubblePopupMenu.OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view, int position) {
|
|
||||||
mBubblePopMenu.dismiss();
|
|
||||||
if (position == 0) {
|
|
||||||
showNodeInfo();
|
|
||||||
} else {
|
|
||||||
HoverMenuService.postMessageIntent(new MessageIntent(HoverMenuService.ACTION_SHOW_NODE_LAYOUT_BOUNDS)
|
|
||||||
.putExtra(HoverMenuService.EXTRA_NODE_INFO, mSelectedNodeInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mBubblePopMenu.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
mBubblePopMenu.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void showNodeInfo() {
|
|
||||||
ensureNodeInfoDialog();
|
|
||||||
mNodeInfoView.setNodeInfo(mSelectedNodeInfo);
|
|
||||||
mNodeInfoDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureNodeInfoDialog() {
|
|
||||||
if (mNodeInfoDialog == null) {
|
|
||||||
mNodeInfoView = new NodeInfoView(getContext());
|
|
||||||
mNodeInfoDialog = new MaterialDialog.Builder(getContext())
|
|
||||||
.customView(mNodeInfoView, false)
|
|
||||||
.theme(Theme.LIGHT)
|
|
||||||
.build();
|
|
||||||
if (mNodeInfoDialog.getWindow() != null)
|
|
||||||
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
|
||||||
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
|
||||||
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_AND_EXPAND_MENU));
|
|
||||||
setVisibility(GONE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.dispatchKeyEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
package com.stardust.scriptdroid.ui.floating;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.stardust.enhancedfloaty.FloatyService;
|
||||||
|
import com.stardust.floatingcircularactionmenu.CircularActionMenu;
|
||||||
|
import com.stardust.floatingcircularactionmenu.CircularActionMenuFloatingWindow;
|
||||||
|
import com.stardust.floatingcircularactionmenu.CircularActionMenuFloaty;
|
||||||
|
import com.stardust.scriptdroid.R;
|
||||||
|
import com.stardust.scriptdroid.accessibility.AccessibilityService;
|
||||||
|
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||||
|
import com.stardust.scriptdroid.ui.floating.layoutinspector.LayoutBoundsFloatyWindow;
|
||||||
|
import com.stardust.scriptdroid.ui.floating.layoutinspector.LayoutHierarchyFloatyWindow;
|
||||||
|
import com.stardust.scriptdroid.ui.floating.layoutinspector.LayoutHierarchyView;
|
||||||
|
import com.stardust.view.accessibility.LayoutInspector;
|
||||||
|
|
||||||
|
import org.androidannotations.annotations.Click;
|
||||||
|
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/10/18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CircularMenu {
|
||||||
|
|
||||||
|
|
||||||
|
private static final int STATE_NORMAL = 0;
|
||||||
|
private static final int STATE_RECORDING = 1;
|
||||||
|
|
||||||
|
CircularActionMenuFloatingWindow mWindow;
|
||||||
|
private int mState;
|
||||||
|
private ImageView mActionViewIcon;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
|
||||||
|
public CircularMenu(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
initFloaty();
|
||||||
|
setupListeners();
|
||||||
|
FloatyService.addWindow(mWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupListeners() {
|
||||||
|
mWindow.setOnActionViewClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mState == STATE_RECORDING) {
|
||||||
|
stopRecord();
|
||||||
|
} else if (mWindow.isExpanded()) {
|
||||||
|
mWindow.collapse();
|
||||||
|
} else {
|
||||||
|
AutoJs.getInstance().getLayoutInspector().captureCurrentWindow();
|
||||||
|
mWindow.expand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initFloaty() {
|
||||||
|
mWindow = new CircularActionMenuFloatingWindow(new CircularActionMenuFloaty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View inflateActionView(FloatyService service, CircularActionMenuFloatingWindow window) {
|
||||||
|
View actionView = View.inflate(service, R.layout.circular_action_view, null);
|
||||||
|
mActionViewIcon = (ImageView) actionView.findViewById(R.id.icon);
|
||||||
|
return actionView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CircularActionMenu inflateMenuItems(FloatyService service, CircularActionMenuFloatingWindow 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OnClick(R.id.script_list)
|
||||||
|
void showScriptList() {
|
||||||
|
mWindow.collapse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.record)
|
||||||
|
void startRecord() {
|
||||||
|
mWindow.collapse();
|
||||||
|
mState = STATE_RECORDING;
|
||||||
|
mActionViewIcon.setImageResource(R.drawable.ic_ali_record);
|
||||||
|
mActionViewIcon.setBackgroundResource(R.drawable.circle_red);
|
||||||
|
mActionViewIcon.setPadding(28, 28, 28, 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopRecord() {
|
||||||
|
mWindow.collapse();
|
||||||
|
mState = STATE_NORMAL;
|
||||||
|
mActionViewIcon.setImageResource(R.drawable.autojs_logo);
|
||||||
|
mActionViewIcon.setBackground(null);
|
||||||
|
mActionViewIcon.setPadding(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.layout_bounds)
|
||||||
|
void showLayoutBounds() {
|
||||||
|
mWindow.collapse();
|
||||||
|
if (!ensureCapture()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LayoutBoundsFloatyWindow window = new LayoutBoundsFloatyWindow(
|
||||||
|
AutoJs.getInstance().getLayoutInspector().getCapture()
|
||||||
|
);
|
||||||
|
FloatyService.addWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.layout_hierarchy)
|
||||||
|
void showLayoutHierarchy() {
|
||||||
|
mWindow.collapse();
|
||||||
|
if (!ensureCapture()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LayoutHierarchyFloatyWindow window = new LayoutHierarchyFloatyWindow(
|
||||||
|
AutoJs.getInstance().getLayoutInspector().getCapture()
|
||||||
|
);
|
||||||
|
FloatyService.addWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.settings)
|
||||||
|
void settings() {
|
||||||
|
mWindow.collapse();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean ensureCapture() {
|
||||||
|
LayoutInspector inspector = AutoJs.getInstance().getLayoutInspector();
|
||||||
|
if (inspector.isDumping()) {
|
||||||
|
Toast.makeText(mContext, R.string.text_layout_inspector_is_dumping, Toast.LENGTH_SHORT).show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (AccessibilityService.getInstance() == null) {
|
||||||
|
Toast.makeText(mContext, R.string.text_no_accessibility_permission_to_capture, Toast.LENGTH_SHORT).show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (inspector.getCapture() == null) {
|
||||||
|
Toast.makeText(mContext, R.string.text_inspect_failed, Toast.LENGTH_SHORT).show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
mWindow.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.stardust.scriptdroid.ui.floating;
|
||||||
|
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import com.stardust.enhancedfloaty.FloatyService;
|
||||||
|
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/10/18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class FullScreenFloatyWindow implements FloatyWindow {
|
||||||
|
|
||||||
|
private WindowManager mWindowManager;
|
||||||
|
private WindowManager.LayoutParams mLayoutParams;
|
||||||
|
private View mView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(FloatyService floatyService, WindowManager windowManager) {
|
||||||
|
mWindowManager = windowManager;
|
||||||
|
mView = inflateView(floatyService);
|
||||||
|
mLayoutParams = new WindowManager.LayoutParams(
|
||||||
|
WindowManager.LayoutParams.MATCH_PARENT,
|
||||||
|
WindowManager.LayoutParams.MATCH_PARENT,
|
||||||
|
WindowManager.LayoutParams.TYPE_PHONE,
|
||||||
|
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
||||||
|
PixelFormat.TRANSLUCENT);
|
||||||
|
mWindowManager.addView(mView, mLayoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract View inflateView(FloatyService service);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDestroy(FloatyService floatyService) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
mWindowManager.removeView(mView);
|
||||||
|
FloatyService.removeWindow(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package com.stardust.scriptdroid.ui.floating.layoutinspector;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.afollestad.materialdialogs.Theme;
|
||||||
|
import com.stardust.enhancedfloaty.FloatyService;
|
||||||
|
import com.stardust.scriptdroid.R;
|
||||||
|
import com.stardust.scriptdroid.ui.floating.FullScreenFloatyWindow;
|
||||||
|
import com.stardust.view.accessibility.NodeInfo;
|
||||||
|
import com.stardust.widget.BubblePopupMenu;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/3/12.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LayoutBoundsFloatyWindow extends FullScreenFloatyWindow {
|
||||||
|
|
||||||
|
private LayoutBoundsView mLayoutBoundsView;
|
||||||
|
private MaterialDialog mNodeInfoDialog;
|
||||||
|
private BubblePopupMenu mBubblePopMenu;
|
||||||
|
private NodeInfoView mNodeInfoView;
|
||||||
|
private NodeInfo mSelectedNode;
|
||||||
|
private Context mContext;
|
||||||
|
private NodeInfo mRootNode;
|
||||||
|
|
||||||
|
public LayoutBoundsFloatyWindow(NodeInfo rootNode) {
|
||||||
|
mRootNode = rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflateView(FloatyService service) {
|
||||||
|
mContext = new ContextThemeWrapper(service, R.style.AppTheme);
|
||||||
|
mLayoutBoundsView = new LayoutBoundsView(mContext) {
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.dispatchKeyEvent(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setupView();
|
||||||
|
return mLayoutBoundsView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupView() {
|
||||||
|
mLayoutBoundsView.setOnNodeInfoSelectListener(new OnNodeInfoSelectListener() {
|
||||||
|
@Override
|
||||||
|
public void onNodeSelect(NodeInfo info) {
|
||||||
|
mSelectedNode = info;
|
||||||
|
ensureOperationPopMenu();
|
||||||
|
if (mBubblePopMenu.getContentView().getMeasuredWidth() <= 0)
|
||||||
|
mBubblePopMenu.preMeasure();
|
||||||
|
mBubblePopMenu.showAsDropDownAtLocation(mLayoutBoundsView, info.getBoundsInScreen().height(), info.getBoundsInScreen().centerX() - mBubblePopMenu.getContentView().getMeasuredWidth() / 2, info.getBoundsInScreen().bottom - mLayoutBoundsView.getStatusBarHeight());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mLayoutBoundsView.getBoundsPaint().setStrokeWidth(2f);
|
||||||
|
mLayoutBoundsView.setRootNode(mRootNode);
|
||||||
|
if (mSelectedNode != null)
|
||||||
|
mLayoutBoundsView.setSelectedNode(mSelectedNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void showNodeInfo() {
|
||||||
|
ensureDialog();
|
||||||
|
mNodeInfoView.setNodeInfo(mSelectedNode);
|
||||||
|
mNodeInfoDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureOperationPopMenu() {
|
||||||
|
if (mBubblePopMenu != null)
|
||||||
|
return;
|
||||||
|
mBubblePopMenu = new BubblePopupMenu(mContext, Arrays.asList(
|
||||||
|
mContext.getString(R.string.text_show_widget_infomation),
|
||||||
|
mContext.getString(R.string.text_show_layout_hierarchy)));
|
||||||
|
mBubblePopMenu.setOnItemClickListener(new BubblePopupMenu.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view, int position) {
|
||||||
|
mBubblePopMenu.dismiss();
|
||||||
|
if (position == 0) {
|
||||||
|
showNodeInfo();
|
||||||
|
} else {
|
||||||
|
showLayoutHierarchy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mBubblePopMenu.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
mBubblePopMenu.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showLayoutHierarchy() {
|
||||||
|
close();
|
||||||
|
LayoutHierarchyFloatyWindow window = new LayoutHierarchyFloatyWindow(mRootNode);
|
||||||
|
window.setSelectedNode(mSelectedNode);
|
||||||
|
FloatyService.addWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureDialog() {
|
||||||
|
if (mNodeInfoDialog == null) {
|
||||||
|
mNodeInfoView = new NodeInfoView(mContext);
|
||||||
|
mNodeInfoDialog = new MaterialDialog.Builder(mContext)
|
||||||
|
.customView(mNodeInfoView, false)
|
||||||
|
.theme(Theme.LIGHT)
|
||||||
|
.build();
|
||||||
|
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedNode(NodeInfo selectedNode) {
|
||||||
|
mSelectedNode = selectedNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
|
package com.stardust.scriptdroid.ui.floating.layoutinspector;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
package com.stardust.scriptdroid.ui.floating.layoutinspector;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.afollestad.materialdialogs.Theme;
|
||||||
|
import com.stardust.enhancedfloaty.FloatyService;
|
||||||
|
import com.stardust.scriptdroid.R;
|
||||||
|
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||||
|
import com.stardust.scriptdroid.ui.floating.FullScreenFloatyWindow;
|
||||||
|
import com.stardust.view.accessibility.NodeInfo;
|
||||||
|
import com.stardust.widget.BubblePopupMenu;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/3/12.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LayoutHierarchyFloatyWindow extends FullScreenFloatyWindow {
|
||||||
|
|
||||||
|
private static final String TAG = "FloatingHierarchyView";
|
||||||
|
private static final int COLOR_SHADOW = 0xddffffff;
|
||||||
|
|
||||||
|
private LayoutHierarchyView mLayoutHierarchyView;
|
||||||
|
private MaterialDialog mNodeInfoDialog;
|
||||||
|
private BubblePopupMenu mBubblePopMenu;
|
||||||
|
private NodeInfoView mNodeInfoView;
|
||||||
|
private NodeInfo mSelectedNodeInfo;
|
||||||
|
private Context mContext;
|
||||||
|
private NodeInfo mRootNode;
|
||||||
|
private NodeInfo mSelectedNode;
|
||||||
|
|
||||||
|
public LayoutHierarchyFloatyWindow(NodeInfo rootNode) {
|
||||||
|
mRootNode = rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflateView(FloatyService service) {
|
||||||
|
mContext = new ContextThemeWrapper(service, R.style.AppTheme);
|
||||||
|
mLayoutHierarchyView = new LayoutHierarchyView(mContext) {
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.dispatchKeyEvent(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setupView();
|
||||||
|
return mLayoutHierarchyView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupView() {
|
||||||
|
mLayoutHierarchyView.setBackgroundColor(COLOR_SHADOW);
|
||||||
|
mLayoutHierarchyView.setShowClickedNodeBounds(true);
|
||||||
|
mLayoutHierarchyView.getBoundsPaint().setStrokeWidth(3);
|
||||||
|
mLayoutHierarchyView.getBoundsPaint().setColor(0xFFD32F2F);
|
||||||
|
mLayoutHierarchyView.setOnItemLongClickListener(new LayoutHierarchyView.OnItemLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemLongClick(View view, NodeInfo nodeInfo) {
|
||||||
|
mSelectedNodeInfo = nodeInfo;
|
||||||
|
ensureOperationPopMenu();
|
||||||
|
if (mBubblePopMenu.getContentView().getMeasuredWidth() <= 0)
|
||||||
|
mBubblePopMenu.preMeasure();
|
||||||
|
mBubblePopMenu.showAsDropDown(view, view.getWidth() / 2 - mBubblePopMenu.getContentView().getMeasuredWidth() / 2, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mLayoutHierarchyView.setRootNode(mRootNode);
|
||||||
|
if (mSelectedNode != null)
|
||||||
|
mLayoutHierarchyView.setSelectedNode(mSelectedNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureOperationPopMenu() {
|
||||||
|
if (mBubblePopMenu != null)
|
||||||
|
return;
|
||||||
|
mBubblePopMenu = new BubblePopupMenu(mContext, Arrays.asList(
|
||||||
|
mContext.getString(R.string.text_show_widget_infomation),
|
||||||
|
mContext.getString(R.string.text_show_layout_bounds)));
|
||||||
|
mBubblePopMenu.setOnItemClickListener(new BubblePopupMenu.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view, int position) {
|
||||||
|
mBubblePopMenu.dismiss();
|
||||||
|
if (position == 0) {
|
||||||
|
showNodeInfo();
|
||||||
|
} else {
|
||||||
|
showLayoutBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mBubblePopMenu.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
mBubblePopMenu.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showLayoutBounds() {
|
||||||
|
close();
|
||||||
|
LayoutBoundsFloatyWindow window = new LayoutBoundsFloatyWindow(mRootNode);
|
||||||
|
window.setSelectedNode(mSelectedNode);
|
||||||
|
FloatyService.addWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void showNodeInfo() {
|
||||||
|
ensureNodeInfoDialog();
|
||||||
|
mNodeInfoView.setNodeInfo(mSelectedNodeInfo);
|
||||||
|
mNodeInfoDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureNodeInfoDialog() {
|
||||||
|
if (mNodeInfoDialog == null) {
|
||||||
|
mNodeInfoView = new NodeInfoView(mContext);
|
||||||
|
mNodeInfoDialog = new MaterialDialog.Builder(mContext)
|
||||||
|
.customView(mNodeInfoView, false)
|
||||||
|
.theme(Theme.LIGHT)
|
||||||
|
.build();
|
||||||
|
if (mNodeInfoDialog.getWindow() != null)
|
||||||
|
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setSelectedNode(NodeInfo selectedNode) {
|
||||||
|
mSelectedNode = selectedNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
|
package com.stardust.scriptdroid.ui.floating.layoutinspector;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
|
package com.stardust.scriptdroid.ui.floating.layoutinspector;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
|
package com.stardust.scriptdroid.ui.floating.layoutinspector;
|
||||||
|
|
||||||
import com.stardust.view.accessibility.NodeInfo;
|
import com.stardust.view.accessibility.NodeInfo;
|
||||||
|
|
||||||
@@ -26,8 +26,9 @@ import com.stardust.scriptdroid.BuildConfig;
|
|||||||
import com.stardust.scriptdroid.Pref;
|
import com.stardust.scriptdroid.Pref;
|
||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger;
|
import com.stardust.scriptdroid.external.floatingwindow.FloatyWindowManger;
|
||||||
import com.stardust.scriptdroid.script.StorageFileProvider;
|
import com.stardust.scriptdroid.script.StorageFileProvider;
|
||||||
|
import com.stardust.scriptdroid.ui.floating.CircularMenu;
|
||||||
import com.stardust.scriptdroid.ui.main.community.CommunityFragment_;
|
import com.stardust.scriptdroid.ui.main.community.CommunityFragment_;
|
||||||
import com.stardust.scriptdroid.ui.main.doc.OnlineDocsFragment_;
|
import com.stardust.scriptdroid.ui.main.doc.OnlineDocsFragment_;
|
||||||
import com.stardust.scriptdroid.ui.main.scripts.MyScriptListFragment_;
|
import com.stardust.scriptdroid.ui.main.scripts.MyScriptListFragment_;
|
||||||
@@ -184,7 +185,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
|||||||
|
|
||||||
@Click(R.id.exit)
|
@Click(R.id.exit)
|
||||||
public void exitCompletely() {
|
public void exitCompletely() {
|
||||||
HoverMenuManger.hideHoverMenu();
|
FloatyWindowManger.hideCircularMenu();
|
||||||
stopService(new Intent(this, FloatyService.class));
|
stopService(new Intent(this, FloatyService.class));
|
||||||
AutoJs.getInstance().getScriptEngineService().stopAll();
|
AutoJs.getInstance().getScriptEngineService().stopAll();
|
||||||
finish();
|
finish();
|
||||||
|
|||||||
@@ -14,15 +14,13 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
|||||||
import com.stardust.scriptdroid.App;
|
import com.stardust.scriptdroid.App;
|
||||||
import com.stardust.scriptdroid.Pref;
|
import com.stardust.scriptdroid.Pref;
|
||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger;
|
import com.stardust.scriptdroid.external.floatingwindow.FloatyWindowManger;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
|
||||||
import com.stardust.scriptdroid.network.NodeBB;
|
import com.stardust.scriptdroid.network.NodeBB;
|
||||||
import com.stardust.scriptdroid.network.VersionService;
|
import com.stardust.scriptdroid.network.VersionService;
|
||||||
import com.stardust.scriptdroid.network.api.UserApi;
|
import com.stardust.scriptdroid.network.api.UserApi;
|
||||||
import com.stardust.scriptdroid.network.entity.User;
|
import com.stardust.scriptdroid.network.entity.User;
|
||||||
import com.stardust.scriptdroid.network.entity.VersionInfo;
|
import com.stardust.scriptdroid.network.entity.VersionInfo;
|
||||||
import com.stardust.scriptdroid.tool.SimpleObserver;
|
import com.stardust.scriptdroid.tool.SimpleObserver;
|
||||||
import com.stardust.scriptdroid.ui.login.LoginActivity;
|
|
||||||
import com.stardust.scriptdroid.ui.login.LoginActivity_;
|
import com.stardust.scriptdroid.ui.login.LoginActivity_;
|
||||||
import com.stardust.scriptdroid.ui.settings.SettingsActivity;
|
import com.stardust.scriptdroid.ui.settings.SettingsActivity;
|
||||||
import com.stardust.scriptdroid.ui.update.UpdateInfoDialogBuilder;
|
import com.stardust.scriptdroid.ui.update.UpdateInfoDialogBuilder;
|
||||||
@@ -39,7 +37,6 @@ import org.androidannotations.annotations.EFragment;
|
|||||||
import org.androidannotations.annotations.ViewById;
|
import org.androidannotations.annotations.ViewById;
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
@@ -47,11 +44,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
|||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.functions.Consumer;
|
import io.reactivex.functions.Consumer;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.Callback;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Response;
|
|
||||||
import okhttp3.WebSocket;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,13 +158,13 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
|||||||
|
|
||||||
@Click(R.id.floating_window)
|
@Click(R.id.floating_window)
|
||||||
void showOrDismissFloatingWindow() {
|
void showOrDismissFloatingWindow() {
|
||||||
boolean isFloatingWindowShowing = HoverMenuManger.isHoverMenuShowing();
|
boolean isFloatingWindowShowing = FloatyWindowManger.isCircularMenuShowing();
|
||||||
boolean checked = mFloatingWindowItem.getSwitchCompat().isChecked();
|
boolean checked = mFloatingWindowItem.getSwitchCompat().isChecked();
|
||||||
if (checked && !isFloatingWindowShowing) {
|
if (checked && !isFloatingWindowShowing) {
|
||||||
HoverMenuManger.showHoverMenu();
|
FloatyWindowManger.showCircularMenu();
|
||||||
enableAccessibilityServiceByRootIfNeeded();
|
enableAccessibilityServiceByRootIfNeeded();
|
||||||
} else if (!checked && isFloatingWindowShowing) {
|
} else if (!checked && isFloatingWindowShowing) {
|
||||||
HoverMenuManger.hideHoverMenu();
|
FloatyWindowManger.hideCircularMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +290,6 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
|||||||
private void syncSwitchState() {
|
private void syncSwitchState() {
|
||||||
mAccessibilityServiceItem.getSwitchCompat().setChecked(
|
mAccessibilityServiceItem.getSwitchCompat().setChecked(
|
||||||
AccessibilityServiceTool.isAccessibilityServiceEnabled(getActivity()));
|
AccessibilityServiceTool.isAccessibilityServiceEnabled(getActivity()));
|
||||||
mFloatingWindowItem.getSwitchCompat().setChecked(HoverMenuManger.isHoverMenuShowing());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableAccessibilityService() {
|
private void enableAccessibilityService() {
|
||||||
@@ -337,8 +328,4 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
|||||||
mConnectionStateDisposable.dispose();
|
mConnectionStateDisposable.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onHoverMenuServiceStateChanged(HoverMenuService.ServiceStateChangedEvent event) {
|
|
||||||
mAccessibilityServiceItem.getSwitchCompat().setChecked(event.state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
app/src/main/res/drawable/autojs_logo.png
Normal file
BIN
app/src/main/res/drawable/autojs_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 305 KiB |
8
app/src/main/res/drawable/circle_blue.xml
Normal file
8
app/src/main/res/drawable/circle_blue.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:innerRadius="0dp"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thicknessRatio="2"
|
||||||
|
android:useLevel="false">
|
||||||
|
<solid android:color="#42a5f5"/>
|
||||||
|
</shape>
|
||||||
8
app/src/main/res/drawable/circle_gray.xml
Normal file
8
app/src/main/res/drawable/circle_gray.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:innerRadius="0dp"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thicknessRatio="2"
|
||||||
|
android:useLevel="false">
|
||||||
|
<solid android:color="#C0C0C0"/>
|
||||||
|
</shape>
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:innerRadius="0dp"
|
||||||
<corners android:radius="32dp"/>
|
android:shape="ring"
|
||||||
<size
|
android:thicknessRatio="2"
|
||||||
android:width="64dp"
|
android:useLevel="false">
|
||||||
android:height="64dp"/>
|
<solid android:color="@color/colorPrimary"/>
|
||||||
|
|
||||||
<solid android:color="#5cab7d"/>
|
|
||||||
|
|
||||||
</shape>
|
</shape>
|
||||||
11
app/src/main/res/drawable/circle_light_green.xml
Normal file
11
app/src/main/res/drawable/circle_light_green.xml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<corners android:radius="32dp"/>
|
||||||
|
<size
|
||||||
|
android:width="64dp"
|
||||||
|
android:height="64dp"/>
|
||||||
|
|
||||||
|
<solid android:color="#5cab7d"/>
|
||||||
|
|
||||||
|
</shape>
|
||||||
8
app/src/main/res/drawable/circle_red.xml
Normal file
8
app/src/main/res/drawable/circle_red.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:innerRadius="0dp"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thicknessRatio="2"
|
||||||
|
android:useLevel="false">
|
||||||
|
<solid android:color="#ef5350"/>
|
||||||
|
</shape>
|
||||||
8
app/src/main/res/drawable/circle_white.xml
Normal file
8
app/src/main/res/drawable/circle_white.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:innerRadius="0dp"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thicknessRatio="2"
|
||||||
|
android:useLevel="false">
|
||||||
|
<solid android:color="@color/colorPrimary"/>
|
||||||
|
</shape>
|
||||||
8
app/src/main/res/drawable/circle_yellow.xml
Normal file
8
app/src/main/res/drawable/circle_yellow.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:innerRadius="0dp"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thicknessRatio="2"
|
||||||
|
android:useLevel="false">
|
||||||
|
<solid android:color="#fdd835"/>
|
||||||
|
</shape>
|
||||||
BIN
app/src/main/res/drawable/ic_circular_menu_bounds.png
Normal file
BIN
app/src/main/res/drawable/ic_circular_menu_bounds.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/main/res/drawable/ic_circular_menu_hierarchy.png
Normal file
BIN
app/src/main/res/drawable/ic_circular_menu_hierarchy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/drawable/ic_circular_menu_settings.png
Normal file
BIN
app/src/main/res/drawable/ic_circular_menu_settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
66
app/src/main/res/layout/circular_action_menu.xml
Normal file
66
app/src/main/res/layout/circular_action_menu.xml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.stardust.floatingcircularactionmenu.CircularActionMenu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
app:cam_angle="165"
|
||||||
|
app:cam_radius="80dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/script_list"
|
||||||
|
android:layout_width="42dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/circle_green"
|
||||||
|
android:foreground="?selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_menu"
|
||||||
|
android:tint="@android:color/white"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/record"
|
||||||
|
android:layout_width="42dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/circle_red"
|
||||||
|
android:foreground="?selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_ali_record"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/layout_bounds"
|
||||||
|
android:layout_width="42dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/circle_blue"
|
||||||
|
android:foreground="?selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_circular_menu_bounds"
|
||||||
|
android:tint="@android:color/white"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/layout_hierarchy"
|
||||||
|
android:layout_width="42dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/circle_yellow"
|
||||||
|
android:foreground="?selectableItemBackgroundBorderless"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@drawable/ic_circular_menu_hierarchy"
|
||||||
|
android:tint="@android:color/white"/>
|
||||||
|
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/settings"
|
||||||
|
android:layout_width="42dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/circle_gray"
|
||||||
|
android:foreground="?selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_circular_menu_settings"
|
||||||
|
android:tint="@android:color/white"/>
|
||||||
|
|
||||||
|
|
||||||
|
</com.stardust.floatingcircularactionmenu.CircularActionMenu>
|
||||||
12
app/src/main/res/layout/circular_action_view.xml
Normal file
12
app/src/main/res/layout/circular_action_view.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:src="@drawable/autojs_logo"/>
|
||||||
|
</LinearLayout>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:background="@drawable/circle_green"
|
android:background="@drawable/circle_light_green"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:background="@drawable/circle_green"
|
android:background="@drawable/circle_light_green"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ module.exports = function(runtime, scope){
|
|||||||
}
|
}
|
||||||
|
|
||||||
http.request = function(url, options, callback){
|
http.request = function(url, options, callback){
|
||||||
var call = http.newCall(buildRequest(url, options));
|
var call = http.client().newCall(http.buildRequest(url, options));
|
||||||
if(!callback){
|
if(!callback){
|
||||||
return wrapResponse(call.execute());
|
return wrapResponse(call.execute());
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ module.exports = function(runtime, scope){
|
|||||||
}else if(options.contentType == "application/json"){
|
}else if(options.contentType == "application/json"){
|
||||||
options.body = JSON.stringify(data);
|
options.body = JSON.stringify(data);
|
||||||
}else{
|
}else{
|
||||||
//todo what?
|
options.body = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.stardust.autojs.core.templatematching;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.media.Image;
|
||||||
|
|
||||||
|
import com.stardust.autojs.runtime.api.image.Images;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/10/5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
|
||||||
|
public void test(Image image) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user