This commit is contained in:
hyb1996
2018-10-12 14:51:45 +08:00
27 changed files with 974 additions and 473 deletions

View File

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

View File

@@ -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,19 +53,11 @@ 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);
} catch (RuntimeException e) {
mInflateException.setAndNotify(e);
return;
}
this.mWindowBridge = new WindowBridge.DefaultImpl(this.mWindowLayoutParams, this.mWindowManager, this.mWindowView);
this.initGesture();
try {
super.onCreate(service, manager);
} catch (RuntimeException e) {
mInflateException.setAndNotify(e);
return;
}
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;
}

View File

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

View File

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

View File

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

View File

@@ -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,127 +95,17 @@ 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();
}
Object o = mNativeEventEmitter.get(name, start);
if(o != Scriptable.NOT_FOUND){
if (o != Scriptable.NOT_FOUND) {
return o;
}
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() {

View File

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

View File

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

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="view_tag_view_attrs" type="id"/>
</resources>