replace hover with custom circular menu

This commit is contained in:
hyb1996 2017-10-18 20:53:21 +08:00
parent e6c0500358
commit a478278135
41 changed files with 653 additions and 1671 deletions

View File

@ -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'

View File

@ -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;
}
}
}

View File

@ -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() {
}
}

View File

@ -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;
}
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

View 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>

View 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>

View File

@ -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>

View 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>

View 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>

View 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>

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View 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>

View 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>

View File

@ -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"

View File

@ -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"

View File

@ -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;
}
}

View File

@ -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) {
}
}