Merge branch 'dev' of https://github.com/hyb1996/NoRootScriptDroid into dev
This commit is contained in:
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
@@ -123,7 +123,6 @@ dependencies {
|
||||
implementation 'org.apache.commons:commons-lang3:3.6'
|
||||
//Expandable RecyclerView
|
||||
implementation 'com.thoughtbot:expandablerecyclerview:1.3'
|
||||
implementation('com.github.hyb1996:FloatingCircularActionMenu:0.0.4')
|
||||
implementation 'com.github.hyb1996:Auto.js-ApkBuilder:1.0.1'
|
||||
// RxJava
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.1.2"
|
||||
|
||||
@@ -78,6 +78,7 @@ public class App extends MultiDexApplication {
|
||||
}
|
||||
|
||||
private void setUpDebugEnvironment() {
|
||||
Bugly.isDev = false;
|
||||
CrashHandler crashHandler = new CrashHandler(ErrorReportActivity.class);
|
||||
|
||||
CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(getApplicationContext());
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.autojs.autojs.model.indices.Module;
|
||||
import org.autojs.autojs.model.indices.Modules;
|
||||
import org.autojs.autojs.model.indices.Property;
|
||||
import org.autojs.autojs.ui.widget.GridDividerDecoration;
|
||||
import org.autojs.autojs.workground.WrapContentGridLayoutManger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -98,10 +99,11 @@ public class FunctionsKeyboardView extends FrameLayout {
|
||||
}
|
||||
|
||||
private void initPropertiesView() {
|
||||
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), SPAN_COUNT);
|
||||
mPropertiesView.setLayoutManager(gridLayoutManager);
|
||||
WrapContentGridLayoutManger manager = new WrapContentGridLayoutManger(getContext(), 2);
|
||||
manager.setDebugInfo("FunctionsKeyboardView");
|
||||
mPropertiesView.setLayoutManager(manager);
|
||||
mPropertiesView.setAdapter(new PropertiesAdapter());
|
||||
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
|
||||
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
|
||||
|
||||
@Override
|
||||
public int getSpanSize(int position) {
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.autojs.autojs.ui.viewmodel.ExplorerItemList;
|
||||
import org.autojs.autojs.ui.widget.BindableViewHolder;
|
||||
import org.autojs.autojs.theme.widget.ThemeColorSwipeRefreshLayout;
|
||||
|
||||
import org.autojs.autojs.workground.WrapContentGridLayoutManger;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.Stack;
|
||||
@@ -194,7 +195,8 @@ public class ExplorerView extends ThemeColorSwipeRefreshLayout implements SwipeR
|
||||
|
||||
private void initExplorerItemListView() {
|
||||
mExplorerItemListView.setAdapter(mExplorerAdapter);
|
||||
GridLayoutManager manager = new GridLayoutManager(getContext(), 2);
|
||||
WrapContentGridLayoutManger manager = new WrapContentGridLayoutManger(getContext(), 2);
|
||||
manager.setDebugInfo("ExplorerView");
|
||||
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
|
||||
@Override
|
||||
public int getSpanSize(int position) {
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
package org.autojs.autojs.ui.floating;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.PointF;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/9/25.
|
||||
*/
|
||||
|
||||
public class CircularActionMenu extends FrameLayout {
|
||||
|
||||
public interface OnStateChangeListener {
|
||||
void onExpanding(CircularActionMenu menu);
|
||||
|
||||
void onExpanded(CircularActionMenu menu);
|
||||
|
||||
void onCollapsing(CircularActionMenu menu);
|
||||
|
||||
void onCollapsed(CircularActionMenu menu);
|
||||
|
||||
void onMeasured(CircularActionMenu menu);
|
||||
}
|
||||
|
||||
public static class OnStateChangeListenerAdapter implements OnStateChangeListener {
|
||||
|
||||
@Override
|
||||
public void onExpanding(CircularActionMenu menu) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExpanded(CircularActionMenu menu) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCollapsing(CircularActionMenu menu) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCollapsed(CircularActionMenu menu) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasured(CircularActionMenu menu) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private PointF[] mItemExpandedPositionOffsets;
|
||||
private CopyOnWriteArrayList<OnStateChangeListener> mOnStateChangeListeners = new CopyOnWriteArrayList<>();
|
||||
private boolean mExpanded;
|
||||
private boolean mExpanding = false;
|
||||
private boolean mCollapsing = false;
|
||||
private float mRadius = 200;
|
||||
private float mAngle = (float) Math.toRadians(90);
|
||||
private long mDuration = 200;
|
||||
private int mExpandedHeight = -1;
|
||||
private int mExpandedWidth = -1;
|
||||
private final Interpolator mInterpolator = new FastOutSlowInInterpolator();
|
||||
|
||||
|
||||
public CircularActionMenu(@NonNull Context context) {
|
||||
super(context);
|
||||
init(null);
|
||||
}
|
||||
|
||||
public CircularActionMenu(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(attrs);
|
||||
}
|
||||
|
||||
public CircularActionMenu(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(attrs);
|
||||
}
|
||||
|
||||
private void init(AttributeSet attrs) {
|
||||
if (attrs == null)
|
||||
return;
|
||||
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CircularActionMenu);
|
||||
mRadius = a.getDimensionPixelSize(R.styleable.CircularActionMenu_cam_radius, (int) mRadius);
|
||||
int angleInDegree = a.getInt(R.styleable.CircularActionMenu_cam_angle, 0);
|
||||
if (angleInDegree != 0) {
|
||||
mAngle = (float) Math.toRadians(angleInDegree);
|
||||
}
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
View v = getItemAt(i);
|
||||
LayoutParams params = (LayoutParams) v.getLayoutParams();
|
||||
params.gravity = Gravity.START | Gravity.LEFT | Gravity.CENTER_VERTICAL;
|
||||
// FIXME: 2017/10/17 Not working
|
||||
updateViewLayout(v, params);
|
||||
}
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public float getRadius() {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
public void setRadius(float radius) {
|
||||
mRadius = radius;
|
||||
}
|
||||
|
||||
public float getAngle() {
|
||||
return mAngle;
|
||||
}
|
||||
|
||||
public void setAngle(float angle) {
|
||||
mAngle = angle;
|
||||
}
|
||||
|
||||
public void expand(int direction) {
|
||||
setVisibility(VISIBLE);
|
||||
mExpanding = true;
|
||||
Animator.AnimatorListener listener = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mExpanding = false;
|
||||
mExpanded = true;
|
||||
for (OnStateChangeListener l : mOnStateChangeListeners) {
|
||||
l.onExpanded(CircularActionMenu.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
ScaleAnimation scaleAnimation = createScaleAnimation(0, 1);
|
||||
direction = (direction == Gravity.RIGHT ? 1 : -1);
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
View item = getItemAt(i);
|
||||
item.animate()
|
||||
.translationXBy(direction * mItemExpandedPositionOffsets[i].x)
|
||||
.translationYBy(mItemExpandedPositionOffsets[i].y)
|
||||
.setListener(listener)
|
||||
.setDuration(mDuration)
|
||||
.start();
|
||||
item.startAnimation(scaleAnimation);
|
||||
}
|
||||
for (OnStateChangeListener l : mOnStateChangeListeners) {
|
||||
l.onExpanding(CircularActionMenu.this);
|
||||
}
|
||||
}
|
||||
|
||||
private ScaleAnimation createScaleAnimation(float fromScale, float toScale) {
|
||||
ScaleAnimation scaleAnimation = new ScaleAnimation(fromScale, toScale, fromScale, toScale, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
scaleAnimation.setDuration(mDuration);
|
||||
scaleAnimation.setFillAfter(true);
|
||||
scaleAnimation.setInterpolator(mInterpolator);
|
||||
return scaleAnimation;
|
||||
}
|
||||
|
||||
public View getItemAt(int i) {
|
||||
return getChildAt(i);
|
||||
}
|
||||
|
||||
public void collapse() {
|
||||
Animator.AnimatorListener listener = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mCollapsing = false;
|
||||
mExpanded = false;
|
||||
setVisibility(GONE);
|
||||
for (OnStateChangeListener l : mOnStateChangeListeners) {
|
||||
l.onCollapsed(CircularActionMenu.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
mCollapsing = true;
|
||||
ScaleAnimation scaleAnimation = createScaleAnimation(1, 0);
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
View item = getItemAt(i);
|
||||
item.animate()
|
||||
.translationX(0)
|
||||
.translationY(0)
|
||||
.setListener(listener)
|
||||
.setDuration(mDuration)
|
||||
.setInterpolator(mInterpolator)
|
||||
.start();
|
||||
item.startAnimation(scaleAnimation);
|
||||
}
|
||||
for (OnStateChangeListener l : mOnStateChangeListeners) {
|
||||
l.onCollapsing(CircularActionMenu.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void addOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
|
||||
mOnStateChangeListeners.add(onStateChangeListener);
|
||||
}
|
||||
|
||||
public boolean removeOnStateChangeListener(OnStateChangeListener listener) {
|
||||
return mOnStateChangeListeners.remove(listener);
|
||||
}
|
||||
|
||||
public boolean isExpanded() {
|
||||
return mExpanded;
|
||||
}
|
||||
|
||||
public boolean isExpanding() {
|
||||
return mExpanding;
|
||||
}
|
||||
|
||||
public boolean isCollapsing() {
|
||||
return mCollapsing;
|
||||
}
|
||||
|
||||
|
||||
public int getItemCount() {
|
||||
return getChildCount();
|
||||
}
|
||||
|
||||
private void calcExpandedPositions() {
|
||||
mItemExpandedPositionOffsets = new PointF[getItemCount()];
|
||||
double averageAngle = mAngle / (getItemCount() - 1);
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
double angle = -mAngle / 2 + i * averageAngle;
|
||||
mItemExpandedPositionOffsets[i] = new PointF((float) (mRadius * Math.cos(angle)),
|
||||
(float) (mRadius * Math.sin(angle)));
|
||||
}
|
||||
}
|
||||
|
||||
private void calcExpandedSize() {
|
||||
int maxX = 0;
|
||||
int maxY = 0;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int maxWidth = 0;
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
View item = getItemAt(i);
|
||||
maxWidth = Math.max(item.getMeasuredWidth(), maxWidth);
|
||||
maxX = Math.max((int) (mItemExpandedPositionOffsets[i].x + item.getMeasuredWidth()), maxX);
|
||||
// FIXME: 2017/9/26 这样算出来的高度略大
|
||||
maxY = Math.max((int) (mItemExpandedPositionOffsets[i].y + item.getMeasuredHeight()), maxY);
|
||||
minY = Math.min((int) (mItemExpandedPositionOffsets[i].y - item.getMeasuredHeight()), minY);
|
||||
}
|
||||
mExpandedWidth = maxX;
|
||||
mExpandedHeight = maxY - minY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
measureChildren(widthMeasureSpec, heightMeasureSpec);
|
||||
calcExpandedPositions();
|
||||
if (mExpandedHeight == -1 || mExpandedWidth == -1) {
|
||||
calcExpandedSize();
|
||||
}
|
||||
setMeasuredDimension(2 * mExpandedWidth, mExpandedHeight);
|
||||
for (OnStateChangeListener listener : mOnStateChangeListeners) {
|
||||
listener.onMeasured(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
for (int i = 0; i < getChildCount(); ++i) {
|
||||
final View child = getChildAt(i);
|
||||
measureChild(child, widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
public int getExpandedHeight() {
|
||||
return mExpandedHeight;
|
||||
}
|
||||
|
||||
public int getExpandedWidth() {
|
||||
return mExpandedWidth;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import com.stardust.app.OperationDialogBuilder;
|
||||
import com.stardust.autojs.core.record.Recorder;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
import com.stardust.floatingcircularactionmenu.CircularActionMenu;
|
||||
|
||||
import org.autojs.autojs.Pref;
|
||||
import org.autojs.autojs.R;
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.autojs.autojs.ui.floating;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.floatingcircularactionmenu.CircularActionMenu;
|
||||
|
||||
public interface CircularMenuFloaty {
|
||||
|
||||
|
||||
@@ -11,17 +11,16 @@ import android.view.WindowManager;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
import com.stardust.enhancedfloaty.WindowBridge;
|
||||
import com.stardust.floatingcircularactionmenu.CircularActionMenu;
|
||||
import com.stardust.floatingcircularactionmenu.gesture.BounceDragGesture;
|
||||
import com.stardust.util.ScreenMetrics;
|
||||
|
||||
public class CircularMenuWindow implements FloatyWindow {
|
||||
import org.autojs.autojs.ui.floating.gesture.BounceDragGesture;
|
||||
|
||||
public class CircularMenuWindow extends FloatyWindow {
|
||||
|
||||
private static final String KEY_POSITION_X = CircularMenuWindow.class.getName() + ".position.x";
|
||||
private static final String KEY_POSITION_Y = CircularMenuWindow.class.getName() + ".position.y";
|
||||
|
||||
protected CircularMenuFloaty mFloaty;
|
||||
protected WindowManager mWindowManager;
|
||||
protected CircularActionMenu mCircularActionMenu;
|
||||
protected View mCircularActionView;
|
||||
protected BounceDragGesture mDragGesture;
|
||||
@@ -37,19 +36,19 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
private OrientationEventListener mOrientationEventListener;
|
||||
|
||||
public CircularMenuWindow(Context context, CircularMenuFloaty floaty) {
|
||||
this.mFloaty = floaty;
|
||||
mFloaty = floaty;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void onCreate(FloatyService service, WindowManager manager) {
|
||||
this.mWindowManager = manager;
|
||||
this.mActionViewWindowLayoutParams = this.createWindowLayoutParams();
|
||||
this.mMenuWindowLayoutParams = this.createWindowLayoutParams();
|
||||
this.inflateWindowViews(service);
|
||||
this.initWindowBridge();
|
||||
this.initGestures();
|
||||
this.setListeners();
|
||||
this.setInitialState();
|
||||
@Override
|
||||
protected void onCreateWindow(FloatyService service, WindowManager manager) {
|
||||
mActionViewWindowLayoutParams = createWindowLayoutParams();
|
||||
mMenuWindowLayoutParams = createWindowLayoutParams();
|
||||
inflateWindowViews(service);
|
||||
initWindowBridge();
|
||||
initGestures();
|
||||
setListeners();
|
||||
setInitialState();
|
||||
mOrientationEventListener = new OrientationEventListener(mContext) {
|
||||
@Override
|
||||
public void onOrientationChanged(int orientation) {
|
||||
@@ -63,6 +62,16 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onCreateView(FloatyService floatyService) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WindowManager.LayoutParams onCreateWindowLayoutParams() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void keepToSide() {
|
||||
mDragGesture.keepToEdge();
|
||||
}
|
||||
@@ -75,23 +84,22 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
}
|
||||
|
||||
private void initGestures() {
|
||||
this.mDragGesture = new BounceDragGesture(this.mActionViewWindowBridge, this.mCircularActionView);
|
||||
this.mDragGesture.setKeepToSideHiddenWidthRadio(this.mKeepToSideHiddenWidthRadio);
|
||||
this.mDragGesture.setPressedAlpha(this.mActiveAlpha);
|
||||
this.mDragGesture.setUnpressedAlpha(this.mInactiveAlpha);
|
||||
mDragGesture = new BounceDragGesture(mActionViewWindowBridge, mCircularActionView);
|
||||
mDragGesture.setKeepToSideHiddenWidthRadio(mKeepToSideHiddenWidthRadio);
|
||||
mDragGesture.setPressedAlpha(mActiveAlpha);
|
||||
mDragGesture.setUnpressedAlpha(mInactiveAlpha);
|
||||
}
|
||||
|
||||
private void initWindowBridge() {
|
||||
this.mActionViewWindowBridge = new OrientationAwareWindowBridge(this.mActionViewWindowLayoutParams, this.mWindowManager, this.mCircularActionView, mContext);
|
||||
this.mMenuWindowBridge = new WindowBridge.DefaultImpl(this.mMenuWindowLayoutParams, this.mWindowManager, this.mCircularActionMenu);
|
||||
mActionViewWindowBridge = new OrientationAwareWindowBridge(mActionViewWindowLayoutParams, getWindowManager(), mCircularActionView, mContext);
|
||||
mMenuWindowBridge = new WindowBridge.DefaultImpl(mMenuWindowLayoutParams, getWindowManager(), mCircularActionMenu);
|
||||
}
|
||||
|
||||
public void setKeepToSideHiddenWidthRadio(float keepToSideHiddenWidthRadio) {
|
||||
this.mKeepToSideHiddenWidthRadio = keepToSideHiddenWidthRadio;
|
||||
if (this.mDragGesture != null) {
|
||||
this.mDragGesture.setKeepToSideHiddenWidthRadio(this.mKeepToSideHiddenWidthRadio);
|
||||
mKeepToSideHiddenWidthRadio = keepToSideHiddenWidthRadio;
|
||||
if (mDragGesture != null) {
|
||||
mDragGesture.setKeepToSideHiddenWidthRadio(mKeepToSideHiddenWidthRadio);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams createWindowLayoutParams() {
|
||||
@@ -103,7 +111,7 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
}
|
||||
|
||||
private void setListeners() {
|
||||
this.setOnActionViewClickListener(v -> {
|
||||
setOnActionViewClickListener(v -> {
|
||||
if (isExpanded()) {
|
||||
collapse();
|
||||
} else {
|
||||
@@ -111,11 +119,11 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
}
|
||||
|
||||
});
|
||||
if (this.mActionViewOnClickListener != null) {
|
||||
this.mDragGesture.setOnDraggedViewClickListener(this.mActionViewOnClickListener);
|
||||
if (mActionViewOnClickListener != null) {
|
||||
mDragGesture.setOnDraggedViewClickListener(mActionViewOnClickListener);
|
||||
}
|
||||
|
||||
this.mCircularActionMenu.addOnStateChangeListener(new CircularActionMenu.OnStateChangeListenerAdapter() {
|
||||
mCircularActionMenu.addOnStateChangeListener(new CircularActionMenu.OnStateChangeListenerAdapter() {
|
||||
public void onCollapsed(CircularActionMenu menu) {
|
||||
mCircularActionView.setAlpha(mInactiveAlpha);
|
||||
}
|
||||
@@ -127,73 +135,73 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
}
|
||||
|
||||
public void setOnActionViewClickListener(View.OnClickListener listener) {
|
||||
if (this.mDragGesture == null) {
|
||||
this.mActionViewOnClickListener = listener;
|
||||
if (mDragGesture == null) {
|
||||
mActionViewOnClickListener = listener;
|
||||
} else {
|
||||
this.mDragGesture.setOnDraggedViewClickListener(listener);
|
||||
mDragGesture.setOnDraggedViewClickListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void expand() {
|
||||
this.mDragGesture.setEnabled(false);
|
||||
this.setMenuPositionAtActionView();
|
||||
if (this.mActionViewWindowBridge.getX() > this.mActionViewWindowBridge.getScreenWidth() / 2) {
|
||||
this.mCircularActionMenu.expand(3);
|
||||
mDragGesture.setEnabled(false);
|
||||
setMenuPositionAtActionView();
|
||||
if (mActionViewWindowBridge.getX() > mActionViewWindowBridge.getScreenWidth() / 2) {
|
||||
mCircularActionMenu.expand(3);
|
||||
} else {
|
||||
this.mCircularActionMenu.expand(5);
|
||||
mCircularActionMenu.expand(5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setActiveAlpha(float activeAlpha) {
|
||||
this.mActiveAlpha = activeAlpha;
|
||||
if (this.mDragGesture != null) {
|
||||
this.mDragGesture.setPressedAlpha(activeAlpha);
|
||||
mActiveAlpha = activeAlpha;
|
||||
if (mDragGesture != null) {
|
||||
mDragGesture.setPressedAlpha(activeAlpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setInactiveAlpha(float inactiveAlpha) {
|
||||
this.mInactiveAlpha = inactiveAlpha;
|
||||
if (this.mDragGesture != null) {
|
||||
this.mDragGesture.setUnpressedAlpha(this.mInactiveAlpha);
|
||||
mInactiveAlpha = inactiveAlpha;
|
||||
if (mDragGesture != null) {
|
||||
mDragGesture.setUnpressedAlpha(mInactiveAlpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void collapse() {
|
||||
this.mDragGesture.setEnabled(true);
|
||||
this.setMenuPositionAtActionView();
|
||||
this.mCircularActionMenu.collapse();
|
||||
this.mCircularActionView.setAlpha(this.mDragGesture.getUnpressedAlpha());
|
||||
mDragGesture.setEnabled(true);
|
||||
setMenuPositionAtActionView();
|
||||
mCircularActionMenu.collapse();
|
||||
mCircularActionView.setAlpha(mDragGesture.getUnpressedAlpha());
|
||||
}
|
||||
|
||||
public boolean isExpanded() {
|
||||
return this.mCircularActionMenu.isExpanded();
|
||||
return mCircularActionMenu.isExpanded();
|
||||
}
|
||||
|
||||
private void setMenuPositionAtActionView() {
|
||||
int y = this.mActionViewWindowBridge.getY() - this.mCircularActionMenu.getMeasuredHeight() / 2 + this.mCircularActionView.getMeasuredHeight() / 2;
|
||||
int y = mActionViewWindowBridge.getY() - mCircularActionMenu.getMeasuredHeight() / 2 + mCircularActionView.getMeasuredHeight() / 2;
|
||||
int x;
|
||||
if (this.mActionViewWindowBridge.getX() > this.mActionViewWindowBridge.getScreenWidth() / 2) {
|
||||
x = this.mActionViewWindowBridge.getX() - this.mCircularActionMenu.getExpandedWidth() + this.mCircularActionView.getMeasuredWidth() / 2;
|
||||
if (mActionViewWindowBridge.getX() > mActionViewWindowBridge.getScreenWidth() / 2) {
|
||||
x = mActionViewWindowBridge.getX() - mCircularActionMenu.getExpandedWidth() + mCircularActionView.getMeasuredWidth() / 2;
|
||||
} else {
|
||||
x = this.mActionViewWindowBridge.getX() - this.mCircularActionMenu.getExpandedWidth() + this.mCircularActionView.getMeasuredWidth();
|
||||
x = mActionViewWindowBridge.getX() - mCircularActionMenu.getExpandedWidth() + mCircularActionView.getMeasuredWidth();
|
||||
}
|
||||
|
||||
this.mMenuWindowBridge.updatePosition(x, y);
|
||||
mMenuWindowBridge.updatePosition(x, y);
|
||||
}
|
||||
|
||||
private void inflateWindowViews(FloatyService service) {
|
||||
this.mCircularActionMenu = this.mFloaty.inflateMenuItems(service, this);
|
||||
this.mCircularActionView = this.mFloaty.inflateActionView(service, this);
|
||||
this.mCircularActionMenu.setVisibility(View.GONE);
|
||||
this.mWindowManager.addView(this.mCircularActionMenu, this.mActionViewWindowLayoutParams);
|
||||
this.mWindowManager.addView(this.mCircularActionView, this.mMenuWindowLayoutParams);
|
||||
mCircularActionMenu = mFloaty.inflateMenuItems(service, this);
|
||||
mCircularActionView = mFloaty.inflateActionView(service, this);
|
||||
mCircularActionMenu.setVisibility(View.GONE);
|
||||
getWindowManager().addView(mCircularActionMenu, mActionViewWindowLayoutParams);
|
||||
getWindowManager().addView(mCircularActionView, mMenuWindowLayoutParams);
|
||||
}
|
||||
|
||||
public void onServiceDestroy(FloatyService floatyService) {
|
||||
this.close();
|
||||
close();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
@@ -202,10 +210,14 @@ public class CircularMenuWindow implements FloatyWindow {
|
||||
.putInt(KEY_POSITION_X, mActionViewWindowBridge.getX())
|
||||
.putInt(KEY_POSITION_Y, mActionViewWindowBridge.getY())
|
||||
.apply();
|
||||
try {
|
||||
mOrientationEventListener.disable();
|
||||
this.mWindowManager.removeView(this.mCircularActionMenu);
|
||||
this.mWindowManager.removeView(this.mCircularActionView);
|
||||
getWindowManager().removeView(mCircularActionMenu);
|
||||
getWindowManager().removeView(mCircularActionView);
|
||||
FloatyService.removeWindow(this);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,35 +11,16 @@ import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
* Created by Stardust on 2017/10/18.
|
||||
*/
|
||||
|
||||
public abstract class FullScreenFloatyWindow implements FloatyWindow {
|
||||
|
||||
private WindowManager mWindowManager;
|
||||
private WindowManager.LayoutParams mLayoutParams;
|
||||
private View mView;
|
||||
public abstract class FullScreenFloatyWindow extends FloatyWindow {
|
||||
|
||||
@Override
|
||||
public void onCreate(FloatyService floatyService, WindowManager windowManager) {
|
||||
mWindowManager = windowManager;
|
||||
mView = inflateView(floatyService);
|
||||
mLayoutParams = new WindowManager.LayoutParams(
|
||||
protected WindowManager.LayoutParams onCreateWindowLayoutParams() {
|
||||
return new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
FloatyWindowManger.getWindowType(),
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
mWindowManager.addView(mView, mLayoutParams);
|
||||
}
|
||||
|
||||
protected abstract View inflateView(FloatyService service);
|
||||
|
||||
@Override
|
||||
public void onServiceDestroy(FloatyService floatyService) {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mWindowManager.removeView(mView);
|
||||
FloatyService.removeWindow(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.autojs.autojs.ui.floating.gesture;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
|
||||
import com.stardust.enhancedfloaty.WindowBridge;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/9/26.
|
||||
*/
|
||||
|
||||
public class BounceDragGesture extends DragGesture {
|
||||
|
||||
private long mBounceDuration = 300;
|
||||
private static final int MIN_DY_TO_SCREEN_BOTTOM = 100;
|
||||
private static final int MIN_DY_TO_SCREEN_TOP = 0;
|
||||
private BounceInterpolator mBounceInterpolator;
|
||||
|
||||
public BounceDragGesture(WindowBridge windowBridge, View view) {
|
||||
super(windowBridge, view);
|
||||
setAutoKeepToEdge(true);
|
||||
mBounceInterpolator = new BounceInterpolator();
|
||||
}
|
||||
|
||||
public void setBounceDuration(long bounceDuration) {
|
||||
mBounceDuration = bounceDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent event) {
|
||||
return super.onDown(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keepToEdge() {
|
||||
int y = Math.min(mWindowBridge.getScreenHeight() - mView.getHeight() - MIN_DY_TO_SCREEN_BOTTOM, Math.max(MIN_DY_TO_SCREEN_TOP, mWindowBridge.getY()));
|
||||
int x = mWindowBridge.getX();
|
||||
int hiddenWidth = (int) (getKeepToSideHiddenWidthRadio() * (float) mView.getWidth());
|
||||
if (x > mWindowBridge.getScreenWidth() / 2) {
|
||||
bounce(x, mWindowBridge.getScreenWidth() - mView.getWidth() + hiddenWidth, y);
|
||||
} else {
|
||||
bounce(x, -hiddenWidth, y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void bounce(final int fromX, final int toX, final int y) {
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(fromX, toX);
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
mWindowBridge.updatePosition((int) ((float) animation.getAnimatedValue()), y);
|
||||
}
|
||||
});
|
||||
animator.setDuration(mBounceDuration);
|
||||
animator.setInterpolator(mBounceInterpolator);
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package org.autojs.autojs.ui.floating.gesture;
|
||||
|
||||
import android.support.v4.view.GestureDetectorCompat;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.enhancedfloaty.WindowBridge;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/18.
|
||||
*/
|
||||
|
||||
public class DragGesture extends GestureDetector.SimpleOnGestureListener {
|
||||
|
||||
protected WindowBridge mWindowBridge;
|
||||
protected View mView;
|
||||
|
||||
private float mKeepToSideHiddenWidthRadio = 0.5f;
|
||||
private int mInitialX;
|
||||
private int mInitialY;
|
||||
private float mInitialTouchX;
|
||||
private float mInitialTouchY;
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private boolean mAutoKeepToEdge;
|
||||
private float mPressedAlpha = 1.0f;
|
||||
private float mUnpressedAlpha = 0.4f;
|
||||
private boolean mEnabled = true;
|
||||
|
||||
public DragGesture(WindowBridge windowBridge, View view) {
|
||||
mWindowBridge = windowBridge;
|
||||
mView = view;
|
||||
setupView();
|
||||
}
|
||||
|
||||
private void setupView() {
|
||||
final GestureDetectorCompat gestureDetector = new GestureDetectorCompat(mView.getContext(), this);
|
||||
mView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
gestureDetector.onTouchEvent(event);
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
mView.setAlpha(mUnpressedAlpha);
|
||||
if (!onTheEdge() && mAutoKeepToEdge) {
|
||||
keepToEdge();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
mEnabled = enabled;
|
||||
}
|
||||
|
||||
protected boolean onTheEdge() {
|
||||
int dX1 = Math.abs(mWindowBridge.getX());
|
||||
int dX2 = Math.abs(mWindowBridge.getX() - mWindowBridge.getScreenWidth());
|
||||
return Math.min(dX1, dX2) < 5;
|
||||
}
|
||||
|
||||
public float getPressedAlpha() {
|
||||
return mPressedAlpha;
|
||||
}
|
||||
|
||||
public void setPressedAlpha(float pressedAlpha) {
|
||||
mPressedAlpha = pressedAlpha;
|
||||
}
|
||||
|
||||
public float getUnpressedAlpha() {
|
||||
return mUnpressedAlpha;
|
||||
}
|
||||
|
||||
public void setUnpressedAlpha(float unpressedAlpha) {
|
||||
mUnpressedAlpha = unpressedAlpha;
|
||||
}
|
||||
|
||||
public void setAutoKeepToEdge(boolean autoKeepToEdge) {
|
||||
mAutoKeepToEdge = autoKeepToEdge;
|
||||
}
|
||||
|
||||
public boolean isAutoKeepToEdge() {
|
||||
return mAutoKeepToEdge;
|
||||
}
|
||||
|
||||
public void setKeepToSideHiddenWidthRadio(float keepToSideHiddenWidthRadio) {
|
||||
mKeepToSideHiddenWidthRadio = keepToSideHiddenWidthRadio;
|
||||
}
|
||||
|
||||
public float getKeepToSideHiddenWidthRadio() {
|
||||
return mKeepToSideHiddenWidthRadio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent event) {
|
||||
mInitialX = mWindowBridge.getX();
|
||||
mInitialY = mWindowBridge.getY();
|
||||
mInitialTouchX = event.getRawX();
|
||||
mInitialTouchY = event.getRawY();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
||||
if (!mEnabled) {
|
||||
return false;
|
||||
}
|
||||
mWindowBridge.updatePosition(mInitialX + (int) ((e2.getRawX() - mInitialTouchX)),
|
||||
mInitialY + (int) ((e2.getRawY() - mInitialTouchY)));
|
||||
mView.setAlpha(mPressedAlpha);
|
||||
Log.d("DragGesture", "onScroll");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void keepToEdge() {
|
||||
int x = mWindowBridge.getX();
|
||||
int hiddenWidth = (int) (mKeepToSideHiddenWidthRadio * mView.getWidth());
|
||||
if (x > mWindowBridge.getScreenWidth() / 2)
|
||||
mWindowBridge.updatePosition(mWindowBridge.getScreenWidth() - mView.getWidth() + hiddenWidth, mWindowBridge.getY());
|
||||
else
|
||||
mWindowBridge.updatePosition(-hiddenWidth, mWindowBridge.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
if (mOnClickListener != null)
|
||||
mOnClickListener.onClick(mView);
|
||||
return super.onSingleTapConfirmed(e);
|
||||
}
|
||||
|
||||
public void setOnDraggedViewClickListener(View.OnClickListener onClickListener) {
|
||||
mOnClickListener = onClickListener;
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,14 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.afollestad.materialdialogs.Theme;
|
||||
import com.stardust.app.DialogUtils;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
|
||||
import org.autojs.autojs.R;
|
||||
import org.autojs.autojs.ui.codegeneration.CodeGenerateDialog;
|
||||
import org.autojs.autojs.ui.floating.FloatyWindowManger;
|
||||
import org.autojs.autojs.ui.floating.FullScreenFloatyWindow;
|
||||
|
||||
import com.stardust.view.accessibility.NodeInfo;
|
||||
|
||||
import org.autojs.autojs.ui.widget.BubblePopupMenu;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -39,8 +42,8 @@ public class LayoutBoundsFloatyWindow extends FullScreenFloatyWindow {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View inflateView(FloatyService service) {
|
||||
mContext = new ContextThemeWrapper(service, R.style.AppTheme);
|
||||
protected View onCreateView(FloatyService floatyService) {
|
||||
mContext = new ContextThemeWrapper(floatyService, R.style.AppTheme);
|
||||
mLayoutBoundsView = new LayoutBoundsView(mContext) {
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
@@ -51,11 +54,10 @@ public class LayoutBoundsFloatyWindow extends FullScreenFloatyWindow {
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
};
|
||||
setupView();
|
||||
return mLayoutBoundsView;
|
||||
}
|
||||
|
||||
private void setupView() {
|
||||
protected void onViewCreated(View v) {
|
||||
mLayoutBoundsView.setOnNodeInfoSelectListener(info -> {
|
||||
mSelectedNode = info;
|
||||
ensureOperationPopMenu();
|
||||
|
||||
@@ -44,8 +44,8 @@ public class LayoutHierarchyFloatyWindow extends FullScreenFloatyWindow {
|
||||
|
||||
|
||||
@Override
|
||||
protected View inflateView(FloatyService service) {
|
||||
mContext = new ContextThemeWrapper(service, R.style.AppTheme);
|
||||
protected View onCreateView(FloatyService floatyService) {
|
||||
mContext = new ContextThemeWrapper(floatyService, R.style.AppTheme);
|
||||
mLayoutHierarchyView = new LayoutHierarchyView(mContext) {
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
@@ -56,11 +56,11 @@ public class LayoutHierarchyFloatyWindow extends FullScreenFloatyWindow {
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
};
|
||||
setupView();
|
||||
return mLayoutHierarchyView;
|
||||
}
|
||||
|
||||
private void setupView() {
|
||||
@Override
|
||||
protected void onViewCreated(View v) {
|
||||
mLayoutHierarchyView.setBackgroundColor(COLOR_SHADOW);
|
||||
mLayoutHierarchyView.setShowClickedNodeBounds(true);
|
||||
mLayoutHierarchyView.getBoundsPaint().setStrokeWidth(3);
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.autojs.autojs.ui.BaseActivity;
|
||||
import org.androidannotations.annotations.AfterViews;
|
||||
import org.androidannotations.annotations.EActivity;
|
||||
import org.androidannotations.annotations.ViewById;
|
||||
import org.autojs.autojs.workground.WrapContentGridLayoutManger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -57,7 +58,9 @@ public class ShortcutIconSelectActivity extends BaseActivity {
|
||||
|
||||
private void setupApps() {
|
||||
mApps.setAdapter(new AppsAdapter());
|
||||
mApps.setLayoutManager(new GridLayoutManager(this, 5));
|
||||
WrapContentGridLayoutManger manager = new WrapContentGridLayoutManger(this, 2);
|
||||
manager.setDebugInfo("IconSelectView");
|
||||
mApps.setLayoutManager(manager);
|
||||
loadApps();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.autojs.autojs.workground;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tencent.bugly.crashreport.BuglyLog;
|
||||
|
||||
public class WrapContentGridLayoutManger extends GridLayoutManager {
|
||||
|
||||
private String mDebugInfo;
|
||||
|
||||
public WrapContentGridLayoutManger(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public WrapContentGridLayoutManger(Context context, int spanCount) {
|
||||
super(context, spanCount);
|
||||
}
|
||||
|
||||
public WrapContentGridLayoutManger(Context context, int spanCount, int orientation, boolean reverseLayout) {
|
||||
super(context, spanCount, orientation, reverseLayout);
|
||||
}
|
||||
|
||||
public void setDebugInfo(String debugInfo) {
|
||||
mDebugInfo = debugInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
try {
|
||||
super.onLayoutChildren(recycler, state);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
BuglyLog.e("GridLayoutManager", "Android bug: debug info = " + mDebugInfo, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.stardust.floatingcircularactionmenu.CircularActionMenu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.autojs.autojs.ui.floating.CircularActionMenu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -60,4 +60,4 @@
|
||||
android:src="@drawable/ic_circular_menu_settings"/>
|
||||
|
||||
|
||||
</com.stardust.floatingcircularactionmenu.CircularActionMenu>
|
||||
</org.autojs.autojs.ui.floating.CircularActionMenu>
|
||||
@@ -27,4 +27,9 @@
|
||||
<attr name="title"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="CircularActionMenu">
|
||||
<attr name="cam_radius" format="dimension|reference"/>
|
||||
<attr name="cam_angle" format="integer"/>
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
@@ -46,7 +46,7 @@ dependencies {
|
||||
exclude group: 'com.android.support'
|
||||
})
|
||||
api 'com.android.support:design:28.0.0'
|
||||
api 'com.github.hyb1996:EnhancedFloaty:0.21'
|
||||
api 'com.github.hyb1996:EnhancedFloaty:0.31'
|
||||
api 'com.github.hyb1996:OpenCvLib:2.4.13.4-imgproc'
|
||||
api 'com.makeramen:roundedimageview:2.3.0'
|
||||
// OkHttp
|
||||
|
||||
@@ -37,15 +37,6 @@ public class BaseResizableFloatyWindow extends ResizableFloatyWindow {
|
||||
|
||||
private VolatileDispose<RuntimeException> mInflateException = new VolatileDispose<>();
|
||||
private View mCloseButton;
|
||||
private static final String TAG = "ResizableFloatyWindow";
|
||||
private WindowManager mWindowManager;
|
||||
private WindowManager.LayoutParams mWindowLayoutParams;
|
||||
private ViewGroup mWindowView;
|
||||
private View mRootView;
|
||||
private View mResizer;
|
||||
private View mMoveCursor;
|
||||
private WindowBridge mWindowBridge;
|
||||
private MyFloaty mFloaty;
|
||||
|
||||
|
||||
public BaseResizableFloatyWindow(Context context, ViewSupplier viewSupplier) {
|
||||
@@ -54,7 +45,6 @@ public class BaseResizableFloatyWindow extends ResizableFloatyWindow {
|
||||
|
||||
private BaseResizableFloatyWindow(MyFloaty floaty) {
|
||||
super(floaty);
|
||||
mFloaty = floaty;
|
||||
}
|
||||
|
||||
public RuntimeException waitForCreation() {
|
||||
@@ -63,20 +53,12 @@ public class BaseResizableFloatyWindow extends ResizableFloatyWindow {
|
||||
|
||||
@Override
|
||||
public void onCreate(FloatyService service, WindowManager manager) {
|
||||
this.mWindowManager = manager;
|
||||
this.mWindowLayoutParams = this.createWindowLayoutParams();
|
||||
if (this.mFloaty == null) {
|
||||
throw new IllegalStateException("Must start this service by static method ResizableExpandableFloatyWindow.startService");
|
||||
} else {
|
||||
try {
|
||||
this.initWindowView(service);
|
||||
super.onCreate(service, manager);
|
||||
} catch (RuntimeException e) {
|
||||
mInflateException.setAndNotify(e);
|
||||
return;
|
||||
}
|
||||
this.mWindowBridge = new WindowBridge.DefaultImpl(this.mWindowLayoutParams, this.mWindowManager, this.mWindowView);
|
||||
this.initGesture();
|
||||
}
|
||||
mInflateException.setAndNotify(Exceptions.NO_EXCEPTION);
|
||||
}
|
||||
|
||||
@@ -86,88 +68,37 @@ public class BaseResizableFloatyWindow extends ResizableFloatyWindow {
|
||||
|
||||
public void setAdjustEnabled(boolean enabled) {
|
||||
if (!enabled) {
|
||||
mMoveCursor.setVisibility(View.GONE);
|
||||
mResizer.setVisibility(View.GONE);
|
||||
getMoveCursor().setVisibility(View.GONE);
|
||||
getResizer().setVisibility(View.GONE);
|
||||
mCloseButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
mMoveCursor.setVisibility(View.VISIBLE);
|
||||
mResizer.setVisibility(View.VISIBLE);
|
||||
getMoveCursor().setVisibility(View.VISIBLE);
|
||||
getResizer().setVisibility(View.VISIBLE);
|
||||
mCloseButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAdjustEnabled() {
|
||||
return mMoveCursor.getVisibility() == View.VISIBLE;
|
||||
return getMoveCursor().getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
public View getRootView() {
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
private void initWindowView(FloatyService service) {
|
||||
this.mWindowView = (ViewGroup) View.inflate(service, com.stardust.lib.R.layout.ef_floaty_container, (ViewGroup) null);
|
||||
this.mRootView = this.mFloaty.inflateView(service, this);
|
||||
this.mResizer = this.mFloaty.getResizerView(this.mRootView);
|
||||
this.mMoveCursor = this.mFloaty.getMoveCursorView(this.mRootView);
|
||||
this.mCloseButton = mRootView.findViewById(R.id.close);
|
||||
android.view.ViewGroup.LayoutParams params = new android.view.ViewGroup.LayoutParams(-2, -2);
|
||||
this.mWindowView.addView(this.mRootView, params);
|
||||
this.mWindowView.setFocusableInTouchMode(true);
|
||||
this.mWindowManager.addView(this.mWindowView, this.mWindowLayoutParams);
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams createWindowLayoutParams() {
|
||||
int type;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
} else {
|
||||
type = WindowManager.LayoutParams.TYPE_PHONE;
|
||||
}
|
||||
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
type,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
layoutParams.gravity = Gravity.TOP | Gravity.START;
|
||||
return layoutParams;
|
||||
@Override
|
||||
protected void onViewCreated(View view) {
|
||||
super.onViewCreated(view);
|
||||
mCloseButton = view.findViewById(R.id.close);
|
||||
}
|
||||
|
||||
public void disableWindowFocus() {
|
||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams();
|
||||
windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
updateWindowLayoutParams(windowLayoutParams);
|
||||
}
|
||||
|
||||
public void requestWindowFocus() {
|
||||
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
mWindowView.requestFocus();
|
||||
}
|
||||
|
||||
|
||||
private void initGesture() {
|
||||
if (this.mResizer != null) {
|
||||
ResizeGesture.enableResize(this.mResizer, this.mRootView, this.mWindowBridge);
|
||||
}
|
||||
|
||||
if (this.mMoveCursor != null) {
|
||||
DragGesture gesture = new DragGesture(this.mWindowBridge, this.mMoveCursor);
|
||||
gesture.setPressedAlpha(1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
public WindowBridge getWindowBridge() {
|
||||
return this.mWindowBridge;
|
||||
}
|
||||
|
||||
public void onServiceDestroy(FloatyService service) {
|
||||
this.close();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (mWindowView != null)
|
||||
this.mWindowManager.removeView(this.mWindowView);
|
||||
FloatyService.removeWindow(this);
|
||||
WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams();
|
||||
windowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
updateWindowLayoutParams(windowLayoutParams);
|
||||
getWindowView().requestLayout();
|
||||
}
|
||||
|
||||
private static class MyFloaty implements ResizableFloaty {
|
||||
@@ -185,7 +116,7 @@ public class BaseResizableFloatyWindow extends ResizableFloatyWindow {
|
||||
@Override
|
||||
public View inflateView(FloatyService floatyService, ResizableFloatyWindow resizableFloatyWindow) {
|
||||
mRootView = View.inflate(mContext, R.layout.floaty_window, null);
|
||||
FrameLayout container = (FrameLayout) mRootView.findViewById(R.id.container);
|
||||
FrameLayout container = mRootView.findViewById(R.id.container);
|
||||
View contentView = mContentViewSupplier.inflate(mContext, container);
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,10 @@ import com.stardust.concurrent.VolatileDispose;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
import com.stardust.enhancedfloaty.WindowBridge;
|
||||
import com.stardust.enhancedfloaty.util.WindowTypeCompat;
|
||||
|
||||
public class RawWindow extends FloatyWindow {
|
||||
|
||||
public class RawWindow implements FloatyWindow {
|
||||
|
||||
|
||||
public interface RawFloaty {
|
||||
@@ -24,13 +26,9 @@ public class RawWindow implements FloatyWindow {
|
||||
View inflateWindowView(FloatyService service, ViewGroup parent);
|
||||
}
|
||||
|
||||
private WindowBridge mWindowBridge;
|
||||
private VolatileDispose<RuntimeException> mInflateException = new VolatileDispose<>();
|
||||
private WindowManager mWindowManager;
|
||||
private ViewGroup mWindowView;
|
||||
private View mWindowContent;
|
||||
private RawFloaty mRawFloaty;
|
||||
private WindowManager.LayoutParams mWindowLayoutParams;
|
||||
private View mContentView;
|
||||
|
||||
public RawWindow(RawFloaty rawFloaty) {
|
||||
mRawFloaty = rawFloaty;
|
||||
@@ -38,26 +36,32 @@ public class RawWindow implements FloatyWindow {
|
||||
|
||||
@Override
|
||||
public void onCreate(FloatyService floatyService, WindowManager windowManager) {
|
||||
mWindowManager = windowManager;
|
||||
mWindowView = (ViewGroup) View.inflate(floatyService, R.layout.raw_window, null);
|
||||
mWindowLayoutParams = createWindowLayoutParams();
|
||||
try {
|
||||
mWindowContent = mRawFloaty.inflateWindowView(floatyService, mWindowView);
|
||||
mWindowManager.addView(mWindowView, mWindowLayoutParams);
|
||||
super.onCreate(floatyService, windowManager);
|
||||
} catch (RuntimeException e) {
|
||||
mInflateException.setAndNotify(e);
|
||||
return;
|
||||
}
|
||||
mWindowBridge = new WindowBridge.DefaultImpl(mWindowLayoutParams, windowManager, mWindowView);
|
||||
mInflateException.setAndNotify(Exceptions.NO_EXCEPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onCreateView(FloatyService floatyService) {
|
||||
ViewGroup windowView = (ViewGroup) View.inflate(floatyService, R.layout.raw_window, null);
|
||||
mContentView = mRawFloaty.inflateWindowView(floatyService, windowView);
|
||||
return windowView;
|
||||
}
|
||||
|
||||
public RuntimeException waitForCreation() {
|
||||
return mInflateException.blockedGetOrThrow(ScriptInterruptedException.class);
|
||||
}
|
||||
|
||||
public View getContentView() {
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
protected WindowManager.LayoutParams createWindowLayoutParams() {
|
||||
@Override
|
||||
protected WindowManager.LayoutParams onCreateWindowLayoutParams() {
|
||||
int flags =
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
@@ -66,64 +70,37 @@ public class RawWindow implements FloatyWindow {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
|
||||
}
|
||||
int type;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
} else {
|
||||
type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
|
||||
}
|
||||
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
type,
|
||||
WindowTypeCompat.getWindowType(),
|
||||
flags,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
layoutParams.gravity = Gravity.TOP | Gravity.START;
|
||||
return layoutParams;
|
||||
}
|
||||
|
||||
|
||||
public void disableWindowFocus() {
|
||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams();
|
||||
windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
updateWindowLayoutParams(windowLayoutParams);
|
||||
}
|
||||
|
||||
public void requestWindowFocus() {
|
||||
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
mWindowView.requestFocus();
|
||||
WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams();
|
||||
windowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
updateWindowLayoutParams(windowLayoutParams);
|
||||
getWindowView().requestLayout();
|
||||
}
|
||||
|
||||
public void setTouchable(boolean touchable) {
|
||||
WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams();
|
||||
if (touchable) {
|
||||
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
windowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
} else {
|
||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
}
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
updateWindowLayoutParams(windowLayoutParams);
|
||||
}
|
||||
|
||||
public WindowBridge getWindowBridge() {
|
||||
return mWindowBridge;
|
||||
}
|
||||
|
||||
public ViewGroup getWindowView() {
|
||||
return mWindowView;
|
||||
}
|
||||
|
||||
public View getWindowContent() {
|
||||
return mWindowContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDestroy(FloatyService floatyService) {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (mWindowView != null)
|
||||
mWindowManager.removeView(mWindowView);
|
||||
FloatyService.removeWindow(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,15 @@ public class JsGridView extends JsListView {
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
setLayoutManager(new GridLayoutManager(getContext(), 1));
|
||||
setLayoutManager(new GridLayoutManager(getContext(), 1){
|
||||
@Override
|
||||
public void onLayoutChildren(Recycler recycler, State state) {
|
||||
try {
|
||||
super.onLayoutChildren(recycler, state);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
getScriptRuntime().console.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,9 @@ public class JsListView extends RecyclerView {
|
||||
setLayoutManager(new WrapContentLinearLayoutManager(getContext()));
|
||||
}
|
||||
|
||||
protected ScriptRuntime getScriptRuntime() {
|
||||
return mScriptRuntime;
|
||||
}
|
||||
|
||||
public void setOnItemTouchListener(OnItemTouchListener onItemTouchListener) {
|
||||
mOnItemTouchListener = onItemTouchListener;
|
||||
|
||||
@@ -1,99 +1,21 @@
|
||||
package com.stardust.autojs.core.ui.widget;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.stardust.autojs.core.eventloop.EventEmitter;
|
||||
import com.stardust.autojs.core.ui.JsEvent;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Dimensions;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Drawables;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Gravities;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Ids;
|
||||
import com.stardust.autojs.core.ui.xview.ViewAttributes;
|
||||
import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype;
|
||||
|
||||
import org.mozilla.javascript.NativeJavaMethod;
|
||||
import org.mozilla.javascript.NativeJavaObject;
|
||||
import org.mozilla.javascript.ScriptRuntime;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.Undefined;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class NativeView extends NativeJavaObjectWithPrototype {
|
||||
|
||||
protected interface Attribute {
|
||||
String get();
|
||||
|
||||
void set(String value);
|
||||
}
|
||||
|
||||
|
||||
protected class BaseAttribute implements Attribute {
|
||||
|
||||
private String mValue;
|
||||
private final AttributeSetter mAttributeSetter;
|
||||
|
||||
public BaseAttribute(AttributeSetter attributeSetter) {
|
||||
mAttributeSetter = attributeSetter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String value) {
|
||||
mValue = value;
|
||||
mAttributeSetter.set(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected interface AttributeGetter {
|
||||
String get();
|
||||
}
|
||||
|
||||
|
||||
protected interface AttributeSetter {
|
||||
void set(String value);
|
||||
}
|
||||
|
||||
protected interface ValueConverter<T> {
|
||||
T convert(String value);
|
||||
}
|
||||
|
||||
protected interface ValueApplier<T> {
|
||||
void apply(T value);
|
||||
}
|
||||
|
||||
protected static class MappingAttributeSetter<T> implements AttributeSetter {
|
||||
|
||||
private final ValueConverter<T> mValueConverter;
|
||||
private final ValueApplier<T> mValueApplier;
|
||||
|
||||
public MappingAttributeSetter(ValueConverter<T> valueConverter, ValueApplier<T> valueApplier) {
|
||||
mValueConverter = valueConverter;
|
||||
mValueApplier = valueApplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String value) {
|
||||
mValueApplier.apply(mValueConverter.convert(value));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScrollEvent {
|
||||
public int scrollX;
|
||||
public int scrollY;
|
||||
@@ -109,17 +31,14 @@ public class NativeView extends NativeJavaObjectWithPrototype {
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Attribute> mAttributes = new HashMap<>();
|
||||
private final com.stardust.autojs.runtime.ScriptRuntime mRuntime;
|
||||
private final Drawables mDrawables;
|
||||
private final ViewAttributes mViewAttributes;
|
||||
private final View mView;
|
||||
private final EventEmitter mEventEmitter;
|
||||
private final NativeJavaObject mNativeEventEmitter;
|
||||
|
||||
public NativeView(Scriptable scope, View javaObject, Class<?> staticType, com.stardust.autojs.runtime.ScriptRuntime runtime) {
|
||||
super(scope, javaObject, staticType);
|
||||
mRuntime = runtime;
|
||||
mDrawables = mRuntime.ui.getResourceParser().getDrawables();
|
||||
mViewAttributes = ViewAttributes.fromView(runtime.ui.getResourceParser(), javaObject);
|
||||
mEventEmitter = runtime.events.emitter();
|
||||
mView = javaObject;
|
||||
mNativeEventEmitter = new NativeJavaObject(scope, mEventEmitter, mEventEmitter.getClass());
|
||||
@@ -129,7 +48,6 @@ public class NativeView extends NativeJavaObjectWithPrototype {
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void init() {
|
||||
onRegisterAttrs();
|
||||
mView.setOnTouchListener((v, event) -> {
|
||||
JsEvent e = new JsEvent(getParentScope(), event, event.getClass());
|
||||
emit("touch", e, v);
|
||||
@@ -152,34 +70,10 @@ public class NativeView extends NativeJavaObjectWithPrototype {
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
protected void onRegisterAttrs() {
|
||||
registerAttr("id", Ids::parse, mView::setId);
|
||||
registerAttr("gravity", Gravities::parse, this::setGravity);
|
||||
registerAttrs(new String[]{"width", "layout_width", "w"}, this::parseDimension, this::setWidth);
|
||||
registerAttrs(new String[]{"height", "layout_height", "h"}, this::parseDimension, this::setHeight);
|
||||
registerDrawableAttrs(new String[]{"bg", "background"}, mView::setBackground);
|
||||
registerAttr("layout_gravity", Gravities::parse, this::setLayoutGravity);
|
||||
registerAttr("layout_weight", Float::parseFloat, this::setLayoutWeight);
|
||||
}
|
||||
|
||||
|
||||
private int parseDimension(String dim) {
|
||||
switch (dim) {
|
||||
case "wrap_content":
|
||||
return ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
case "fill_parent":
|
||||
case "match_parent":
|
||||
return ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
default:
|
||||
return Dimensions.parseToPixel(dim, mView.getResources().getDisplayMetrics(), (ViewGroup) mView.getParent(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean has(String name, Scriptable start) {
|
||||
if (mAttributes.containsKey(name)) {
|
||||
if (mViewAttributes.contains(name)) {
|
||||
return true;
|
||||
}
|
||||
return super.has(name, start) || mNativeEventEmitter.has(name, start);
|
||||
@@ -187,7 +81,7 @@ public class NativeView extends NativeJavaObjectWithPrototype {
|
||||
|
||||
@Override
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
Attribute attribute = mAttributes.get(name);
|
||||
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
|
||||
if (attribute != null) {
|
||||
attribute.set(ScriptRuntime.toString(value));
|
||||
return;
|
||||
@@ -201,7 +95,7 @@ public class NativeView extends NativeJavaObjectWithPrototype {
|
||||
|
||||
@Override
|
||||
public Object get(String name, Scriptable start) {
|
||||
Attribute attribute = mAttributes.get(name);
|
||||
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
|
||||
if (attribute != null) {
|
||||
return attribute.get();
|
||||
}
|
||||
@@ -212,116 +106,6 @@ public class NativeView extends NativeJavaObjectWithPrototype {
|
||||
return super.get(name, start);
|
||||
}
|
||||
|
||||
protected void registerAttr(String name, Attribute attribute) {
|
||||
mAttributes.put(name, attribute);
|
||||
}
|
||||
|
||||
protected void registerAttr(String name, AttributeGetter getter, AttributeSetter setter) {
|
||||
mAttributes.put(name, new Attribute() {
|
||||
@Override
|
||||
public String get() {
|
||||
return getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String value) {
|
||||
setter.set(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void registerAttr(String name, AttributeSetter setter) {
|
||||
mAttributes.put(name, new BaseAttribute(setter));
|
||||
}
|
||||
|
||||
protected <T> void registerAttr(String name, ValueConverter<T> converter, ValueApplier<T> applier) {
|
||||
mAttributes.put(name, new BaseAttribute(new MappingAttributeSetter<>(converter, applier)));
|
||||
}
|
||||
|
||||
protected <T> void registerAttrs(String[] names, ValueConverter<T> converter, ValueApplier<T> applier) {
|
||||
registerAttrs(names, new MappingAttributeSetter<>(converter, applier));
|
||||
}
|
||||
|
||||
protected <T> void registerAttrs(String[] names, AttributeSetter setter) {
|
||||
registerAttrs(names, new BaseAttribute(setter));
|
||||
}
|
||||
|
||||
protected <T> void registerAttrs(String[] names, Attribute attribute) {
|
||||
for (String name : names) {
|
||||
mAttributes.put(name, attribute);
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerDrawableAttr(String name, ValueApplier<Drawable> applier) {
|
||||
mAttributes.put(name, new BaseAttribute(new MappingAttributeSetter<>(
|
||||
this::parseDrawable, applier)));
|
||||
}
|
||||
|
||||
|
||||
private void registerDrawableAttrs(String[] names, ValueApplier<Drawable> applier) {
|
||||
registerAttrs(names, new BaseAttribute(new MappingAttributeSetter<>(
|
||||
this::parseDrawable, applier)));
|
||||
}
|
||||
|
||||
|
||||
protected Drawable parseDrawable(String value) {
|
||||
return mDrawables.parse(mView, value);
|
||||
}
|
||||
|
||||
private boolean setGravity(int g) {
|
||||
try {
|
||||
Method setGravity = mView.getClass().getMethod("setGravity", int.class);
|
||||
setGravity.invoke(mView, g);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setLayoutGravity(int gravity) {
|
||||
ViewParent parent = mView.getParent();
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
if (parent instanceof LinearLayout) {
|
||||
((LinearLayout.LayoutParams) layoutParams).gravity = gravity;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
} else if (parent instanceof FrameLayout) {
|
||||
((FrameLayout.LayoutParams) layoutParams).gravity = gravity;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
} else {
|
||||
try {
|
||||
Field field = layoutParams.getClass().getField("gravity");
|
||||
field.set(layoutParams, gravity);
|
||||
mView.setLayoutParams(layoutParams);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//TODO throw or ?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setLayoutWeight(float weight) {
|
||||
ViewParent parent = mView.getParent();
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
if (parent instanceof LinearLayout) {
|
||||
((LinearLayout.LayoutParams) layoutParams).weight = weight;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setWidth(int width) {
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
layoutParams.width = width;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
|
||||
private void setHeight(int height) {
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
layoutParams.height = height;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View unwrap() {
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
package com.stardust.autojs.core.ui.xview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.stardust.autojs.R;
|
||||
import com.stardust.autojs.core.ui.inflater.ResourceParser;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Dimensions;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Drawables;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Gravities;
|
||||
import com.stardust.autojs.core.ui.inflater.util.Ids;
|
||||
import com.stardust.autojs.core.ui.widget.NativeView;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ViewAttributes {
|
||||
|
||||
public interface Attribute {
|
||||
String get();
|
||||
|
||||
void set(String value);
|
||||
}
|
||||
|
||||
|
||||
protected class BaseAttribute implements Attribute {
|
||||
|
||||
private String mValue;
|
||||
private final AttributeSetter mAttributeSetter;
|
||||
|
||||
public BaseAttribute(AttributeSetter attributeSetter) {
|
||||
mAttributeSetter = attributeSetter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String value) {
|
||||
mValue = value;
|
||||
mAttributeSetter.set(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected interface AttributeGetter {
|
||||
String get();
|
||||
}
|
||||
|
||||
|
||||
protected interface AttributeSetter {
|
||||
void set(String value);
|
||||
}
|
||||
|
||||
protected interface ValueConverter<T> {
|
||||
T convert(String value);
|
||||
}
|
||||
|
||||
protected interface ValueApplier<T> {
|
||||
void apply(T value);
|
||||
}
|
||||
|
||||
protected static class MappingAttributeSetter<T> implements AttributeSetter {
|
||||
|
||||
private final ValueConverter<T> mValueConverter;
|
||||
private final ValueApplier<T> mValueApplier;
|
||||
|
||||
public MappingAttributeSetter(ValueConverter<T> valueConverter, ValueApplier<T> valueApplier) {
|
||||
mValueConverter = valueConverter;
|
||||
mValueApplier = valueApplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String value) {
|
||||
mValueApplier.apply(mValueConverter.convert(value));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Attribute> mAttributes = new HashMap<>();
|
||||
private final Drawables mDrawables;
|
||||
private final View mView;
|
||||
|
||||
public ViewAttributes(Drawables drawables, View view) {
|
||||
mDrawables = drawables;
|
||||
mView = view;
|
||||
init();
|
||||
}
|
||||
|
||||
public static ViewAttributes fromView(ResourceParser parser, View view) {
|
||||
ViewAttributes attributes;
|
||||
Object tag = view.getTag(R.id.view_tag_view_attrs);
|
||||
if (!(tag instanceof ViewAttributes)) {
|
||||
attributes = new ViewAttributes(parser.getDrawables(), view);
|
||||
view.setTag(R.id.view_tag_view_attrs, attributes);
|
||||
} else {
|
||||
attributes = (ViewAttributes) tag;
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
|
||||
public boolean contains(String name) {
|
||||
return mAttributes.containsKey(name);
|
||||
}
|
||||
|
||||
public Attribute get(String name) {
|
||||
return mAttributes.get(name);
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void init() {
|
||||
onRegisterAttrs();
|
||||
}
|
||||
|
||||
|
||||
@CallSuper
|
||||
protected void onRegisterAttrs() {
|
||||
registerAttr("id", Ids::parse, mView::setId);
|
||||
registerAttr("gravity", Gravities::parse, this::setGravity);
|
||||
registerAttrs(new String[]{"width", "layout_width", "w"}, this::parseDimension, this::setWidth);
|
||||
registerAttrs(new String[]{"height", "layout_height", "h"}, this::parseDimension, this::setHeight);
|
||||
registerDrawableAttrs(new String[]{"bg", "background"}, mView::setBackground);
|
||||
registerAttr("layout_gravity", Gravities::parse, this::setLayoutGravity);
|
||||
registerAttr("layout_weight", Float::parseFloat, this::setLayoutWeight);
|
||||
}
|
||||
|
||||
|
||||
private int parseDimension(String dim) {
|
||||
switch (dim) {
|
||||
case "wrap_content":
|
||||
return ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
case "fill_parent":
|
||||
case "match_parent":
|
||||
return ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
default:
|
||||
return Dimensions.parseToPixel(dim, mView.getResources().getDisplayMetrics(), (ViewGroup) mView.getParent(), true);
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerAttr(String name, Attribute attribute) {
|
||||
mAttributes.put(name, attribute);
|
||||
}
|
||||
|
||||
protected void registerAttr(String name, AttributeGetter getter, AttributeSetter setter) {
|
||||
mAttributes.put(name, new Attribute() {
|
||||
@Override
|
||||
public String get() {
|
||||
return getter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String value) {
|
||||
setter.set(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void registerAttr(String name, AttributeSetter setter) {
|
||||
mAttributes.put(name, new BaseAttribute(setter));
|
||||
}
|
||||
|
||||
protected <T> void registerAttr(String name, ValueConverter<T> converter, ValueApplier<T> applier) {
|
||||
mAttributes.put(name, new BaseAttribute(new MappingAttributeSetter<>(converter, applier)));
|
||||
}
|
||||
|
||||
protected <T> void registerAttrs(String[] names, ValueConverter<T> converter, ValueApplier<T> applier) {
|
||||
registerAttrs(names, new MappingAttributeSetter<>(converter, applier));
|
||||
}
|
||||
|
||||
protected <T> void registerAttrs(String[] names, AttributeSetter setter) {
|
||||
registerAttrs(names, new BaseAttribute(setter));
|
||||
}
|
||||
|
||||
protected <T> void registerAttrs(String[] names, Attribute attribute) {
|
||||
for (String name : names) {
|
||||
mAttributes.put(name, attribute);
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerDrawableAttr(String name, ValueApplier<Drawable> applier) {
|
||||
mAttributes.put(name, new BaseAttribute(new MappingAttributeSetter<>(
|
||||
this::parseDrawable, applier)));
|
||||
}
|
||||
|
||||
|
||||
private void registerDrawableAttrs(String[] names, ValueApplier<Drawable> applier) {
|
||||
registerAttrs(names, new BaseAttribute(new MappingAttributeSetter<>(
|
||||
this::parseDrawable, applier)));
|
||||
}
|
||||
|
||||
|
||||
protected Drawable parseDrawable(String value) {
|
||||
return mDrawables.parse(mView, value);
|
||||
}
|
||||
|
||||
private boolean setGravity(int g) {
|
||||
try {
|
||||
Method setGravity = mView.getClass().getMethod("setGravity", int.class);
|
||||
setGravity.invoke(mView, g);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setLayoutGravity(int gravity) {
|
||||
ViewParent parent = mView.getParent();
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
if (parent instanceof LinearLayout) {
|
||||
((LinearLayout.LayoutParams) layoutParams).gravity = gravity;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
} else if (parent instanceof FrameLayout) {
|
||||
((FrameLayout.LayoutParams) layoutParams).gravity = gravity;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
} else {
|
||||
try {
|
||||
Field field = layoutParams.getClass().getField("gravity");
|
||||
field.set(layoutParams, gravity);
|
||||
mView.setLayoutParams(layoutParams);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//TODO throw or ?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setLayoutWeight(float weight) {
|
||||
ViewParent parent = mView.getParent();
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
if (parent instanceof LinearLayout) {
|
||||
((LinearLayout.LayoutParams) layoutParams).weight = weight;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setWidth(int width) {
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
layoutParams.width = width;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
|
||||
private void setHeight(int height) {
|
||||
ViewGroup.LayoutParams layoutParams = mView.getLayoutParams();
|
||||
layoutParams.height = height;
|
||||
mView.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public class Floaty {
|
||||
}
|
||||
|
||||
public View findView(String id) {
|
||||
return JsViewHelper.findViewByStringId(mWindow.getWindowContent(), id);
|
||||
return JsViewHelper.findViewByStringId(mWindow.getContentView(), id);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
|
||||
4
autojs/src/main/res/values/ids.xml
Normal file
4
autojs/src/main/res/values/ids.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="view_tag_view_attrs" type="id"/>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user