mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-21 21:01:43 +08:00
replace hover with custom circular menu
This commit is contained in:
parent
e6c0500358
commit
a478278135
@ -120,11 +120,11 @@ dependencies {
|
||||
//
|
||||
compile 'com.github.hyb1996:android-multi-level-listview:1.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.yqritc:recyclerview-flexibledivider:1.4.0'
|
||||
compile 'com.wang.avi:library:2.1.3'
|
||||
compile 'org.apache.commons:commons-lang3:3.5'
|
||||
compile 'com.github.hyb1996:FloatingCircularActionMenu:0.0.1'
|
||||
// RxJava
|
||||
compile "io.reactivex.rxjava2:rxjava:2.1.0"
|
||||
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.Intent;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
import com.stardust.enhancedfloaty.util.FloatingWindowPermissionUtil;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.ui.floating.CircularMenu;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import ezy.assist.compat.SettingsCompat;
|
||||
|
||||
@ -18,6 +21,8 @@ import ezy.assist.compat.SettingsCompat;
|
||||
|
||||
public class FloatyWindowManger {
|
||||
|
||||
private static WeakReference<CircularMenu> sCircularMenu;
|
||||
|
||||
public static void addWindow(Context context, FloatyWindow window) {
|
||||
context.startService(new Intent(context, FloatyService.class));
|
||||
if (!SettingsCompat.canDrawOverlays(context)) {
|
||||
@ -49,4 +54,23 @@ public class FloatyWindowManger {
|
||||
public static void closeWindow(FloatyWindow window) {
|
||||
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.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.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.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;
|
||||
|
||||
@ -26,8 +26,9 @@ import com.stardust.scriptdroid.BuildConfig;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
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.ui.floating.CircularMenu;
|
||||
import com.stardust.scriptdroid.ui.main.community.CommunityFragment_;
|
||||
import com.stardust.scriptdroid.ui.main.doc.OnlineDocsFragment_;
|
||||
import com.stardust.scriptdroid.ui.main.scripts.MyScriptListFragment_;
|
||||
@ -184,7 +185,7 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
|
||||
|
||||
@Click(R.id.exit)
|
||||
public void exitCompletely() {
|
||||
HoverMenuManger.hideHoverMenu();
|
||||
FloatyWindowManger.hideCircularMenu();
|
||||
stopService(new Intent(this, FloatyService.class));
|
||||
AutoJs.getInstance().getScriptEngineService().stopAll();
|
||||
finish();
|
||||
|
||||
@ -14,15 +14,13 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.Pref;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.floatingwindow.HoverMenuManger;
|
||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
||||
import com.stardust.scriptdroid.external.floatingwindow.FloatyWindowManger;
|
||||
import com.stardust.scriptdroid.network.NodeBB;
|
||||
import com.stardust.scriptdroid.network.VersionService;
|
||||
import com.stardust.scriptdroid.network.api.UserApi;
|
||||
import com.stardust.scriptdroid.network.entity.User;
|
||||
import com.stardust.scriptdroid.network.entity.VersionInfo;
|
||||
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.settings.SettingsActivity;
|
||||
import com.stardust.scriptdroid.ui.update.UpdateInfoDialogBuilder;
|
||||
@ -39,7 +37,6 @@ import org.androidannotations.annotations.EFragment;
|
||||
import org.androidannotations.annotations.ViewById;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
@ -47,11 +44,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
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)
|
||||
void showOrDismissFloatingWindow() {
|
||||
boolean isFloatingWindowShowing = HoverMenuManger.isHoverMenuShowing();
|
||||
boolean isFloatingWindowShowing = FloatyWindowManger.isCircularMenuShowing();
|
||||
boolean checked = mFloatingWindowItem.getSwitchCompat().isChecked();
|
||||
if (checked && !isFloatingWindowShowing) {
|
||||
HoverMenuManger.showHoverMenu();
|
||||
FloatyWindowManger.showCircularMenu();
|
||||
enableAccessibilityServiceByRootIfNeeded();
|
||||
} else if (!checked && isFloatingWindowShowing) {
|
||||
HoverMenuManger.hideHoverMenu();
|
||||
FloatyWindowManger.hideCircularMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +290,6 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
private void syncSwitchState() {
|
||||
mAccessibilityServiceItem.getSwitchCompat().setChecked(
|
||||
AccessibilityServiceTool.isAccessibilityServiceEnabled(getActivity()));
|
||||
mFloatingWindowItem.getSwitchCompat().setChecked(HoverMenuManger.isHoverMenuShowing());
|
||||
}
|
||||
|
||||
private void enableAccessibilityService() {
|
||||
@ -337,8 +328,4 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
|
||||
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"?>
|
||||
<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 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>
|
||||
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_gravity="center_vertical"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:background="@drawable/circle_green"
|
||||
android:background="@drawable/circle_light_green"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:background="@drawable/circle_green"
|
||||
android:background="@drawable/circle_light_green"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"
|
||||
|
||||
@ -31,7 +31,7 @@ module.exports = function(runtime, scope){
|
||||
}
|
||||
|
||||
http.request = function(url, options, callback){
|
||||
var call = http.newCall(buildRequest(url, options));
|
||||
var call = http.client().newCall(http.buildRequest(url, options));
|
||||
if(!callback){
|
||||
return wrapResponse(call.execute());
|
||||
}
|
||||
@ -74,7 +74,7 @@ module.exports = function(runtime, scope){
|
||||
}else if(options.contentType == "application/json"){
|
||||
options.body = JSON.stringify(data);
|
||||
}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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user