Merge pull request #203 from hyb1996/new_ui
Fix some problems and improve layout hierarchy and bounds view
This commit is contained in:
15
.idea/misc.xml
generated
15
.idea/misc.xml
generated
@@ -2,15 +2,16 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="EntryPointsManager">
|
<component name="EntryPointsManager">
|
||||||
<entry_points version="2.0" />
|
<entry_points version="2.0" />
|
||||||
<list size="8">
|
<list size="9">
|
||||||
<item index="0" class="java.lang.String" itemvalue="android.support.annotation.Keep" />
|
<item index="0" class="java.lang.String" itemvalue="android.support.annotation.Keep" />
|
||||||
<item index="1" class="java.lang.String" itemvalue="android.webkit.JavascriptInterface" />
|
<item index="1" class="java.lang.String" itemvalue="android.webkit.JavascriptInterface" />
|
||||||
<item index="2" class="java.lang.String" itemvalue="com.stardust.autojs.runtime.ScriptClass" />
|
<item index="2" class="java.lang.String" itemvalue="butterknife.OnClick" />
|
||||||
<item index="3" class="java.lang.String" itemvalue="com.stardust.autojs.runtime.ScriptInterface" />
|
<item index="3" class="java.lang.String" itemvalue="com.stardust.autojs.runtime.ScriptClass" />
|
||||||
<item index="4" class="java.lang.String" itemvalue="com.stardust.view.ViewBind.Click" />
|
<item index="4" class="java.lang.String" itemvalue="com.stardust.autojs.runtime.ScriptInterface" />
|
||||||
<item index="5" class="java.lang.String" itemvalue="com.stardust.view.ViewBinding.Check" />
|
<item index="5" class="java.lang.String" itemvalue="com.stardust.view.ViewBind.Click" />
|
||||||
<item index="6" class="java.lang.String" itemvalue="com.stardust.view.ViewBinding.Click" />
|
<item index="6" class="java.lang.String" itemvalue="com.stardust.view.ViewBinding.Check" />
|
||||||
<item index="7" class="java.lang.String" itemvalue="org.greenrobot.eventbus.Subscribe" />
|
<item index="7" class="java.lang.String" itemvalue="com.stardust.view.ViewBinding.Click" />
|
||||||
|
<item index="8" class="java.lang.String" itemvalue="org.greenrobot.eventbus.Subscribe" />
|
||||||
</list>
|
</list>
|
||||||
</component>
|
</component>
|
||||||
<component name="NullableNotNullManager">
|
<component name="NullableNotNullManager">
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "com.stardust.scriptdroid"
|
applicationId "com.stardust.scriptdroid"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 137
|
versionCode 140
|
||||||
versionName "2.0.12 Beta"
|
versionName "2.0.13 Alpha3"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
ndk {
|
ndk {
|
||||||
@@ -78,22 +78,40 @@ dependencies {
|
|||||||
exclude group: 'com.android.support', module: 'support-annotations'
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
})
|
})
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
|
// LeakCanary (a memory leak tracer)
|
||||||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
|
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
|
||||||
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
||||||
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
||||||
|
// Storio (Sqlite api library)
|
||||||
annotationProcessor 'com.pushtorefresh.storio:sqlite-annotations-processor:1.12.3'
|
annotationProcessor 'com.pushtorefresh.storio:sqlite-annotations-processor:1.12.3'
|
||||||
compile 'com.pushtorefresh.storio:sqlite-annotations:1.12.3'
|
compile 'com.pushtorefresh.storio:sqlite-annotations:1.12.3'
|
||||||
|
// Android Annotations
|
||||||
|
annotationProcessor "org.androidannotations:androidannotations:$AAVersion"
|
||||||
|
compile "org.androidannotations:androidannotations-api:$AAVersion"
|
||||||
|
// ButterKnife
|
||||||
|
compile 'com.jakewharton:butterknife:8.6.0'
|
||||||
|
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
|
||||||
|
// Android supports
|
||||||
compile 'com.android.support:appcompat-v7:25.3.0'
|
compile 'com.android.support:appcompat-v7:25.3.0'
|
||||||
compile 'com.android.support:design:25.1.0'
|
compile 'com.android.support:design:25.3.0'
|
||||||
|
compile 'com.android.support:multidex:1.0.1'
|
||||||
|
// Personal libraries
|
||||||
compile 'com.github.hyb1996:MutableTheme:0.2.2'
|
compile 'com.github.hyb1996:MutableTheme:0.2.2'
|
||||||
|
compile 'com.github.hyb1996:EnhancedFloaty:0.17'
|
||||||
|
// Material Dialogs
|
||||||
compile 'com.afollestad.material-dialogs:core:0.9.2.3'
|
compile 'com.afollestad.material-dialogs:core:0.9.2.3'
|
||||||
|
// Gson
|
||||||
compile 'com.google.code.gson:gson:2.8.0'
|
compile 'com.google.code.gson:gson:2.8.0'
|
||||||
|
// Common Markdown
|
||||||
compile 'com.github.atlassian:commonmark-java:commonmark-parent-0.9.0'
|
compile 'com.github.atlassian:commonmark-java:commonmark-parent-0.9.0'
|
||||||
|
// AlipayZeroSdk
|
||||||
compile 'moe.feng:AlipayZeroSdk:1.1'
|
compile 'moe.feng:AlipayZeroSdk:1.1'
|
||||||
|
// Console
|
||||||
compile 'com.jraska:console:0.4.3'
|
compile 'com.jraska:console:0.4.3'
|
||||||
|
// Android issue reporter (a github issue reporter)
|
||||||
compile 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
|
compile 'com.heinrichreimersoftware:android-issue-reporter:1.3.1'
|
||||||
compile 'de.codecrafters.tableview:tableview:2.5.0'
|
//
|
||||||
compile group: "pl.openrnd.android", name: "multi-level-listview", version: "1.0.1"
|
compile 'com.github.hyb1996:android-multi-level-listview:1.1'
|
||||||
compile 'de.psdev.licensesdialog:licensesdialog:1.8.1'
|
compile 'de.psdev.licensesdialog:licensesdialog:1.8.1'
|
||||||
compile 'io.mattcarroll.hover:hover:0.9.7'
|
compile 'io.mattcarroll.hover:hover:0.9.7'
|
||||||
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
|
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
|
||||||
@@ -101,10 +119,8 @@ dependencies {
|
|||||||
// Tasker Plugin
|
// Tasker Plugin
|
||||||
compile group: 'com.twofortyfouram', name: 'android-plugin-client-sdk-for-locale', version: '[4.0.2, 5.0['
|
compile group: 'com.twofortyfouram', name: 'android-plugin-client-sdk-for-locale', version: '[4.0.2, 5.0['
|
||||||
compile 'com.android.volley:volley:1.0.0'
|
compile 'com.android.volley:volley:1.0.0'
|
||||||
compile 'com.github.hyb1996:EnhancedFloaty:0.17'
|
|
||||||
compile 'com.flurry.android:analytics:7.0.0@aar'
|
compile 'com.flurry.android:analytics:7.0.0@aar'
|
||||||
compile 'com.pushtorefresh.storio:sqlite:1.12.3'
|
compile 'com.pushtorefresh.storio:sqlite:1.12.3'
|
||||||
compile 'com.android.support:multidex:1.0.1'
|
|
||||||
// Terminal emulator
|
// Terminal emulator
|
||||||
compile(name: 'libtermexec-release', ext: 'aar')
|
compile(name: 'libtermexec-release', ext: 'aar')
|
||||||
compile(name: 'emulatorview-release', ext: 'aar')
|
compile(name: 'emulatorview-release', ext: 'aar')
|
||||||
@@ -113,6 +129,7 @@ dependencies {
|
|||||||
compile 'com.afollestad.material-dialogs:commons:0.9.2.3'
|
compile 'com.afollestad.material-dialogs:commons:0.9.2.3'
|
||||||
compile 'com.makeramen:roundedimageview:2.2.1'
|
compile 'com.makeramen:roundedimageview:2.2.1'
|
||||||
compile 'com.rengwuxian.materialedittext:library:2.0.3'
|
compile 'com.rengwuxian.materialedittext:library:2.0.3'
|
||||||
|
compile 'org.msgpack:msgpack-core:0.8.11'
|
||||||
compile(name: '920-common-release', ext: 'aar')
|
compile(name: '920-common-release', ext: 'aar')
|
||||||
compile(name: '920-styles-release', ext: 'aar')
|
compile(name: '920-styles-release', ext: 'aar')
|
||||||
compile(name: '920-file_explorer-release', ext: 'aar')
|
compile(name: '920-file_explorer-release', ext: 'aar')
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package com.stardust.app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.stardust.scriptdroid.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/6/26.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class OperationDialogBuilder extends MaterialDialog.Builder {
|
||||||
|
|
||||||
|
private RecyclerView mOperations;
|
||||||
|
private ArrayList<Integer> mIds = new ArrayList<>();
|
||||||
|
private ArrayList<Integer> mIcons = new ArrayList<>();
|
||||||
|
private ArrayList<Integer> mTexts = new ArrayList<>();
|
||||||
|
private Object mOnItemClickTarget;
|
||||||
|
|
||||||
|
public OperationDialogBuilder(@NonNull Context context) {
|
||||||
|
super(context);
|
||||||
|
mOperations = new RecyclerView(context);
|
||||||
|
mOperations.setLayoutManager(new LinearLayoutManager(context));
|
||||||
|
mOperations.setAdapter(new RecyclerView.Adapter<ViewHolder>() {
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.operation_dialog_item, parent, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
holder.itemView.setId(mIds.get(position));
|
||||||
|
holder.text.setText(mTexts.get(position));
|
||||||
|
holder.icon.setImageResource(mIcons.get(position));
|
||||||
|
if (mOnItemClickTarget != null) {
|
||||||
|
//// TODO: 2017/6/26 效率
|
||||||
|
ButterKnife.bind(mOnItemClickTarget, holder.itemView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mIds.size();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
customView(mOperations, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationDialogBuilder item(int id, int iconRes, int textRes) {
|
||||||
|
mIds.add(id);
|
||||||
|
mIcons.add(iconRes);
|
||||||
|
mTexts.add(textRes);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationDialogBuilder bindItemClick(Object target) {
|
||||||
|
mOnItemClickTarget = target;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
@BindView(R.id.icon)
|
||||||
|
ImageView icon;
|
||||||
|
@BindView(R.id.text)
|
||||||
|
TextView text;
|
||||||
|
|
||||||
|
public ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ButterKnife.bind(this, itemView);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,11 +18,13 @@ import com.stardust.hover.WindowHoverMenu;
|
|||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.FloatingWindowManger;
|
import com.stardust.scriptdroid.external.floatingwindow.FloatingWindowManger;
|
||||||
|
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView;
|
||||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||||
import com.stardust.theme.ThemeColorManagerCompat;
|
import com.stardust.theme.ThemeColorManagerCompat;
|
||||||
import com.stardust.util.MessageEvent;
|
import com.stardust.util.MessageEvent;
|
||||||
|
import com.stardust.util.MessageIntent;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
@@ -45,13 +47,18 @@ public class HoverMenuService extends Service {
|
|||||||
public boolean state;
|
public boolean state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String MESSAGE_SHOW_AND_EXPAND_MENU = "MESSAGE_SHOW_AND_EXPAND_MENU";
|
public static final String ACTION_SHOW_AND_EXPAND_MENU = "ACTION_SHOW_AND_EXPAND_MENU";
|
||||||
public static final String MESSAGE_SHOW_LAYOUT_HIERARCHY = "MESSAGE_SHOW_LAYOUT_HIERARCHY";
|
public static final String ACTION_SHOW_LAYOUT_HIERARCHY = "ACTION_SHOW_LAYOUT_HIERARCHY";
|
||||||
public static final String MESSAGE_SHOW_LAYOUT_BOUNDS = "MESSAGE_SHOW_LAYOUT_BOUNDS";
|
public static final String ACTION_SHOW_LAYOUT_BOUNDS = "ACTION_SHOW_LAYOUT_BOUNDS";
|
||||||
public static final String MESSAGE_COLLAPSE_MENU = "MESSAGE_COLLAPSE_MENU";
|
public static final String ACTION_COLLAPSE_MENU = "ACTION_COLLAPSE_MENU";
|
||||||
public static final String MESSAGE_MENU_COLLAPSING = "MESSAGE_MENU_COLLAPSING";
|
public static final String ACTION_MENU_COLLAPSING = "ACTION_MENU_COLLAPSING";
|
||||||
public static final String MESSAGE_MENU_EXPANDING = "MESSAGE_MENU_EXPANDING";
|
public static final String ACTION_MENU_EXPANDING = "ACTION_MENU_EXPANDING";
|
||||||
public static final String MESSAGE_MENU_EXIT = "MESSAGE_MENU_EXIT";
|
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 boolean sIsRunning;
|
||||||
private static EventBus eventBus = new EventBus();
|
private static EventBus eventBus = new EventBus();
|
||||||
@@ -70,8 +77,12 @@ public class HoverMenuService extends Service {
|
|||||||
eventBus.post(new ServiceStateChangedEvent(sIsRunning));
|
eventBus.post(new ServiceStateChangedEvent(sIsRunning));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void postEvent(MessageEvent event) {
|
public static void postIntent(Intent intent) {
|
||||||
eventBus.post(event);
|
eventBus.post(new MessageIntent(intent));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void postMessageIntent(MessageIntent intent) {
|
||||||
|
eventBus.post(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -88,6 +99,7 @@ public class HoverMenuService extends Service {
|
|||||||
|
|
||||||
private WindowViewController mWindowViewController;
|
private WindowViewController mWindowViewController;
|
||||||
|
|
||||||
|
private ContextThemeWrapper mThemeWrapper;
|
||||||
private FloatingLayoutHierarchyView mFloatingLayoutHierarchyView;
|
private FloatingLayoutHierarchyView mFloatingLayoutHierarchyView;
|
||||||
private FloatingLayoutBoundsView mFloatingLayoutBoundsView;
|
private FloatingLayoutBoundsView mFloatingLayoutBoundsView;
|
||||||
|
|
||||||
@@ -95,7 +107,7 @@ public class HoverMenuService extends Service {
|
|||||||
private HoverMenu.OnExitListener mWindowHoverMenuMenuExitListener = new HoverMenu.OnExitListener() {
|
private HoverMenu.OnExitListener mWindowHoverMenuMenuExitListener = new HoverMenu.OnExitListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onExitByUserRequest() {
|
public void onExitByUserRequest() {
|
||||||
eventBus.post(new MessageEvent(MESSAGE_MENU_EXIT));
|
eventBus.post(new MessageEvent(ACTION_MENU_EXIT));
|
||||||
savePreferredLocation();
|
savePreferredLocation();
|
||||||
mWindowHoverMenu.hide();
|
mWindowHoverMenu.hide();
|
||||||
stopSelf();
|
stopSelf();
|
||||||
@@ -121,15 +133,16 @@ public class HoverMenuService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initViews() {
|
private void initViews() {
|
||||||
mFloatingLayoutHierarchyView = new FloatingLayoutHierarchyView(this);
|
mThemeWrapper = new ContextThemeWrapper(this, R.style.AppTheme);
|
||||||
mFloatingLayoutBoundsView = new FloatingLayoutBoundsView(this);
|
mFloatingLayoutHierarchyView = new FloatingLayoutHierarchyView(mThemeWrapper);
|
||||||
|
mFloatingLayoutBoundsView = new FloatingLayoutBoundsView(mThemeWrapper);
|
||||||
initWindowMenu();
|
initWindowMenu();
|
||||||
mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutHierarchyView);
|
mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutHierarchyView);
|
||||||
mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutBoundsView);
|
mWindowViewController.addView(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true, mFloatingLayoutBoundsView);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initWindowMenu() {
|
private void initWindowMenu() {
|
||||||
mWindowHoverMenu = (WindowHoverMenu) new HoverMenuBuilder(new ContextThemeWrapper(this, R.style.AppTheme))
|
mWindowHoverMenu = (WindowHoverMenu) new HoverMenuBuilder(mThemeWrapper)
|
||||||
.displayWithinWindow()
|
.displayWithinWindow()
|
||||||
.useAdapter(new HoverMenuAdapter(this))
|
.useAdapter(new HoverMenuAdapter(this))
|
||||||
.restoreVisualState(loadPreferredLocation())
|
.restoreVisualState(loadPreferredLocation())
|
||||||
@@ -140,14 +153,14 @@ public class HoverMenuService extends Service {
|
|||||||
mWindowHoverMenu.setHoverMenuTransitionListener(new SimpleHoverMenuTransitionListener() {
|
mWindowHoverMenu.setHoverMenuTransitionListener(new SimpleHoverMenuTransitionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onExpanding() {
|
public void onExpanding() {
|
||||||
eventBus.post(new MessageEvent(MESSAGE_MENU_EXPANDING));
|
eventBus.post(new MessageEvent(ACTION_MENU_EXPANDING));
|
||||||
captureCurrentWindow();
|
captureCurrentWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCollapsing() {
|
public void onCollapsing() {
|
||||||
AutoJs.getInstance().getLayoutInspector().clearCapture();
|
AutoJs.getInstance().getLayoutInspector().clearCapture();
|
||||||
eventBus.post(new MessageEvent(MESSAGE_MENU_COLLAPSING));
|
eventBus.post(new MessageEvent(ACTION_MENU_COLLAPSING));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -195,20 +208,30 @@ public class HoverMenuService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMessageEvent(MessageEvent event) {
|
public void handleMessageIntent(MessageIntent intent) {
|
||||||
switch (event.message) {
|
switch (intent.getAction()) {
|
||||||
case MESSAGE_SHOW_AND_EXPAND_MENU:
|
case ACTION_SHOW_AND_EXPAND_MENU:
|
||||||
showAndExpandMenu();
|
showAndExpandMenu();
|
||||||
break;
|
break;
|
||||||
case MESSAGE_SHOW_LAYOUT_HIERARCHY:
|
case ACTION_SHOW_LAYOUT_HIERARCHY:
|
||||||
showLayoutHierarchy();
|
showLayoutHierarchy();
|
||||||
break;
|
break;
|
||||||
case MESSAGE_SHOW_LAYOUT_BOUNDS:
|
case ACTION_SHOW_LAYOUT_BOUNDS:
|
||||||
showLayoutBounds();
|
showLayoutBounds();
|
||||||
break;
|
break;
|
||||||
case MESSAGE_COLLAPSE_MENU:
|
case ACTION_COLLAPSE_MENU:
|
||||||
mWindowHoverMenu.collapseMenu();
|
mWindowHoverMenu.collapseMenu();
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
|||||||
if (!ensureCapture()) {
|
if (!ensureCapture()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_SHOW_LAYOUT_HIERARCHY));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_LAYOUT_HIERARCHY));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean ensureCapture() {
|
private boolean ensureCapture() {
|
||||||
@@ -72,7 +72,7 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
|||||||
if (!ensureCapture()) {
|
if (!ensureCapture()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_SHOW_LAYOUT_BOUNDS));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_LAYOUT_BOUNDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBinding.Click(R.id.stop_all_running_scripts)
|
@ViewBinding.Click(R.id.stop_all_running_scripts)
|
||||||
@@ -84,7 +84,7 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
|||||||
private void openMainActivity() {
|
private void openMainActivity() {
|
||||||
App.getApp().startActivity(new Intent(App.getApp(), MainActivity.class)
|
App.getApp().startActivity(new Intent(App.getApp(), MainActivity.class)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK));
|
.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -125,9 +125,9 @@ public class MainMenuNavigatorContent implements NavigatorContent {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMessageEvent(MessageEvent event) {
|
public void onMessageEvent(MessageEvent event) {
|
||||||
if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXPANDING)) {
|
if (event.message.equals(HoverMenuService.ACTION_MENU_EXPANDING)) {
|
||||||
syncCurrentInfo();
|
syncCurrentInfo();
|
||||||
} else if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXIT)) {
|
} else if (event.message.equals(HoverMenuService.ACTION_MENU_EXIT)) {
|
||||||
HoverMenuService.getEventBus().unregister(this);
|
HoverMenuService.getEventBus().unregister(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.content;
|
package com.stardust.scriptdroid.external.floatingwindow.menu.content;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.widget.SwitchCompat;
|
import android.support.v7.widget.SwitchCompat;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -124,7 +125,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
private void resumeRecord() {
|
private void resumeRecord() {
|
||||||
mRecorder.resume();
|
mRecorder.resume();
|
||||||
setState(Recorder.STATE_RECORDING);
|
setState(Recorder.STATE_RECORDING);
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pauseRecord() {
|
private void pauseRecord() {
|
||||||
@@ -137,7 +138,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
mRecorder.setOnStateChangedListener(this);
|
mRecorder.setOnStateChangedListener(this);
|
||||||
mRecorder.start();
|
mRecorder.start();
|
||||||
setState(Recorder.STATE_RECORDING);
|
setState(Recorder.STATE_RECORDING);
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setState(int state) {
|
private void setState(int state) {
|
||||||
@@ -153,7 +154,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
private void stopRecord() {
|
private void stopRecord() {
|
||||||
mRecorder.stop();
|
mRecorder.stop();
|
||||||
setState(Recorder.STATE_STOPPED);
|
setState(Recorder.STATE_STOPPED);
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -163,10 +164,10 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMessageEvent(MessageEvent event) {
|
public void onMessageEvent(MessageEvent event) {
|
||||||
if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXPANDING)) {
|
if (event.message.equals(HoverMenuService.ACTION_MENU_EXPANDING)) {
|
||||||
if (mRecorder != null && mRecorder.getState() == Recorder.STATE_RECORDING)
|
if (mRecorder != null && mRecorder.getState() == Recorder.STATE_RECORDING)
|
||||||
pauseRecord();
|
pauseRecord();
|
||||||
} else if (event.message.equals(HoverMenuService.MESSAGE_MENU_EXIT)) {
|
} else if (event.message.equals(HoverMenuService.ACTION_MENU_EXIT)) {
|
||||||
onMenuExit();
|
onMenuExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.content;
|
package com.stardust.scriptdroid.external.floatingwindow.menu.content;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -15,7 +16,6 @@ import com.stardust.scriptdroid.script.StorageScriptProvider;
|
|||||||
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
||||||
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
|
import com.stardust.scriptdroid.ui.main.script_list.ScriptAndFolderListRecyclerView;
|
||||||
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
|
import com.stardust.scriptdroid.ui.main.script_list.ScriptListWithProgressBarView;
|
||||||
import com.stardust.util.MessageEvent;
|
|
||||||
import com.stardust.widget.ViewHolderSupplier;
|
import com.stardust.widget.ViewHolderSupplier;
|
||||||
|
|
||||||
import io.mattcarroll.hover.Navigator;
|
import io.mattcarroll.hover.Navigator;
|
||||||
@@ -53,7 +53,7 @@ public class ScriptListNavigatorContent implements NavigatorContent {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(ScriptFile file, int position) {
|
public void onClick(ScriptFile file, int position) {
|
||||||
Scripts.run(file);
|
Scripts.run(file);
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -94,7 +94,7 @@ public class ScriptListNavigatorContent implements NavigatorContent {
|
|||||||
int position = mFloatingScriptFileListView.getChildViewHolder((View) v.getParent()).getAdapterPosition();
|
int position = mFloatingScriptFileListView.getChildViewHolder((View) v.getParent()).getAdapterPosition();
|
||||||
ScriptFile file = mFloatingScriptFileListView.getAdapter().getScriptFileAt(position);
|
ScriptFile file = mFloatingScriptFileListView.getAdapter().getScriptFileAt(position);
|
||||||
EditActivity.editFile(v.getContext(), file);
|
EditActivity.editFile(v.getContext(), file);
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_COLLAPSE_MENU));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,8 @@ import java.util.concurrent.Executor;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/3/10.
|
* Created by Stardust on 2017/3/10.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: 2017/5/8
|
|
||||||
|
|
||||||
public class LayoutInspector {
|
public class LayoutInspector {
|
||||||
|
|
||||||
private volatile NodeInfo mCapture;
|
private volatile NodeInfo mCapture;
|
||||||
@@ -22,7 +19,7 @@ public class LayoutInspector {
|
|||||||
private Executor mExecutor = UnderuseExecutors.getExecutor();
|
private Executor mExecutor = UnderuseExecutors.getExecutor();
|
||||||
|
|
||||||
public void captureCurrentWindow() {
|
public void captureCurrentWindow() {
|
||||||
AccessibilityService service = AccessibilityWatchDogService.getInstance();
|
AccessibilityWatchDogService service = AccessibilityWatchDogService.getInstance();
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
mCapture = null;
|
mCapture = null;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -18,19 +18,31 @@ import java.util.List;
|
|||||||
public class NodeInfo {
|
public class NodeInfo {
|
||||||
|
|
||||||
private List<NodeInfo> children = new ArrayList<>();
|
private List<NodeInfo> children = new ArrayList<>();
|
||||||
|
private Rect mBoundsInScreen;
|
||||||
|
|
||||||
public String id;
|
public String id;
|
||||||
public CharSequence contentDesc, className, packageName, text;
|
public CharSequence desc;
|
||||||
|
public CharSequence className;
|
||||||
|
public CharSequence packageName;
|
||||||
|
public CharSequence text;
|
||||||
public int drawingOrder;
|
public int drawingOrder;
|
||||||
public boolean accessibilityFocused, checked, clickable, contextClickable, dismissable, editable, enabled,
|
public boolean accessibilityFocused;
|
||||||
focusable, longClickable, selected, scrollable, visibleToUser;
|
public boolean checked;
|
||||||
|
public boolean clickable;
|
||||||
|
public boolean contextClickable;
|
||||||
|
public boolean dismissable;
|
||||||
|
public boolean editable;
|
||||||
|
public boolean enabled;
|
||||||
|
public boolean focusable;
|
||||||
|
public boolean longClickable;
|
||||||
|
public boolean selected;
|
||||||
|
public boolean scrollable;
|
||||||
public String bounds;
|
public String bounds;
|
||||||
|
|
||||||
private Rect mBoundsInScreen;
|
|
||||||
|
|
||||||
public NodeInfo(AccessibilityNodeInfoCompat node) {
|
public NodeInfo(AccessibilityNodeInfoCompat node) {
|
||||||
id = simplifyId(node.getViewIdResourceName());
|
id = simplifyId(node.getViewIdResourceName());
|
||||||
contentDesc = node.getContentDescription();
|
desc = node.getContentDescription();
|
||||||
className = node.getClassName();
|
className = node.getClassName();
|
||||||
packageName = node.getPackageName();
|
packageName = node.getPackageName();
|
||||||
text = node.getText();
|
text = node.getText();
|
||||||
@@ -48,8 +60,6 @@ public class NodeInfo {
|
|||||||
longClickable = node.isLongClickable();
|
longClickable = node.isLongClickable();
|
||||||
selected = node.isSelected();
|
selected = node.isSelected();
|
||||||
scrollable = node.isScrollable();
|
scrollable = node.isScrollable();
|
||||||
visibleToUser = node.isVisibleToUser();
|
|
||||||
|
|
||||||
mBoundsInScreen = new Rect();
|
mBoundsInScreen = new Rect();
|
||||||
node.getBoundsInScreen(mBoundsInScreen);
|
node.getBoundsInScreen(mBoundsInScreen);
|
||||||
bounds = boundsToString(mBoundsInScreen);
|
bounds = boundsToString(mBoundsInScreen);
|
||||||
@@ -92,6 +102,7 @@ public class NodeInfo {
|
|||||||
return capture(r);
|
return capture(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public List<NodeInfo> getChildren() {
|
public List<NodeInfo> getChildren() {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.Region;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.RequiresApi;
|
import android.support.annotation.RequiresApi;
|
||||||
@@ -16,6 +17,8 @@ import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.No
|
|||||||
import com.stardust.util.ViewUtil;
|
import com.stardust.util.ViewUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,12 +27,16 @@ import java.util.List;
|
|||||||
|
|
||||||
public class LayoutBoundsView extends View {
|
public class LayoutBoundsView extends View {
|
||||||
|
|
||||||
|
private static final int COLOR_SHADOW = 0x6a000000;
|
||||||
private NodeInfo mRootNode;
|
private NodeInfo mRootNode;
|
||||||
|
private NodeInfo mTouchedNode;
|
||||||
|
private Paint mBoundsPaint;
|
||||||
private Paint mPaint;
|
private Paint mFillingPaint;
|
||||||
private int mStatusBarHeight;
|
private int mStatusBarHeight;
|
||||||
private OnNodeInfoSelectListener mOnNodeInfoSelectListener;
|
private OnNodeInfoSelectListener mOnNodeInfoSelectListener;
|
||||||
|
private int mTouchedNodeBoundsColor = Color.RED;
|
||||||
|
private int mNormalNodeBoundsColor = Color.GREEN;
|
||||||
|
private Rect mTouchedNodeBounds;
|
||||||
|
|
||||||
public LayoutBoundsView(Context context) {
|
public LayoutBoundsView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -59,32 +66,68 @@ public class LayoutBoundsView extends View {
|
|||||||
|
|
||||||
public void setRootNode(NodeInfo rootNode) {
|
public void setRootNode(NodeInfo rootNode) {
|
||||||
mRootNode = rootNode;
|
mRootNode = rootNode;
|
||||||
|
mTouchedNode = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
mPaint = new Paint();
|
mBoundsPaint = new Paint();
|
||||||
mPaint.setColor(Color.GREEN);
|
mBoundsPaint.setStyle(Paint.Style.STROKE);
|
||||||
mPaint.setStyle(Paint.Style.STROKE);
|
mFillingPaint = new Paint();
|
||||||
|
mFillingPaint.setStyle(Paint.Style.FILL);
|
||||||
|
mFillingPaint.setColor(COLOR_SHADOW);
|
||||||
mStatusBarHeight = ViewUtil.getStatusBarHeight(getContext());
|
mStatusBarHeight = ViewUtil.getStatusBarHeight(getContext());
|
||||||
setWillNotDraw(false);
|
setWillNotDraw(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
|
if (mTouchedNode != null) {
|
||||||
|
canvas.save();
|
||||||
|
if (mTouchedNodeBounds == null) {
|
||||||
|
mTouchedNodeBounds = new Rect(mTouchedNode.getBoundsInScreen());
|
||||||
|
mTouchedNodeBounds.offset(0, -mStatusBarHeight);
|
||||||
|
}
|
||||||
|
canvas.clipRect(mTouchedNodeBounds, Region.Op.DIFFERENCE);
|
||||||
|
}
|
||||||
|
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mFillingPaint);
|
||||||
|
if (mTouchedNode != null) {
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
mBoundsPaint.setColor(mNormalNodeBoundsColor);
|
||||||
draw(canvas, mRootNode);
|
draw(canvas, mRootNode);
|
||||||
|
if (mTouchedNode != null) {
|
||||||
|
mBoundsPaint.setColor(mTouchedNodeBoundsColor);
|
||||||
|
drawRect(canvas, mTouchedNode.getBoundsInScreen(), mStatusBarHeight, mBoundsPaint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Paint getPaint() {
|
public Paint getBoundsPaint() {
|
||||||
return mPaint;
|
return mBoundsPaint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Paint getFillingPaint() {
|
||||||
|
return mFillingPaint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatusBarHeight() {
|
||||||
|
return mStatusBarHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTouchedNodeBoundsColor(int touchedNodeBoundsColor) {
|
||||||
|
mTouchedNodeBoundsColor = touchedNodeBoundsColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNormalNodeBoundsColor(int normalNodeBoundsColor) {
|
||||||
|
mNormalNodeBoundsColor = normalNodeBoundsColor;
|
||||||
|
}
|
||||||
|
|
||||||
private void draw(Canvas canvas, NodeInfo node) {
|
private void draw(Canvas canvas, NodeInfo node) {
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return;
|
return;
|
||||||
drawRect(canvas, node.getBoundsInScreen(), mStatusBarHeight, mPaint);
|
drawRect(canvas, node.getBoundsInScreen(), mStatusBarHeight, mBoundsPaint);
|
||||||
for (NodeInfo child : node.getChildren()) {
|
for (NodeInfo child : node.getChildren()) {
|
||||||
draw(canvas, child);
|
draw(canvas, child);
|
||||||
}
|
}
|
||||||
@@ -98,25 +141,39 @@ public class LayoutBoundsView extends View {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN && mRootNode != null) {
|
if (mRootNode != null) {
|
||||||
ArrayList<NodeInfo> list = new ArrayList<>();
|
setSelectedNode(findNodeAt(mRootNode, (int) event.getRawX(), (int) event.getRawY()));
|
||||||
findNodeAt(mRootNode, (int) event.getRawX(), (int) event.getRawY(), list);
|
}
|
||||||
showNodeInfoList(list);
|
if (event.getAction() == MotionEvent.ACTION_UP && mTouchedNode != null) {
|
||||||
|
onNodeInfoClick(mTouchedNode);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return super.onTouchEvent(event);
|
return super.onTouchEvent(event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showNodeInfoList(ArrayList<NodeInfo> list) {
|
|
||||||
onNodeInfoClick(list.get(list.size() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onNodeInfoClick(NodeInfo nodeInfo) {
|
private void onNodeInfoClick(NodeInfo nodeInfo) {
|
||||||
if (mOnNodeInfoSelectListener != null) {
|
if (mOnNodeInfoSelectListener != null) {
|
||||||
mOnNodeInfoSelectListener.onNodeSelect(nodeInfo);
|
mOnNodeInfoSelectListener.onNodeSelect(nodeInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NodeInfo findNodeAt(NodeInfo node, int x, int y) {
|
||||||
|
ArrayList<NodeInfo> list = new ArrayList<>();
|
||||||
|
findNodeAt(node, x, y, list);
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Collections.min(list, new Comparator<NodeInfo>() {
|
||||||
|
@Override
|
||||||
|
public int compare(NodeInfo o1, NodeInfo o2) {
|
||||||
|
return o1.getBoundsInScreen().width() * o1.getBoundsInScreen().height() -
|
||||||
|
o2.getBoundsInScreen().width() * o2.getBoundsInScreen().height();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void findNodeAt(NodeInfo node, int x, int y, List<NodeInfo> list) {
|
private void findNodeAt(NodeInfo node, int x, int y, List<NodeInfo> list) {
|
||||||
for (NodeInfo child : node.getChildren()) {
|
for (NodeInfo child : node.getChildren()) {
|
||||||
if (child != null && child.getBoundsInScreen().contains(x, y)) {
|
if (child != null && child.getBoundsInScreen().contains(x, y)) {
|
||||||
@@ -126,4 +183,9 @@ public class LayoutBoundsView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSelectedNode(NodeInfo selectedNode) {
|
||||||
|
mTouchedNode = selectedNode;
|
||||||
|
mTouchedNodeBounds = null;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,11 @@ import com.stardust.util.ViewUtil;
|
|||||||
import com.stardust.widget.LevelBeamView;
|
import com.stardust.widget.LevelBeamView;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
import pl.openrnd.multilevellistview.ItemInfo;
|
import pl.openrnd.multilevellistview.ItemInfo;
|
||||||
import pl.openrnd.multilevellistview.MultiLevelListAdapter;
|
import pl.openrnd.multilevellistview.MultiLevelListAdapter;
|
||||||
@@ -34,13 +37,17 @@ import pl.openrnd.multilevellistview.OnItemClickListener;
|
|||||||
|
|
||||||
public class LayoutHierarchyView extends MultiLevelListView {
|
public class LayoutHierarchyView extends MultiLevelListView {
|
||||||
|
|
||||||
|
public interface OnItemLongClickListener {
|
||||||
|
void onItemLongClick(View view, NodeInfo nodeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
private Adapter mAdapter;
|
private Adapter mAdapter;
|
||||||
private OnNodeInfoSelectListener mOnNodeInfoSelectListener;
|
private OnItemLongClickListener mOnItemLongClickListener;
|
||||||
private AdapterView.OnItemLongClickListener mOnItemLongClickListenerProxy = new AdapterView.OnItemLongClickListener() {
|
private AdapterView.OnItemLongClickListener mOnItemLongClickListenerProxy = new AdapterView.OnItemLongClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
if (mOnNodeInfoSelectListener != null) {
|
if (mOnItemLongClickListener != null) {
|
||||||
mOnNodeInfoSelectListener.onNodeSelect(((ViewHolder) view.getTag()).nodeInfo);
|
mOnItemLongClickListener.onItemLongClick(view, ((ViewHolder) view.getTag()).nodeInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -55,7 +62,9 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
|||||||
private Drawable mOriginalBackground;
|
private Drawable mOriginalBackground;
|
||||||
|
|
||||||
private boolean mShowClickedNodeBounds;
|
private boolean mShowClickedNodeBounds;
|
||||||
private int mClickedColor = 0x77c4c4c4;
|
private int mClickedColor = 0x99b2b3b7;
|
||||||
|
private NodeInfo mRootNode;
|
||||||
|
private Set<NodeInfo> mInitiallyExpandedNodes = new HashSet<>();
|
||||||
|
|
||||||
public LayoutHierarchyView(Context context) {
|
public LayoutHierarchyView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -80,6 +89,9 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
|||||||
mClickedColor = clickedColor;
|
mClickedColor = clickedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getStatusBarHeight() {
|
||||||
|
return mStatusBarHeight;
|
||||||
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
mAdapter = new Adapter();
|
mAdapter = new Adapter();
|
||||||
@@ -127,12 +139,14 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setRootNode(NodeInfo rootNodeInfo) {
|
public void setRootNode(NodeInfo rootNodeInfo) {
|
||||||
|
mRootNode = rootNodeInfo;
|
||||||
mAdapter.setDataItems(Collections.singletonList(rootNodeInfo));
|
mAdapter.setDataItems(Collections.singletonList(rootNodeInfo));
|
||||||
mClickedNodeInfo = null;
|
mClickedNodeInfo = null;
|
||||||
|
mInitiallyExpandedNodes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnNodeInfoLongClickListener(final OnNodeInfoSelectListener onNodeInfoSelectListener) {
|
public void setOnItemLongClickListener(final OnItemLongClickListener onNodeInfoSelectListener) {
|
||||||
mOnNodeInfoSelectListener = onNodeInfoSelectListener;
|
mOnItemLongClickListener = onNodeInfoSelectListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -143,6 +157,35 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSelectedNode(NodeInfo selectedNode) {
|
||||||
|
mInitiallyExpandedNodes.clear();
|
||||||
|
Stack<NodeInfo> parents = new Stack<>();
|
||||||
|
searchNodeParents(selectedNode, mRootNode, parents);
|
||||||
|
mClickedNodeInfo = parents.peek();
|
||||||
|
for (NodeInfo nodeInfo : parents) {
|
||||||
|
mInitiallyExpandedNodes.add(nodeInfo);
|
||||||
|
}
|
||||||
|
mAdapter.reloadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean searchNodeParents(NodeInfo nodeInfo, NodeInfo rootNode, Stack<NodeInfo> stack) {
|
||||||
|
stack.push(rootNode);
|
||||||
|
if (nodeInfo == rootNode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
boolean found = false;
|
||||||
|
for (NodeInfo child : rootNode.getChildren()) {
|
||||||
|
if (searchNodeParents(nodeInfo, child, stack)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
private class ViewHolder {
|
private class ViewHolder {
|
||||||
TextView nameView;
|
TextView nameView;
|
||||||
TextView infoView;
|
TextView infoView;
|
||||||
@@ -163,15 +206,20 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<?> getSubObjects(Object object) {
|
protected List<?> getSubObjects(Object object) {
|
||||||
return ((NodeInfo) object).getChildren();
|
return ((NodeInfo) object).getChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isExpandable(Object object) {
|
protected boolean isExpandable(Object object) {
|
||||||
return !((NodeInfo) object).getChildren().isEmpty();
|
return !((NodeInfo) object).getChildren().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isInitiallyExpanded(Object object) {
|
||||||
|
return mInitiallyExpandedNodes.contains((NodeInfo) object);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getViewForObject(Object object, View convertView, ItemInfo itemInfo) {
|
public View getViewForObject(Object object, View convertView, ItemInfo itemInfo) {
|
||||||
NodeInfo nodeInfo = (NodeInfo) object;
|
NodeInfo nodeInfo = (NodeInfo) object;
|
||||||
@@ -199,6 +247,9 @@ public class LayoutHierarchyView extends MultiLevelListView {
|
|||||||
|
|
||||||
viewHolder.levelBeamView.setLevel(itemInfo.getLevel());
|
viewHolder.levelBeamView.setLevel(itemInfo.getLevel());
|
||||||
|
|
||||||
|
if (nodeInfo == mClickedNodeInfo) {
|
||||||
|
setClickedItem(convertView, nodeInfo);
|
||||||
|
}
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.support.annotation.AttrRes;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.annotation.RequiresApi;
|
|
||||||
import android.support.annotation.StyleRes;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ViewSwitcher;
|
|
||||||
|
|
||||||
import com.stardust.scriptdroid.R;
|
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/10.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class LayoutInspectView extends FrameLayout {
|
|
||||||
|
|
||||||
private ViewSwitcher mViewSwitcher;
|
|
||||||
private NodeInfoView mNodeInfoView;
|
|
||||||
private LayoutHierarchyView mLayoutBoundsView;
|
|
||||||
private View mCurrentView;
|
|
||||||
|
|
||||||
public LayoutInspectView(@NonNull Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutInspectView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutInspectView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public LayoutInspectView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
|
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
inflate(getContext(), R.layout.floating_window_expand, this);
|
|
||||||
mNodeInfoView = (NodeInfoView) findViewById(R.id.node_info);
|
|
||||||
mLayoutBoundsView = (LayoutHierarchyView) findViewById(R.id.bounds_view);
|
|
||||||
mViewSwitcher = (ViewSwitcher) findViewById(R.id.view_switcher);
|
|
||||||
mCurrentView = mNodeInfoView;
|
|
||||||
mLayoutBoundsView.setOnNodeInfoLongClickListener(new OnNodeInfoSelectListener() {
|
|
||||||
@Override
|
|
||||||
public void onNodeSelect(NodeInfo info) {
|
|
||||||
mNodeInfoView.setNodeInfo(info);
|
|
||||||
showNodeInfoView();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showNodeInfoView() {
|
|
||||||
if (mCurrentView != mNodeInfoView) {
|
|
||||||
mViewSwitcher.showPrevious();
|
|
||||||
mCurrentView = mNodeInfoView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLayoutBoundsViewShowing() {
|
|
||||||
return mCurrentView == mLayoutBoundsView;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNodeInfoViewShowing() {
|
|
||||||
return mCurrentView == mNodeInfoView;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void backToLayoutBoundsView() {
|
|
||||||
if (mCurrentView != mLayoutBoundsView) {
|
|
||||||
mViewSwitcher.showNext();
|
|
||||||
mCurrentView = mLayoutBoundsView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
|
package com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -12,23 +14,68 @@ import android.widget.Toast;
|
|||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
||||||
import com.stardust.util.ClipboardUtil;
|
import com.stardust.util.ClipboardUtil;
|
||||||
|
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import de.codecrafters.tableview.TableDataAdapter;
|
import butterknife.BindView;
|
||||||
import de.codecrafters.tableview.TableView;
|
import butterknife.ButterKnife;
|
||||||
import de.codecrafters.tableview.model.TableColumnWeightModel;
|
import butterknife.OnClick;
|
||||||
import de.codecrafters.tableview.toolkit.SimpleTableDataAdapter;
|
import butterknife.OnLongClick;
|
||||||
import de.codecrafters.tableview.toolkit.TableDataRowBackgroundProviders;
|
import butterknife.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/3/10.
|
* Created by Stardust on 2017/3/10.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NodeInfoView extends TableView {
|
public class NodeInfoView extends RecyclerView {
|
||||||
|
|
||||||
private static final Field[] fields = NodeInfo.class.getFields();
|
private static final String[] FIELD_NAMES = {
|
||||||
private String[][] mData = new String[fields.length][2];
|
"id",
|
||||||
|
"bounds",
|
||||||
|
"desc",
|
||||||
|
"className",
|
||||||
|
"packageName",
|
||||||
|
"text",
|
||||||
|
"drawingOrder",
|
||||||
|
"accessibilityFocused",
|
||||||
|
"checked",
|
||||||
|
"clickable",
|
||||||
|
"contextClickable",
|
||||||
|
"dismissable",
|
||||||
|
"editable",
|
||||||
|
"enabled",
|
||||||
|
"focusable",
|
||||||
|
"longClickable",
|
||||||
|
"selected",
|
||||||
|
"scrollable",
|
||||||
|
};
|
||||||
|
private static final Field[] FIELDS = new Field[FIELD_NAMES.length];
|
||||||
|
|
||||||
|
static {
|
||||||
|
Arrays.sort(FIELD_NAMES);
|
||||||
|
for (int i = 0; i < FIELD_NAMES.length; i++) {
|
||||||
|
try {
|
||||||
|
FIELDS[i] = NodeInfo.class.getDeclaredField(FIELD_NAMES[i]);
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[][] mData = new String[FIELDS.length + 1][2];
|
||||||
|
private OnLongClickListener itemLongClickListener = new OnLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
int pos = getChildAdapterPosition(v);
|
||||||
|
if (pos < 1 || pos >= mData.length)
|
||||||
|
return false;
|
||||||
|
ClipboardUtil.setClip(getContext(), mData[pos][0] + " = " + mData[pos][1]);
|
||||||
|
Toast.makeText(getContext(), R.string.text_copy_to_clip, Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public NodeInfoView(Context context) {
|
public NodeInfoView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -46,67 +93,88 @@ public class NodeInfoView extends TableView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeInfo(NodeInfo nodeInfo) {
|
public void setNodeInfo(NodeInfo nodeInfo) {
|
||||||
for (int i = 0; i < fields.length; i++) {
|
for (int i = 0; i < FIELDS.length; i++) {
|
||||||
try {
|
try {
|
||||||
Object value = fields[i].get(nodeInfo);
|
Object value = FIELDS[i].get(nodeInfo);
|
||||||
mData[i][1] = value == null ? "null" : value.toString();
|
mData[i + 1][1] = value == null ? "" : value.toString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getDataAdapter().notifyDataSetChanged();
|
getAdapter().notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
initData();
|
initData();
|
||||||
setUpTableConfig();
|
setAdapter(new Adapter());
|
||||||
setAdapter();
|
setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
setUpStyle();
|
addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext())
|
||||||
}
|
.color(0x1e000000)
|
||||||
|
.size(2)
|
||||||
private void setAdapter() {
|
.build());
|
||||||
setDataAdapter(new TableDataAdapter<String[]>(getContext(), mData) {
|
|
||||||
SimpleTableDataAdapter mSimpleTableDataAdapter = new SimpleTableDataAdapter(getContext(), mData);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getCellView(int rowIndex, int columnIndex, ViewGroup parentView) {
|
|
||||||
final TextView textView = (TextView) mSimpleTableDataAdapter.getCellView(rowIndex, columnIndex, parentView);
|
|
||||||
textView.setSingleLine(false);
|
|
||||||
textView.setMaxLines(3);
|
|
||||||
textView.setTextColor(0xcc000000);
|
|
||||||
textView.setTextIsSelectable(true);
|
|
||||||
textView.setOnLongClickListener(new OnLongClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View v) {
|
|
||||||
ClipboardUtil.setClip(getContext(), textView.getText());
|
|
||||||
Toast.makeText(getContext(), R.string.text_already_copy_to_clip, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return textView;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setUpTableConfig() {
|
|
||||||
setColumnCount(2);
|
|
||||||
setColumnModel(new TableColumnWeightModel(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initData() {
|
private void initData() {
|
||||||
for (int i = 0; i < mData.length; i++) {
|
mData[0][0] = getResources().getString(R.string.text_attribute);
|
||||||
mData[i][0] = fields[i].getName();
|
mData[0][1] = getResources().getString(R.string.text_value);
|
||||||
|
for (int i = 1; i < mData.length; i++) {
|
||||||
|
mData[i][0] = FIELD_NAMES[i - 1];
|
||||||
mData[i][1] = "";
|
mData[i][1] = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpStyle() {
|
private class Adapter extends RecyclerView.Adapter<ViewHolder> {
|
||||||
int colorEvenRows = Color.WHITE;
|
|
||||||
int colorOddRows = 0xffe7e7e7;
|
final int VIEW_TYPE_HEADER = 0;
|
||||||
setDataRowBackgroundProvider(TableDataRowBackgroundProviders.alternatingRowColors(colorEvenRows, colorOddRows));
|
final int VIEW_TYPE_ITEM = 1;
|
||||||
getChildAt(0).setVisibility(GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
int layoutRes = viewType == VIEW_TYPE_HEADER ? R.layout.node_info_view_header : R.layout.node_info_view_item;
|
||||||
|
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
holder.attrName.setText(mData[position][0]);
|
||||||
|
holder.attrValue.setText(mData[position][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mData.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
return position == 0 ? VIEW_TYPE_HEADER : VIEW_TYPE_ITEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
|
||||||
|
@BindView(R.id.name)
|
||||||
|
TextView attrName;
|
||||||
|
|
||||||
|
@BindView(R.id.value)
|
||||||
|
TextView attrValue;
|
||||||
|
|
||||||
|
public ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ButterKnife.bind(this, itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Optional
|
||||||
|
@OnClick(R.id.item)
|
||||||
|
void onItemClick() {
|
||||||
|
int pos = getAdapterPosition();
|
||||||
|
if (pos < 1 || pos >= mData.length)
|
||||||
|
return;
|
||||||
|
ClipboardUtil.setClip(getContext(), mData[pos][0] + " = " + mData[pos][1]);
|
||||||
|
Toast.makeText(getContext(), R.string.text_already_copy_to_clip, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,24 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.view;
|
package com.stardust.scriptdroid.external.floatingwindow.menu.view;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.afollestad.materialdialogs.Theme;
|
import com.afollestad.materialdialogs.Theme;
|
||||||
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutBoundsView;
|
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.NodeInfoView;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.OnNodeInfoSelectListener;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.OnNodeInfoSelectListener;
|
||||||
import com.stardust.util.MessageEvent;
|
import com.stardust.util.MessageIntent;
|
||||||
|
import com.stardust.widget.BubblePopupMenu;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/3/12.
|
* Created by Stardust on 2017/3/12.
|
||||||
@@ -20,7 +27,9 @@ import com.stardust.util.MessageEvent;
|
|||||||
public class FloatingLayoutBoundsView extends LayoutBoundsView {
|
public class FloatingLayoutBoundsView extends LayoutBoundsView {
|
||||||
|
|
||||||
private MaterialDialog mNodeInfoDialog;
|
private MaterialDialog mNodeInfoDialog;
|
||||||
|
private BubblePopupMenu mBubblePopMenu;
|
||||||
private NodeInfoView mNodeInfoView;
|
private NodeInfoView mNodeInfoView;
|
||||||
|
private NodeInfo mSelectedNode;
|
||||||
|
|
||||||
public FloatingLayoutBoundsView(Context context) {
|
public FloatingLayoutBoundsView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -31,21 +40,46 @@ public class FloatingLayoutBoundsView extends LayoutBoundsView {
|
|||||||
setOnNodeInfoSelectListener(new OnNodeInfoSelectListener() {
|
setOnNodeInfoSelectListener(new OnNodeInfoSelectListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onNodeSelect(NodeInfo info) {
|
public void onNodeSelect(NodeInfo info) {
|
||||||
showNodeInfo(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);
|
setVisibility(GONE);
|
||||||
getPaint().setColor(0xFF222222);
|
getBoundsPaint().setStrokeWidth(2f);
|
||||||
getPaint().setStrokeWidth(2f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showNodeInfo(NodeInfo info) {
|
private void showNodeInfo() {
|
||||||
ensureDialog();
|
ensureDialog();
|
||||||
mNodeInfoView.setNodeInfo(info);
|
mNodeInfoView.setNodeInfo(mSelectedNode);
|
||||||
mNodeInfoDialog.show();
|
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() {
|
private void ensureDialog() {
|
||||||
if (mNodeInfoDialog == null) {
|
if (mNodeInfoDialog == null) {
|
||||||
mNodeInfoView = new NodeInfoView(getContext());
|
mNodeInfoView = new NodeInfoView(getContext());
|
||||||
@@ -53,14 +87,14 @@ public class FloatingLayoutBoundsView extends LayoutBoundsView {
|
|||||||
.customView(mNodeInfoView, false)
|
.customView(mNodeInfoView, false)
|
||||||
.theme(Theme.LIGHT)
|
.theme(Theme.LIGHT)
|
||||||
.build();
|
.build();
|
||||||
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_SHOW_AND_EXPAND_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_AND_EXPAND_MENU));
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
package com.stardust.scriptdroid.external.floatingwindow.menu.view;
|
package com.stardust.scriptdroid.external.floatingwindow.menu.view;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.afollestad.materialdialogs.Theme;
|
import com.afollestad.materialdialogs.Theme;
|
||||||
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.HoverMenuService;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.NodeInfo;
|
||||||
import com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutHierarchyView;
|
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.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.util.MessageEvent;
|
import com.stardust.widget.BubblePopupMenu;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/3/12.
|
* Created by Stardust on 2017/3/12.
|
||||||
@@ -20,9 +26,12 @@ import com.stardust.util.MessageEvent;
|
|||||||
public class FloatingLayoutHierarchyView extends LayoutHierarchyView {
|
public class FloatingLayoutHierarchyView extends LayoutHierarchyView {
|
||||||
|
|
||||||
private static final String TAG = "FloatingHierarchyView";
|
private static final String TAG = "FloatingHierarchyView";
|
||||||
|
private static final int COLOR_SHADOW = 0xddffffff;
|
||||||
|
|
||||||
private MaterialDialog mNodeInfoDialog;
|
private MaterialDialog mNodeInfoDialog;
|
||||||
|
private BubblePopupMenu mBubblePopMenu;
|
||||||
private NodeInfoView mNodeInfoView;
|
private NodeInfoView mNodeInfoView;
|
||||||
|
private NodeInfo mSelectedNodeInfo;
|
||||||
|
|
||||||
public FloatingLayoutHierarchyView(Context context) {
|
public FloatingLayoutHierarchyView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -30,26 +39,53 @@ public class FloatingLayoutHierarchyView extends LayoutHierarchyView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
setBackgroundColor(0x99ffffff);
|
setBackgroundColor(COLOR_SHADOW);
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
setShowClickedNodeBounds(true);
|
setShowClickedNodeBounds(true);
|
||||||
getBoundsPaint().setStrokeWidth(3);
|
getBoundsPaint().setStrokeWidth(3);
|
||||||
getBoundsPaint().setColor(0xFFD32F2F);
|
getBoundsPaint().setColor(0xFFD32F2F);
|
||||||
setOnNodeInfoLongClickListener(new OnNodeInfoSelectListener() {
|
setOnItemLongClickListener(new OnItemLongClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onNodeSelect(NodeInfo info) {
|
public void onItemLongClick(View view, NodeInfo nodeInfo) {
|
||||||
showNodeInfo(info);
|
mSelectedNodeInfo = nodeInfo;
|
||||||
|
ensureOperationPopMenu();
|
||||||
|
if (mBubblePopMenu.getContentView().getMeasuredWidth() <= 0)
|
||||||
|
mBubblePopMenu.preMeasure();
|
||||||
|
mBubblePopMenu.showAsDropDown(view, view.getWidth() / 2 - mBubblePopMenu.getContentView().getMeasuredWidth() / 2, 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showNodeInfo(NodeInfo info) {
|
private void ensureOperationPopMenu() {
|
||||||
ensureDialog();
|
if (mBubblePopMenu != null)
|
||||||
mNodeInfoView.setNodeInfo(info);
|
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();
|
mNodeInfoDialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureDialog() {
|
private void ensureNodeInfoDialog() {
|
||||||
if (mNodeInfoDialog == null) {
|
if (mNodeInfoDialog == null) {
|
||||||
mNodeInfoView = new NodeInfoView(getContext());
|
mNodeInfoView = new NodeInfoView(getContext());
|
||||||
mNodeInfoDialog = new MaterialDialog.Builder(getContext())
|
mNodeInfoDialog = new MaterialDialog.Builder(getContext())
|
||||||
@@ -57,18 +93,19 @@ public class FloatingLayoutHierarchyView extends LayoutHierarchyView {
|
|||||||
.theme(Theme.LIGHT)
|
.theme(Theme.LIGHT)
|
||||||
.build();
|
.build();
|
||||||
if (mNodeInfoDialog.getWindow() != null)
|
if (mNodeInfoDialog.getWindow() != null)
|
||||||
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_SHOW_AND_EXPAND_MENU));
|
HoverMenuService.postIntent(new Intent(HoverMenuService.ACTION_SHOW_AND_EXPAND_MENU));
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.dispatchKeyEvent(event);
|
return super.dispatchKeyEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,7 +40,7 @@ public class SublimePluginClient {
|
|||||||
private String host;
|
private String host;
|
||||||
private int port;
|
private int port;
|
||||||
private OutputStream mOutputStream;
|
private OutputStream mOutputStream;
|
||||||
private Executor mExecutor;
|
private ExecutorService mExecutor;
|
||||||
|
|
||||||
public SublimePluginClient(String host, int port) {
|
public SublimePluginClient(String host, int port) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
@@ -105,8 +106,10 @@ public class SublimePluginClient {
|
|||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (mSocket != null) {
|
if (mSocket != null) {
|
||||||
mSocket.close();
|
mSocket.close();
|
||||||
|
mExecutor.shutdownNow();
|
||||||
mSocket = null;
|
mSocket = null;
|
||||||
mOutputStream = null;
|
mOutputStream = null;
|
||||||
|
mExecutor = null;
|
||||||
EventBus.getDefault().post(new ConnectionStateChangeEvent(false));
|
EventBus.getDefault().post(new ConnectionStateChangeEvent(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.stardust.scriptdroid.ui.main.script_list;
|
package com.stardust.scriptdroid.ui.main.script_list;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
@@ -13,6 +14,7 @@ import android.widget.EditText;
|
|||||||
import com.afollestad.materialdialogs.DialogAction;
|
import com.afollestad.materialdialogs.DialogAction;
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.stardust.app.Fragment;
|
import com.stardust.app.Fragment;
|
||||||
|
import com.stardust.app.OperationDialogBuilder;
|
||||||
import com.stardust.scriptdroid.script.ScriptFile;
|
import com.stardust.scriptdroid.script.ScriptFile;
|
||||||
import com.stardust.pio.PFile;
|
import com.stardust.pio.PFile;
|
||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
@@ -20,6 +22,7 @@ import com.stardust.scriptdroid.script.Scripts;
|
|||||||
import com.stardust.scriptdroid.script.StorageScriptProvider;
|
import com.stardust.scriptdroid.script.StorageScriptProvider;
|
||||||
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
import com.stardust.scriptdroid.ui.edit.EditActivity;
|
||||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||||
|
import com.stardust.util.UnderuseExecutors;
|
||||||
import com.stardust.view.ViewBinder;
|
import com.stardust.view.ViewBinder;
|
||||||
import com.stardust.view.ViewBinding;
|
import com.stardust.view.ViewBinding;
|
||||||
import com.stardust.widget.SimpleAdapterDataObserver;
|
import com.stardust.widget.SimpleAdapterDataObserver;
|
||||||
@@ -29,6 +32,9 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import butterknife.OnClick;
|
||||||
|
import butterknife.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/3/13.
|
* Created by Stardust on 2017/3/13.
|
||||||
*/
|
*/
|
||||||
@@ -109,15 +115,17 @@ public class MyScriptListFragment extends Fragment {
|
|||||||
|
|
||||||
|
|
||||||
private void initDialogs() {
|
private void initDialogs() {
|
||||||
mScriptFileOperationDialog = buildDialog(R.layout.dialog_script_file_operations);
|
mScriptFileOperationDialog = new OperationDialogBuilder(getContext())
|
||||||
mDirectoryOperationDialog = buildDialog(R.layout.dialog_directory_operations);
|
.item(R.id.rename, R.drawable.ic_ali_rename, R.string.text_rename)
|
||||||
}
|
.item(R.id.open_by_other_apps, R.drawable.ic_ali_open, R.string.text_open_by_other_apps)
|
||||||
|
.item(R.id.create_shortcut, R.drawable.ic_ali_shortcut, R.string.text_send_shortcut)
|
||||||
private MaterialDialog buildDialog(int layout) {
|
.item(R.id.delete, R.drawable.ic_ali_delete, R.string.text_delete)
|
||||||
View view = View.inflate(getActivity(), layout, null);
|
.bindItemClick(this)
|
||||||
ViewBinder.bind(this, view);
|
.build();
|
||||||
return new MaterialDialog.Builder(getActivity())
|
mDirectoryOperationDialog = new OperationDialogBuilder(getContext())
|
||||||
.customView(view, false)
|
.item(R.id.rename, R.drawable.ic_ali_rename, R.string.text_rename)
|
||||||
|
.item(R.id.delete, R.drawable.ic_ali_delete, R.string.text_delete)
|
||||||
|
.bindItemClick(this)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,8 +238,9 @@ public class MyScriptListFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBinding.Click(R.id.rename)
|
@Optional
|
||||||
private void renameScriptFile() {
|
@OnClick(R.id.rename)
|
||||||
|
void renameScriptFile() {
|
||||||
dismissDialogs();
|
dismissDialogs();
|
||||||
String originalName = mSelectedScriptFile.getSimplifiedName();
|
String originalName = mSelectedScriptFile.getSimplifiedName();
|
||||||
showNameInputDialog(originalName, new InputCallback(mSelectedScriptFile.isDirectory(), originalName), new MaterialDialog.InputCallback() {
|
showNameInputDialog(originalName, new InputCallback(mSelectedScriptFile.isDirectory(), originalName), new MaterialDialog.InputCallback() {
|
||||||
@@ -252,8 +261,9 @@ public class MyScriptListFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ViewBinding.Click(R.id.open_by_other_apps)
|
@Optional
|
||||||
private void openByOtherApps() {
|
@OnClick(R.id.open_by_other_apps)
|
||||||
|
void openByOtherApps() {
|
||||||
dismissDialogs();
|
dismissDialogs();
|
||||||
Scripts.openByOtherApps(mSelectedScriptFile);
|
Scripts.openByOtherApps(mSelectedScriptFile);
|
||||||
onScriptFileOperated();
|
onScriptFileOperated();
|
||||||
@@ -269,16 +279,18 @@ public class MyScriptListFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBinding.Click(R.id.create_shortcut)
|
@Optional
|
||||||
private void createShortcut() {
|
@OnClick(R.id.create_shortcut)
|
||||||
|
void createShortcut() {
|
||||||
dismissDialogs();
|
dismissDialogs();
|
||||||
Scripts.createShortcut(mSelectedScriptFile);
|
Scripts.createShortcut(mSelectedScriptFile);
|
||||||
Snackbar.make(getView(), R.string.text_already_create, Snackbar.LENGTH_SHORT).show();
|
Snackbar.make(getView(), R.string.text_already_create, Snackbar.LENGTH_SHORT).show();
|
||||||
onScriptFileOperated();
|
onScriptFileOperated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBinding.Click(R.id.delete)
|
@Optional
|
||||||
private void deleteScriptFile() {
|
@OnClick(R.id.delete)
|
||||||
|
void deleteScriptFile() {
|
||||||
dismissDialogs();
|
dismissDialogs();
|
||||||
new MaterialDialog.Builder(getActivity())
|
new MaterialDialog.Builder(getActivity())
|
||||||
.title(R.string.delete_confirm)
|
.title(R.string.delete_confirm)
|
||||||
@@ -295,7 +307,7 @@ public class MyScriptListFragment extends Fragment {
|
|||||||
|
|
||||||
private void doDeletingScriptFile() {
|
private void doDeletingScriptFile() {
|
||||||
mScriptListWithProgressBarView.showProgressBar();
|
mScriptListWithProgressBarView.showProgressBar();
|
||||||
new Thread(new Runnable() {
|
UnderuseExecutors.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (PFile.deleteRecursively(mSelectedScriptFile)) {
|
if (PFile.deleteRecursively(mSelectedScriptFile)) {
|
||||||
@@ -306,7 +318,7 @@ public class MyScriptListFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
onScriptFileOperated();
|
onScriptFileOperated();
|
||||||
}
|
}
|
||||||
}).start();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMessage(final int resId) {
|
private void showMessage(final int resId) {
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ public abstract class BindableViewHolder<DataType> extends RecyclerView.ViewHold
|
|||||||
super(itemView);
|
super(itemView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void bind(DataType data);
|
public abstract void bind(DataType data, int position);
|
||||||
}
|
}
|
||||||
|
|||||||
109
app/src/main/java/com/stardust/widget/BubblePopupMenu.java
Normal file
109
app/src/main/java/com/stardust/widget/BubblePopupMenu.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package com.stardust.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.PopupWindow;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.stardust.scriptdroid.R;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/5/23.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BubblePopupMenu extends PopupWindow {
|
||||||
|
|
||||||
|
|
||||||
|
public interface OnItemClickListener {
|
||||||
|
void onClick(View view, int position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecyclerView mRecyclerView;
|
||||||
|
private OnItemClickListener mOnItemClickListener;
|
||||||
|
private View mLittleTriangle;
|
||||||
|
|
||||||
|
public BubblePopupMenu(Context context, List<String> options) {
|
||||||
|
super(context);
|
||||||
|
View view = View.inflate(context, R.layout.bubble_popup_menu, null);
|
||||||
|
mLittleTriangle = view.findViewById(R.id.little_triangle);
|
||||||
|
mRecyclerView = (RecyclerView) view.findViewById(R.id.list);
|
||||||
|
mRecyclerView.setAdapter(new SimpleRecyclerViewAdapter<>(R.layout.bubble_popup_menu_item, options, new SimpleRecyclerViewAdapter.ViewHolderFactory<MenuItemViewHolder>() {
|
||||||
|
@Override
|
||||||
|
public MenuItemViewHolder create(View itemView) {
|
||||||
|
return new MenuItemViewHolder(itemView);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
setContentView(view);
|
||||||
|
setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||||
|
setOutsideTouchable(true);
|
||||||
|
setFocusable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
|
||||||
|
mOnItemClickListener = onItemClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showAsDropDownAtLocation(View parent, int contentHeight, int x, int y) {
|
||||||
|
int screenWidth = getContentView().getResources().getDisplayMetrics().widthPixels;
|
||||||
|
int screenHeight = getContentView().getResources().getDisplayMetrics().heightPixels;
|
||||||
|
int width = getContentView().getWidth();
|
||||||
|
int height = getContentView().getHeight();
|
||||||
|
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mLittleTriangle.getLayoutParams();
|
||||||
|
if (x + width > screenWidth) {
|
||||||
|
params.leftMargin = x + width - screenWidth;
|
||||||
|
} else if (x < 0) {
|
||||||
|
params.leftMargin = x;
|
||||||
|
} else {
|
||||||
|
params.leftMargin = 0;
|
||||||
|
}
|
||||||
|
if (y + height > screenHeight) {
|
||||||
|
getContentView().setRotation(180);
|
||||||
|
mRecyclerView.setRotation(180);
|
||||||
|
params.leftMargin = -params.leftMargin;
|
||||||
|
y -= contentHeight + height;
|
||||||
|
} else {
|
||||||
|
getContentView().setRotation(0);
|
||||||
|
mRecyclerView.setRotation(0);
|
||||||
|
}
|
||||||
|
mLittleTriangle.setLayoutParams(params);
|
||||||
|
super.showAtLocation(parent, Gravity.NO_GRAVITY, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void preMeasure() {
|
||||||
|
getContentView().measure(getWidth(), getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class MenuItemViewHolder extends BindableViewHolder<String> {
|
||||||
|
|
||||||
|
private TextView mOption;
|
||||||
|
|
||||||
|
public MenuItemViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
mOption = (TextView) itemView.findViewById(R.id.option);
|
||||||
|
itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mOnItemClickListener != null) {
|
||||||
|
int i = mRecyclerView.getChildAdapterPosition(v);
|
||||||
|
mOnItemClickListener.onClick(v, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bind(String s, int position) {
|
||||||
|
mOption.setText(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.stardust.widget;
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/5/24.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SimpleRecyclerViewAdapter<M, VH extends BindableViewHolder<M>> extends RecyclerView.Adapter<VH> {
|
||||||
|
|
||||||
|
public interface ViewHolderFactory<VH> {
|
||||||
|
VH create(View itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<M> mDataList = new ArrayList<>();
|
||||||
|
private int mLayoutResource;
|
||||||
|
private ViewHolderFactory<VH> mVHViewHolderFactory;
|
||||||
|
|
||||||
|
public SimpleRecyclerViewAdapter(int layoutResource, List<M> dataList, ViewHolderFactory<VH> VHViewHolderFactory) {
|
||||||
|
mLayoutResource = layoutResource;
|
||||||
|
mVHViewHolderFactory = VHViewHolderFactory;
|
||||||
|
mDataList.addAll(dataList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleRecyclerViewAdapter(int layoutResource, ViewHolderFactory<VH> VHViewHolderFactory) {
|
||||||
|
this(layoutResource, Collections.<M>emptyList(), VHViewHolderFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
return mVHViewHolderFactory.create(LayoutInflater.from(parent.getContext()).inflate(mLayoutResource, parent, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(VH holder, int position) {
|
||||||
|
M m = mDataList.get(position);
|
||||||
|
holder.bind(m, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mDataList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(M m) {
|
||||||
|
mDataList.add(m);
|
||||||
|
notifyItemInserted(mDataList.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
app/src/main/res/anim/item_hover.xml
Normal file
28
app/src/main/res/anim/item_hover.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="true" android:state_pressed="true">
|
||||||
|
<set>
|
||||||
|
<objectAnimator android:duration="100"
|
||||||
|
android:propertyName="translationZ"
|
||||||
|
android:valueTo="4dp"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
<objectAnimator android:duration="0"
|
||||||
|
android:propertyName="elevation"
|
||||||
|
android:valueTo="2dp"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
|
||||||
|
</set>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<set>
|
||||||
|
<objectAnimator android:duration="0"
|
||||||
|
android:propertyName="translationZ"
|
||||||
|
android:valueTo="0"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
<objectAnimator android:duration="0"
|
||||||
|
android:propertyName="elevation"
|
||||||
|
android:valueTo="0"
|
||||||
|
android:valueType="floatType"/>
|
||||||
|
</set>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
7
app/src/main/res/drawable/bubble.xml
Normal file
7
app/src/main/res/drawable/bubble.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/bubble_bg"/>
|
||||||
|
|
||||||
|
<corners android:radius="16dp"/>
|
||||||
|
|
||||||
|
</shape>
|
||||||
19
app/src/main/res/drawable/little_triangle.xml
Normal file
19
app/src/main/res/drawable/little_triangle.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<rotate
|
||||||
|
android:fromDegrees="45"
|
||||||
|
android:pivotX="0"
|
||||||
|
android:pivotY="100%"
|
||||||
|
android:toDegrees="45">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<size
|
||||||
|
android:width="12dp"
|
||||||
|
android:height="12dp"/>
|
||||||
|
<solid android:color="@color/bubble_bg"/>
|
||||||
|
</shape>
|
||||||
|
</rotate>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</layer-list>
|
||||||
23
app/src/main/res/layout/bubble_popup_menu.xml
Normal file
23
app/src/main/res/layout/bubble_popup_menu.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/little_triangle"
|
||||||
|
android:layout_width="17dp"
|
||||||
|
android:layout_height="8.5dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:background="@drawable/little_triangle"/>
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/list"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bubble"
|
||||||
|
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
19
app/src/main/res/layout/bubble_popup_menu_item.xml
Normal file
19
app/src/main/res/layout/bubble_popup_menu_item.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/option"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:textColor="@android:color/primary_text_light"
|
||||||
|
android:textSize="15sp"
|
||||||
|
tools:text="OOXX"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<com.stardust.theme.widget.ThemeColorToolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:background="@color/colorPrimary"
|
|
||||||
app:popupTheme="@style/AppTheme.PopupOverlay"
|
|
||||||
app:title="@string/_app_name"
|
|
||||||
app:titleTextColor="@android:color/white"/>
|
|
||||||
|
|
||||||
<ViewSwitcher
|
|
||||||
android:id="@+id/view_switcher"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.NodeInfoView
|
|
||||||
android:id="@+id/node_info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="#ffffff"/>
|
|
||||||
|
|
||||||
<com.stardust.scriptdroid.external.floatingwindow.menu.layout_inspector.view.LayoutHierarchyView
|
|
||||||
android:id="@+id/bounds_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="#ffffff"/>
|
|
||||||
|
|
||||||
</ViewSwitcher>
|
|
||||||
</LinearLayout>
|
|
||||||
23
app/src/main/res/layout/node_info_view_header.xml
Normal file
23
app/src/main/res/layout/node_info_view_header.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:textColor="#8a000000"
|
||||||
|
android:textSize="12sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:textColor="#8a000000"
|
||||||
|
android:textSize="12sp"/>
|
||||||
|
</LinearLayout>
|
||||||
26
app/src/main/res/layout/node_info_view_item.xml
Normal file
26
app/src/main/res/layout/node_info_view_item.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/item"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:textColor="#de000000"
|
||||||
|
android:textSize="13sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:textColor="#8a000000"
|
||||||
|
android:textSize="13sp"/>
|
||||||
|
</LinearLayout>
|
||||||
25
app/src/main/res/layout/operation_dialog_item.xml
Normal file
25
app/src/main/res/layout/operation_dialog_item.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:paddingLeft="24dp"
|
||||||
|
android:paddingTop="16dp">
|
||||||
|
|
||||||
|
<com.stardust.theme.widget.ThemeColorImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textColor="@android:color/primary_text_light"
|
||||||
|
android:textSize="16sp"/>
|
||||||
|
</LinearLayout>
|
||||||
@@ -4,4 +4,5 @@
|
|||||||
<color name="colorPrimaryDark">#00796B</color>
|
<color name="colorPrimaryDark">#00796B</color>
|
||||||
<color name="colorAccent">#536DFE</color>
|
<color name="colorAccent">#536DFE</color>
|
||||||
<color name="sliding_up_panel_shadow_color">#99444444</color>
|
<color name="sliding_up_panel_shadow_color">#99444444</color>
|
||||||
|
<color name="bubble_bg">#eef2f3f9</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -184,6 +184,11 @@
|
|||||||
<string name="text_server_address">服务器地址</string>
|
<string name="text_server_address">服务器地址</string>
|
||||||
<string name="text_annunciation">声明</string>
|
<string name="text_annunciation">声明</string>
|
||||||
<string name="text_about_me_and_repo">关于项目与开发者</string>
|
<string name="text_about_me_and_repo">关于项目与开发者</string>
|
||||||
|
<string name="text_attribute">属性</string>
|
||||||
|
<string name="text_value">值</string>
|
||||||
|
<string name="text_show_widget_infomation">查看控件信息</string>
|
||||||
|
<string name="text_show_layout_hierarchy">在布局层次中查看</string>
|
||||||
|
<string name="text_show_layout_bounds">在布局范围中查看</string>
|
||||||
|
|
||||||
<string-array name="record_control_keys">
|
<string-array name="record_control_keys">
|
||||||
<item>无</item>
|
<item>无</item>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:accessibilityEventTypes="typeNotificationStateChanged|typeAnnouncement|typeAssistReadingContext|typeContextClicked|typeGestureDetectionEnd|typeGestureDetectionStart|typeTouchExplorationGestureEnd|typeTouchExplorationGestureStart|typeTouchInteractionEnd|typeTouchInteractionStart|typeViewAccessibilityFocusCleared|typeViewAccessibilityFocused|typeViewClicked|typeViewHoverEnter|typeViewHoverExit|typeViewFocused|typeViewLongClicked|typeViewScrolled|typeViewSelected|typeViewTextChanged|typeViewTextSelectionChanged|typeViewTextTraversedAtMovementGranularity|typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"
|
android:accessibilityEventTypes="typeAllMask"
|
||||||
android:accessibilityFeedbackType="feedbackGeneric"
|
android:accessibilityFeedbackType="feedbackGeneric"
|
||||||
android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility|flagRequestFilterKeyEvents"
|
android:accessibilityFlags="flagReportViewIds|flagRequestEnhancedWebAccessibility|flagRequestFilterKeyEvents"
|
||||||
android:canPerformGestures="true"
|
android:canPerformGestures="true"
|
||||||
android:canRequestEnhancedWebAccessibility="true"
|
android:canRequestEnhancedWebAccessibility="true"
|
||||||
android:canRetrieveWindowContent="true"
|
android:canRetrieveWindowContent="true"
|
||||||
|
|||||||
@@ -13,23 +13,34 @@ import android.media.projection.MediaProjectionManager;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.support.annotation.RequiresApi;
|
import android.support.annotation.RequiresApi;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||||
import com.stardust.util.ScreenMetrics;
|
import com.stardust.util.ScreenMetrics;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/5/17.
|
* Created by Stardust on 2017/5/17.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
public class ScreenCapturer {
|
public class ScreenCapturer {
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "ScreenCapturer";
|
||||||
private ImageReader mImageReader;
|
private ImageReader mImageReader;
|
||||||
private MediaProjection mMediaProjection;
|
private MediaProjection mMediaProjection;
|
||||||
private VirtualDisplay mVirtualDisplay;
|
private VirtualDisplay mVirtualDisplay;
|
||||||
private Image mImage;
|
private volatile Looper mImageAcquireLooper;
|
||||||
|
private final Object mImageWaitingLock = new Object();
|
||||||
|
private volatile Image mImage;
|
||||||
|
private volatile Image mLatestImage;
|
||||||
|
|
||||||
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight, int screenDensity) {
|
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight, int screenDensity) {
|
||||||
MediaProjectionManager manager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
|
MediaProjectionManager manager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
|
||||||
initVirtualDisplay(manager, data, screenWidth, screenHeight, screenDensity);
|
initVirtualDisplay(manager, data, screenWidth, screenHeight, screenDensity);
|
||||||
|
startAcquireImageLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight) {
|
public ScreenCapturer(Context context, Intent data, int screenWidth, int screenHeight) {
|
||||||
@@ -41,31 +52,64 @@ public class ScreenCapturer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initVirtualDisplay(MediaProjectionManager manager, Intent data, int screenWidth, int screenHeight, int screenDensity) {
|
private void initVirtualDisplay(MediaProjectionManager manager, Intent data, int screenWidth, int screenHeight, int screenDensity) {
|
||||||
mImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 1);
|
mImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);
|
||||||
mMediaProjection = manager.getMediaProjection(Activity.RESULT_OK, data);
|
mMediaProjection = manager.getMediaProjection(Activity.RESULT_OK, data);
|
||||||
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
|
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
|
||||||
screenWidth, screenHeight, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
screenWidth, screenHeight, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
|
||||||
mImageReader.getSurface(), null, null);
|
mImageReader.getSurface(), null, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image capture() {
|
private void startAcquireImageLoop() {
|
||||||
if (mImage != null) {
|
new Thread(new Runnable() {
|
||||||
mImage.close();
|
@Override
|
||||||
}
|
public void run() {
|
||||||
mImage = mImageReader.acquireLatestImage();
|
|
||||||
if (mImage == null) {
|
|
||||||
Looper.prepare();
|
Looper.prepare();
|
||||||
|
mImageAcquireLooper = Looper.myLooper();
|
||||||
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
|
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onImageAvailable(ImageReader reader) {
|
public void onImageAvailable(ImageReader reader) {
|
||||||
Looper.myLooper().quit();
|
if (mLatestImage != null) {
|
||||||
|
mLatestImage.close();
|
||||||
|
}
|
||||||
|
mLatestImage = reader.acquireNextImage();
|
||||||
|
if (mLatestImage != null) {
|
||||||
|
synchronized (mImageWaitingLock) {
|
||||||
|
mImageWaitingLock.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
Looper.loop();
|
Looper.loop();
|
||||||
mImage = mImageReader.acquireLatestImage();
|
|
||||||
}
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image capture() {
|
||||||
|
if (mLatestImage == null) {
|
||||||
|
if (mImage != null) {
|
||||||
return mImage;
|
return mImage;
|
||||||
}
|
}
|
||||||
|
waitForImageAvailable();
|
||||||
|
}
|
||||||
|
if (mImage != null) {
|
||||||
|
mImage.close();
|
||||||
|
}
|
||||||
|
mImage = mLatestImage;
|
||||||
|
mLatestImage = null;
|
||||||
|
return mImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitForImageAvailable() {
|
||||||
|
Log.d(LOG_TAG, "waitForImageAvailable");
|
||||||
|
synchronized (mImageWaitingLock) {
|
||||||
|
try {
|
||||||
|
mImageWaitingLock.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new ScriptInterruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
@@ -76,8 +120,17 @@ public class ScreenCapturer {
|
|||||||
if (mVirtualDisplay != null) {
|
if (mVirtualDisplay != null) {
|
||||||
mVirtualDisplay.release();
|
mVirtualDisplay.release();
|
||||||
}
|
}
|
||||||
|
if (mImageReader != null) {
|
||||||
|
mImageReader.close();
|
||||||
|
}
|
||||||
|
if (mImageAcquireLooper != null) {
|
||||||
|
mImageAcquireLooper.quitSafely();
|
||||||
|
}
|
||||||
if (mImage != null) {
|
if (mImage != null) {
|
||||||
mImage.close();
|
mImage.close();
|
||||||
}
|
}
|
||||||
|
if (mLatestImage != null) {
|
||||||
|
mLatestImage.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
|
|
||||||
public abstract class AccessibilityService extends android.accessibilityservice.AccessibilityService {
|
public abstract class AccessibilityService extends android.accessibilityservice.AccessibilityService {
|
||||||
|
|
||||||
public interface NotificationCallback {
|
|
||||||
void onNotification();
|
|
||||||
}
|
|
||||||
|
|
||||||
private CopyOnWriteArrayList<NotificationCallback> mNotificationCallbacks = new CopyOnWriteArrayList<>();
|
|
||||||
private AccessibilityNodeInfo mRootInActiveWindow;
|
private AccessibilityNodeInfo mRootInActiveWindow;
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
@@ -32,7 +27,12 @@ public abstract class AccessibilityService extends android.accessibilityservice.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessibilityNodeInfo getRootInActiveWindow() {
|
public AccessibilityNodeInfo getRootInActiveWindow() {
|
||||||
|
try {
|
||||||
|
return super.getRootInActiveWindow();
|
||||||
|
} catch (IllegalStateException ignored) {
|
||||||
return mRootInActiveWindow;
|
return mRootInActiveWindow;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
51
common/src/main/java/com/stardust/util/MessageIntent.java
Normal file
51
common/src/main/java/com/stardust/util/MessageIntent.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package com.stardust.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/6/27.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MessageIntent extends Intent {
|
||||||
|
|
||||||
|
private HashMap<String, Object> mObjectExtras;
|
||||||
|
|
||||||
|
public MessageIntent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageIntent(Intent o) {
|
||||||
|
super(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageIntent(String action) {
|
||||||
|
super(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageIntent(String action, Uri uri) {
|
||||||
|
super(action, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageIntent(Context packageContext, Class<?> cls) {
|
||||||
|
super(packageContext, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageIntent(String action, Uri uri, Context packageContext, Class<?> cls) {
|
||||||
|
super(action, uri, packageContext, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageIntent putExtra(String key, Object value) {
|
||||||
|
if (mObjectExtras == null) {
|
||||||
|
mObjectExtras = new HashMap<>();
|
||||||
|
}
|
||||||
|
mObjectExtras.put(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getObjectExtra(String key) {
|
||||||
|
return mObjectExtras.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user