sample: 自定义控件; fix: ActivityNotFoundException

This commit is contained in:
hyb1996
2018-10-14 10:33:23 +08:00
parent db3571851c
commit 14b7a7e85e
39 changed files with 615 additions and 220 deletions

View File

@@ -3,17 +3,23 @@ module.exports = function(runtime, global){
var floaty = {};
floaty.window = function(layout){
if(typeof(layout) == 'xml'){
layout = layout.toXMLString();
if(typeof(xml) == 'xml'){
xml = xml.toXMLString();
}
return wrap(runtime.floaty.window(layout));
return wrap(runtime.floaty.window(function(context, parent){
runtime.ui.layoutInflater.setContext(context);
return ui.__inflate__(runtime.ui.layoutInflater.inflate(xml.toString(), parent, true));
}));
}
floaty.rawWindow = function(layout){
if(typeof(layout) == 'xml'){
layout = layout.toXMLString();
if(typeof(xml) == 'xml'){
xml = xml.toXMLString();
}
return wrap(runtime.floaty.rawWindow(layout));
return wrap(runtime.floaty.rawWindow(function(context, parent){
runtime.ui.layoutInflater.setContext(context);
return ui.__inflate__(runtime.ui.layoutInflater.inflate(xml.toString(), parent, true));
}));
}
function wrap(window){

View File

@@ -46,4 +46,30 @@ J.toJsArray = function(list, nullListToEmptyArray){
return arr;
}
J.objectToMap = function(obj){
if(obj == null || obj === undefined){
return null;
}
let map = new java.util.HashMap();
for(let key in obj){
if(obj.hasOwnProperty(key)){
map.put(key, obj[key]);
}
}
return map;
}
J.mapToObject = function(map){
if(map == null || map === undefined){
return null;
}
let iter = map.entrySet().iterator();
let obj = {};
while(iter.hasNext()){
let entry = iter.next();
obj[entry.key] = entry.value;
}
return obj;
}
module.exports = J;

View File

@@ -6,27 +6,46 @@ module.exports = function (runtime, global) {
var J = util.java;
var ui = {};
ui.__widgets__ = {};
ui.__defineGetter__("emitter", ()=> activity ? activity.getEventEmitter() : null);
ui.layout = function (xml) {
if(!activity){
throw new Error("需要在ui模式下运行才能使用该函数");
}
if(typeof(xml) == 'xml'){
xml = xml.toXMLString();
}
runtime.ui.layoutInflater.setContext(activity);
var view = runtime.ui.layoutInflater.inflate(xml, activity.window.decorView, false);
ui.setContentView(view);
}
ui.inflate = function(xml, parent){
ui.inflate = function(xml, parent, attachToParent){
if(!activity){
throw new Error("需要在ui模式下运行才能使用该函数");
}
if(typeof(xml) == 'xml'){
xml = xml.toXMLString();
}
parent = parent || null;
attachToParent = !!attachToParent;
runtime.ui.layoutInflater.setContext(activity);
return decorate(runtime.ui.layoutInflater.inflate(xml.toString(), parent));
return runtime.ui.layoutInflater.inflate(xml.toString(), parent, attachToParent);
}
ui.__inflate__ = function(ctx, xml, parent, attachToParent){
if(typeof(xml) == 'xml'){
xml = xml.toXMLString();
}
parent = parent || null;
attachToParent = !!attachToParent;
return runtime.ui.layoutInflater.inflate(ctx, xml.toString(), parent, attachToParent);
}
ui.registerWidget = function(name, widget){
if(typeof(widget) !== 'function'){
throw new TypeError('widget should be a class-like function');
}
ui.__widgets__[name] = widget;
}
ui.setContentView = function (view) {
@@ -103,64 +122,96 @@ module.exports = function (runtime, global) {
runtime.ui.bindingContext = global;
var layoutInflater = runtime.ui.layoutInflater;
layoutInflater.setLayoutInflaterDelegate({
beforeConvertXml: function (xml) {
beforeConvertXml: function (context, xml) {
return null;
},
afterConvertXml: function (xml) {
afterConvertXml: function (context, xml) {
return xml;
},
afterInflation: function (result, xml, parent) {
afterInflation: function (context, result, xml, parent) {
return result;
},
beforeInflation: function (xml, parent) {
beforeInflation: function (context, xml, parent) {
return null;
},
beforeInflateView: function (node, parent, attachToParent) {
beforeInflateView: function (context, node, parent, attachToParent) {
return null;
},
afterInflateView: function (view, node, parent, attachToParent) {
afterInflateView: function (context, view, node, parent, attachToParent) {
return view;
},
beforeCreateView: function (node, viewName, attrs) {
beforeCreateView: function (context, node, viewName, parent, attrs) {
if(ui.__widgets__.hasOwnProperty(viewName)){
let Widget = ui.__widgets__[viewName];
let widget = new Widget();
let ctx = layoutInflater.newInflateContext();
ctx.put("widget", widget);
let view = ui.__inflate__(ctx, widget.renderInternal(), parent, false);
return view;
};
return null;
},
afterCreateView: function (view, node, viewName, attrs) {
afterCreateView: function (context, view, node, viewName, parent, attrs) {
if (view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsListView" ||
view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsGridView") {
initListView(view);
}
var widget = context.get("widget");
if(widget != null){
widget.view = view;
let viewAttrs = com.stardust.autojs.core.ui.ViewExtras.getViewAttributes(view, layoutInflater.resourceParser);
viewAttrs.setViewAttributeDelegate({
has: function(name) {
return widget.hasAttr(name);
},
get: function(view, name, getter){
return widget.getAttr(view, name, getter);
},
set: function(view, name, value, setter) {
widget.setAttr(view, name, value, setter);
}
});
widget.notifyViewCreated(view);
}
return view;
},
beforeApplyAttributes: function (view, inflater, attrs, parent) {
beforeApplyAttributes: function (context, view, inflater, attrs, parent) {
return false;
},
afterApplyAttributes: function (view, inflater, attrs, parent) {
afterApplyAttributes: function (context, view, inflater, attrs, parent) {
context.remove("widget");
},
beforeInflateChildren: function (inflater, node, parent) {
beforeInflateChildren: function (context, inflater, node, parent) {
return false;
},
afterInflateChildren: function (inflater, node, parent) {
afterInflateChildren: function (context, inflater, node, parent) {
},
afterApplyPendingAttributesOfChildren: function (inflater, view) {
afterApplyPendingAttributesOfChildren: function (context, inflater, view) {
},
beforeApplyPendingAttributesOfChildren: function (inflater, view) {
beforeApplyPendingAttributesOfChildren: function (context, inflater, view) {
return false;
},
beforeApplyAttribute: function (inflater, view, ns, attrName, value, parent, attrs) {
beforeApplyAttribute: function (context, inflater, view, ns, attrName, value, parent, attrs) {
var isDynamic = layoutInflater.isDynamicValue(value);
if ((isDynamic && layoutInflater.getInflateFlags() == layoutInflater.FLAG_IGNORES_DYNAMIC_ATTRS)
|| (!isDynamic && layoutInflater.getInflateFlags() == layoutInflater.FLAG_JUST_DYNAMIC_ATTRS)) {
return true;
}
value = bind(value);
inflater.setAttr(view, ns, attrName, value, parent, attrs);
this.afterApplyAttribute(inflater, view, ns, attrName, value, parent, attrs);
let widget = context.get("widget");
if(widget != null && widget.hasAttr(attrName)){
widget.setAttr(view, attrName, value, (view, attrName, value)=>{
inflater.setAttr(view, ns, attrName, value, parent, attrs);
});
} else {
inflater.setAttr(view, ns, attrName, value, parent, attrs);
}
this.afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs);
return true;
},
afterApplyAttribute: function (inflater, view, ns, attrName, value, parent, attrs) {
afterApplyAttribute: function (context, inflater, view, ns, attrName, value, parent, attrs) {
}
});
@@ -229,6 +280,39 @@ module.exports = function (runtime, global) {
}
}
ui.Widget = (function(){
function Widget(){
this.__attrs__ = {};
}
Widget.prototype.renderInternal = function(){
if(typeof(this.render) === 'function'){
return this.render();
}
return (< />)
};
Widget.prototype.defineAttr = function(attrName, getter, setter){
this.__attrs__[attrName] = {
getter: getter,
setter: setter
};
};
Widget.prototype.hasAttr = function(attrName){
return this.__attrs__.hasOwnProperty(attrName);
};
Widget.prototype.setAttr = function(view, attrName, value, setter){
this.__attrs__[attrName].setter(view, attrName, value, setter);
};
Widget.prototype.getAttr = function(view, attrName, getter){
return this.__attrs__[attrName].getter(view, attrName, getter);
};
Widget.prototype.notifyViewCreated = function(view){
if(typeof(this.onViewCreated) == 'function'){
this.onViewCreated(view);
}
};
return Widget;
})();
var proxy = runtime.ui;
proxy.__proxy__ = {
set: function (name, value) {

View File

@@ -20,6 +20,16 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.extends = (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.java = require("__java_util__");
exports.format = function(f) {
if (!isString(f)) {

View File

@@ -3,6 +3,8 @@ package com.stardust.autojs.core.http;
import android.widget.AdapterView;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
@@ -67,7 +69,6 @@ public class MutableOkHttp extends OkHttpClient {
public void setTimeout(long timeout) {
mTimeout = timeout;
muteClient();
}

View File

@@ -0,0 +1,21 @@
package com.stardust.autojs.core.ui.attribute;
import android.view.View;
public interface ViewAttributeDelegate {
interface ViewAttributeGetter {
String get(String name);
}
interface ViewAttributeSetter {
void set(String name, String value);
}
boolean has(String name);
String get(View view, String name, ViewAttributeGetter defaultGetter);
void set(View view, String name, String value, ViewAttributeSetter defaultSetter);
}

View File

@@ -15,6 +15,7 @@ import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.stardust.autojs.core.internal.Functions;
import com.stardust.autojs.core.ui.inflater.ResourceParser;
@@ -113,6 +114,7 @@ public class ViewAttributes {
private Map<String, Attribute> mAttributes = new HashMap<>();
private final Drawables mDrawables;
private final View mView;
private ViewAttributeDelegate mViewAttributeDelegate;
public ViewAttributes(ResourceParser resourceParser, View view) {
mDrawables = resourceParser.getDrawables();
@@ -120,6 +122,9 @@ public class ViewAttributes {
init();
}
public void setViewAttributeDelegate(ViewAttributeDelegate viewAttributeDelegate) {
mViewAttributeDelegate = viewAttributeDelegate;
}
public Drawables getDrawables() {
return mDrawables;
@@ -130,13 +135,41 @@ public class ViewAttributes {
}
public boolean contains(String name) {
return mAttributes.containsKey(name);
return mAttributes.containsKey(name) ||
(mViewAttributeDelegate != null && mViewAttributeDelegate.has(name));
}
public Attribute get(String name) {
if (mViewAttributeDelegate != null && mViewAttributeDelegate.has(name)) {
return new Attribute() {
@Override
public String get() {
return mViewAttributeDelegate.get(getView(), name, ViewAttributes.this::getAttrValue);
}
@Override
public void set(String value) {
mViewAttributeDelegate.set(getView(), name, value, ViewAttributes.this::setAttrValue);
}
};
}
return mAttributes.get(name);
}
public String getAttrValue(String name) {
Attribute attribute = mAttributes.get(name);
if (attribute != null) {
return attribute.get();
}
return null;
}
public void setAttrValue(String name, String value) {
Attribute attribute = mAttributes.get(name);
if (attribute != null) {
attribute.set(value);
}
}
@SuppressLint("ClickableViewAccessibility")
private void init() {
@@ -248,9 +281,7 @@ public class ViewAttributes {
}
protected void setElevation(int e) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mView.setElevation(e);
}
ViewCompat.setElevation(mView, e);
}
protected void setScrollbars(String scrollbars) {
@@ -472,15 +503,14 @@ public class ViewAttributes {
}
protected void setBackgroundTint(int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mView.setBackgroundTintList(ColorStateList.valueOf(color));
}
ViewCompat.setBackgroundTintList(mView, ColorStateList.valueOf(color));
}
protected void setContextClickable(boolean clickable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mView.setContextClickable(clickable);
}
}
protected void setChecked(boolean checked) {

View File

@@ -5,8 +5,6 @@ import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.TabLayout;
import android.support.v7.widget.Toolbar;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InflateException;
@@ -19,7 +17,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;
@@ -150,86 +147,96 @@ public class DynamicLayoutInflater {
}
public View inflate(String xml, @Nullable ViewGroup parent, boolean attachToParent) {
View view = mLayoutInflaterDelegate.beforeInflation(xml, parent);
if (view != null)
return view;
xml = convertXml(xml);
return mLayoutInflaterDelegate.afterInflation(doInflation(xml, parent, attachToParent), xml, parent);
InflateContext context = newInflateContext();
return inflate(context, xml, parent, attachToParent);
}
protected View doInflation(String xml, @Nullable ViewGroup parent, boolean attachToParent) {
public View inflate(InflateContext context, String xml, @Nullable ViewGroup parent, boolean attachToParent) {
View view = mLayoutInflaterDelegate.beforeInflation(context, xml, parent);
if (view != null)
return view;
xml = convertXml(context, xml);
return mLayoutInflaterDelegate.afterInflation(context, doInflation(context, xml, parent, attachToParent), xml, parent);
}
public InflateContext newInflateContext(){
return new InflateContext();
}
protected View doInflation(InflateContext context, String xml, @Nullable ViewGroup parent, boolean attachToParent) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(new ByteArrayInputStream(xml.getBytes()));
return inflate(document.getDocumentElement(), parent, attachToParent);
return inflate(context, document.getDocumentElement(), parent, attachToParent);
} catch (Exception e) {
throw new InflateException(e);
}
}
protected String convertXml(String xml) {
String str = mLayoutInflaterDelegate.beforeConvertXml(xml);
protected String convertXml(InflateContext context, String xml) {
String str = mLayoutInflaterDelegate.beforeConvertXml(context, xml);
if (str != null)
return str;
try {
return mLayoutInflaterDelegate.afterConvertXml(XmlConverter.convertToAndroidLayout(xml));
return mLayoutInflaterDelegate.afterConvertXml(context, XmlConverter.convertToAndroidLayout(xml));
} catch (Exception e) {
throw new InflateException(e);
}
}
public View inflate(Node node, @Nullable ViewGroup parent, boolean attachToParent) {
View view = doInflation(node, parent, attachToParent);
if (view != null && view instanceof ShouldCallOnFinishInflate) {
public View inflate(InflateContext context, Node node, @Nullable ViewGroup parent, boolean attachToParent) {
View view = doInflation(context, node, parent, attachToParent);
if (view instanceof ShouldCallOnFinishInflate) {
((ShouldCallOnFinishInflate) view).onFinishDynamicInflate();
}
return view;
}
protected View doInflation(Node node, @Nullable ViewGroup parent, boolean attachToParent) {
View view = mLayoutInflaterDelegate.beforeInflateView(node, parent, attachToParent);
protected View doInflation(InflateContext context, Node node, @Nullable ViewGroup parent, boolean attachToParent) {
View view = mLayoutInflaterDelegate.beforeInflateView(context, node, parent, attachToParent);
if (view != null)
return view;
HashMap<String, String> attrs = getAttributesMap(node);
view = doCreateView(node, node.getNodeName(), attrs);
view = doCreateView(context, node, node.getNodeName(), parent, attrs);
if (parent != null) {
parent.addView(view); // have to add to parent to generate layout params
if (!attachToParent) {
parent.removeView(view);
}
}
ViewInflater<View> inflater = applyAttributes(view, attrs, parent);
ViewInflater<View> inflater = applyAttributes(context, view, attrs, parent);
if (!(view instanceof ViewGroup) || !node.hasChildNodes()) {
return view;
}
inflateChildren(inflater, node, (ViewGroup) view);
inflateChildren(context, inflater, node, (ViewGroup) view);
if (inflater instanceof ViewGroupInflater) {
applyPendingAttributesOfChildren((ViewGroupInflater) inflater, (ViewGroup) view);
applyPendingAttributesOfChildren(context, (ViewGroupInflater) inflater, (ViewGroup) view);
}
return mLayoutInflaterDelegate.afterInflateView(view, node, parent, attachToParent);
return mLayoutInflaterDelegate.afterInflateView(context, view, node, parent, attachToParent);
}
@SuppressWarnings("unchecked")
protected void applyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view) {
if (mLayoutInflaterDelegate.beforeApplyPendingAttributesOfChildren(inflater, view)) {
protected void applyPendingAttributesOfChildren(InflateContext context, ViewGroupInflater inflater, ViewGroup view) {
if (mLayoutInflaterDelegate.beforeApplyPendingAttributesOfChildren(context, inflater, view)) {
return;
}
inflater.applyPendingAttributesOfChildren(view);
mLayoutInflaterDelegate.afterApplyPendingAttributesOfChildren(inflater, view);
mLayoutInflaterDelegate.afterApplyPendingAttributesOfChildren(context, inflater, view);
}
@SuppressWarnings("unchecked")
public ViewInflater<View> applyAttributes(View view, HashMap<String, String> attrs, @Nullable ViewGroup parent) {
public ViewInflater<View> applyAttributes(InflateContext context, View view, HashMap<String, String> attrs, @Nullable ViewGroup parent) {
ViewInflater<View> inflater = (ViewInflater<View>) getViewInflater(view);
if (mLayoutInflaterDelegate.beforeApplyAttributes(view, inflater, attrs, parent)) {
if (mLayoutInflaterDelegate.beforeApplyAttributes(context, view, inflater, attrs, parent)) {
return inflater;
}
applyAttributes(view, inflater, attrs, parent);
mLayoutInflaterDelegate.afterApplyAttributes(view, inflater, attrs, parent);
applyAttributes(context, view, inflater, attrs, parent);
mLayoutInflaterDelegate.afterApplyAttributes(context, view, inflater, attrs, parent);
return inflater;
}
@@ -244,31 +251,31 @@ public class DynamicLayoutInflater {
return setter;
}
protected void inflateChildren(ViewInflater<View> inflater, Node node, ViewGroup parent) {
if (mLayoutInflaterDelegate.beforeInflateChildren(inflater, node, parent)) {
protected void inflateChildren(InflateContext context, ViewInflater<View> inflater, Node node, ViewGroup parent) {
if (mLayoutInflaterDelegate.beforeInflateChildren(context, inflater, node, parent)) {
return;
}
if (inflater.inflateChildren(this, node, parent)) {
return;
}
inflateChildren(node, parent);
mLayoutInflaterDelegate.afterInflateChildren(inflater, node, parent);
inflateChildren(context, node, parent);
mLayoutInflaterDelegate.afterInflateChildren(context, inflater, node, parent);
}
public void inflateChildren(Node node, ViewGroup parent) {
public void inflateChildren(InflateContext context, Node node, ViewGroup parent) {
NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node currentNode = nodeList.item(i);
if (currentNode.getNodeType() != Node.ELEMENT_NODE) continue;
inflate(currentNode, parent, true);
inflate(context, currentNode, parent, true);
}
}
protected View doCreateView(Node node, String viewName, HashMap<String, String> attrs) {
View view = mLayoutInflaterDelegate.beforeCreateView(node, viewName, attrs);
protected View doCreateView(InflateContext context, Node node, String viewName, ViewGroup parent, HashMap<String, String> attrs) {
View view = mLayoutInflaterDelegate.beforeCreateView(context, node, viewName, parent, attrs);
if (view != null)
return view;
return mLayoutInflaterDelegate.afterCreateView(createViewForName(viewName, attrs), node, viewName, attrs);
return mLayoutInflaterDelegate.afterCreateView(context, createViewForName(viewName, attrs), node, viewName, parent, attrs);
}
public View createViewForName(String name, HashMap<String, String> attrs) {
@@ -311,14 +318,14 @@ public class DynamicLayoutInflater {
}
@SuppressWarnings("unchecked")
protected void applyAttributes(View view, ViewInflater<View> setter, Map<String, String> attrs, @Nullable ViewGroup parent) {
protected void applyAttributes(InflateContext context, View view, ViewInflater<View> setter, Map<String, String> attrs, @Nullable ViewGroup parent) {
if (setter != null) {
for (Map.Entry<String, String> entry : attrs.entrySet()) {
String[] attr = entry.getKey().split(":");
if (attr.length == 1) {
applyAttribute(setter, view, null, attr[0], entry.getValue(), parent, attrs);
applyAttribute(context, setter, view, null, attr[0], entry.getValue(), parent, attrs);
} else if (attr.length == 2) {
applyAttribute(setter, view, attr[0], attr[1], entry.getValue(), parent, attrs);
applyAttribute(context, setter, view, attr[0], attr[1], entry.getValue(), parent, attrs);
} else {
throw new InflateException("illegal attr name: " + entry.getKey());
}
@@ -330,8 +337,8 @@ public class DynamicLayoutInflater {
}
protected void applyAttribute(ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs) {
if (mLayoutInflaterDelegate.beforeApplyAttribute(inflater, view, ns, attrName, value, parent, attrs)) {
protected void applyAttribute(InflateContext context, ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs) {
if (mLayoutInflaterDelegate.beforeApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs)) {
return;
}
boolean isDynamic = isDynamicValue(value);
@@ -340,7 +347,7 @@ public class DynamicLayoutInflater {
return;
}
inflater.setAttr(view, ns, attrName, value, parent, attrs);
mLayoutInflaterDelegate.afterApplyAttribute(inflater, view, ns, attrName, value, parent, attrs);
mLayoutInflaterDelegate.afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs);
}

View File

@@ -0,0 +1,32 @@
package com.stardust.autojs.core.ui.inflater;
import java.util.HashMap;
public class InflateContext {
private HashMap<String, Object> mProperties;
public void put(String key, Object value) {
if (mProperties == null) {
mProperties = new HashMap<>();
}
mProperties.put(key, value);
}
public Object get(String key) {
if(mProperties == null)
return null;
return mProperties.get(key);
}
public Object remove(String key){
if(mProperties == null)
return null;
return mProperties.remove(key);
}
public boolean has(String key) {
return mProperties.containsKey(key);
}
}

View File

@@ -18,118 +18,118 @@ public interface LayoutInflaterDelegate {
LayoutInflaterDelegate NO_OP = new NoOp();
View beforeInflation(String xml, ViewGroup parent);
View beforeInflation(InflateContext inflateContext, String xml, ViewGroup parent);
View afterInflation(View doInflation, String xml, ViewGroup parent);
View afterInflation(InflateContext inflateContext, View doInflation, String xml, ViewGroup parent);
String beforeConvertXml(String xml);
String beforeConvertXml(InflateContext inflateContext, String xml);
String afterConvertXml(String xml);
String afterConvertXml(InflateContext inflateContext, String xml);
View beforeInflateView(Node node, ViewGroup parent, boolean attachToParent);
View beforeInflateView(InflateContext inflateContext, Node node, ViewGroup parent, boolean attachToParent);
View afterInflateView(View view, Node node, ViewGroup parent, boolean attachToParent);
View afterInflateView(InflateContext inflateContext, View view, Node node, ViewGroup parent, boolean attachToParent);
View beforeCreateView(Node node, String viewName, HashMap<String, String> attrs);
View beforeCreateView(InflateContext inflateContext, Node node, String viewName, ViewGroup parent, HashMap<String, String> attrs);
View afterCreateView(View view, Node node, String viewName, HashMap<String, String> attrs);
View afterCreateView(InflateContext inflateContext, View view, Node node, String viewName, ViewGroup parent, HashMap<String, String> attrs);
boolean beforeApplyAttributes(View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent);
boolean beforeApplyAttributes(InflateContext inflateContext, View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent);
void afterApplyAttributes(View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent);
void afterApplyAttributes(InflateContext inflateContext, View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent);
boolean beforeInflateChildren(ViewInflater<View> inflater, Node node, ViewGroup parent);
boolean beforeInflateChildren(InflateContext inflateContext, ViewInflater<View> inflater, Node node, ViewGroup parent);
void afterInflateChildren(ViewInflater<View> inflater, Node node, ViewGroup parent);
void afterInflateChildren(InflateContext inflateContext, ViewInflater<View> inflater, Node node, ViewGroup parent);
void afterApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view);
void afterApplyPendingAttributesOfChildren(InflateContext inflateContext, ViewGroupInflater inflater, ViewGroup view);
boolean beforeApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view);
boolean beforeApplyPendingAttributesOfChildren(InflateContext inflateContext, ViewGroupInflater inflater, ViewGroup view);
boolean beforeApplyAttribute(ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs);
boolean beforeApplyAttribute(InflateContext inflateContext, ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs);
void afterApplyAttribute(ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs);
void afterApplyAttribute(InflateContext inflateContext, ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs);
class NoOp implements LayoutInflaterDelegate {
@Override
public String beforeConvertXml(String xml) {
public String beforeConvertXml(InflateContext inflateContext, String xml) {
return null;
}
@Override
public String afterConvertXml(String xml) {
public String afterConvertXml(InflateContext inflateContext, String xml) {
return xml;
}
@Override
public View afterInflation(View result, String xml, ViewGroup parent) {
public View afterInflation(InflateContext inflateContext, View result, String xml, ViewGroup parent) {
return result;
}
@Override
public View beforeInflation(String xml, ViewGroup parent) {
public View beforeInflation(InflateContext inflateContext, String xml, ViewGroup parent) {
return null;
}
@Override
public View beforeInflateView(Node node, ViewGroup parent, boolean attachToParent) {
public View beforeInflateView(InflateContext inflateContext, Node node, ViewGroup parent, boolean attachToParent) {
return null;
}
@Override
public View afterInflateView(View view, Node node, ViewGroup parent, boolean attachToParent) {
public View afterInflateView(InflateContext inflateContext, View view, Node node, ViewGroup parent, boolean attachToParent) {
return view;
}
@Override
public View beforeCreateView(Node node, String viewName, HashMap<String, String> attrs) {
public View beforeCreateView(InflateContext inflateContext, Node node, String viewName, ViewGroup parent, HashMap<String, String> attrs) {
return null;
}
@Override
public View afterCreateView(View view, Node node, String viewName, HashMap<String, String> attrs) {
public View afterCreateView(InflateContext inflateContext, View view, Node node, String viewName, ViewGroup parent, HashMap<String, String> attrs) {
return view;
}
@Override
public boolean beforeApplyAttributes(View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent) {
public boolean beforeApplyAttributes(InflateContext inflateContext, View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent) {
return false;
}
@Override
public void afterApplyAttributes(View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent) {
public void afterApplyAttributes(InflateContext inflateContext, View view, ViewInflater<View> inflater, HashMap<String, String> attrs, ViewGroup parent) {
}
@Override
public boolean beforeInflateChildren(ViewInflater<View> inflater, Node node, ViewGroup parent) {
public boolean beforeInflateChildren(InflateContext inflateContext, ViewInflater<View> inflater, Node node, ViewGroup parent) {
return false;
}
@Override
public void afterInflateChildren(ViewInflater<View> inflater, Node node, ViewGroup parent) {
public void afterInflateChildren(InflateContext inflateContext, ViewInflater<View> inflater, Node node, ViewGroup parent) {
}
@Override
public void afterApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view) {
public void afterApplyPendingAttributesOfChildren(InflateContext inflateContext, ViewGroupInflater inflater, ViewGroup view) {
}
@Override
public boolean beforeApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view) {
public boolean beforeApplyPendingAttributesOfChildren(InflateContext inflateContext, ViewGroupInflater inflater, ViewGroup view) {
return false;
}
@Override
public boolean beforeApplyAttribute(ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs) {
public boolean beforeApplyAttribute(InflateContext inflateContext, ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs) {
return false;
}
@Override
public void afterApplyAttribute(ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs) {
public void afterApplyAttribute(InflateContext inflateContext, ViewInflater<View> inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map<String, String> attrs) {
}
}

View File

@@ -119,6 +119,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
ViewAttributes viewAttributes = ViewExtras.getViewAttributes(view, getResourceParser());
ViewAttributes.Attribute attribute = viewAttributes.get(attr);
if (attribute != null) {
Log.d(LOG_TAG, "setAttr use ViewAttributes: attr = " + attr);
attribute.set(value);
return true;
}
@@ -284,6 +285,7 @@ public class BaseViewInflater<V extends View> implements ViewInflater<V> {
case "paddingBottom":
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), Dimensions.parseToIntPixel(value, view));
break;
case "bg":
case "background":
getDrawables().setupWithViewBackground(view, value);
break;

View File

@@ -346,6 +346,7 @@ public class TextViewInflater<V extends TextView> extends BaseViewInflater<V> {
case "text":
view.setText(Strings.parse(view, value));
break;
case "color":
case "textColor":
view.setTextColor(Colors.parse(view.getContext(), value));
break;

View File

@@ -1,8 +1,9 @@
package com.stardust.autojs.core.ui.nativeview;
import android.graphics.PorterDuff;
import android.view.View;
import android.widget.Button;
import com.stardust.autojs.R;
import com.stardust.autojs.core.ui.JsViewHelper;
import com.stardust.autojs.core.ui.ViewExtras;
import com.stardust.autojs.core.ui.attribute.ViewAttributes;
@@ -47,7 +48,7 @@ public class NativeView extends NativeJavaObjectWithPrototype {
super(scope, view, staticType);
mViewAttributes = ViewExtras.getViewAttributes(view, runtime.ui.getResourceParser());
mView = view;
mViewPrototype = new ViewPrototype(mView, scope, runtime);
mViewPrototype = new ViewPrototype(mView, mViewAttributes, scope, runtime);
prototype = new NativeJavaObject(scope, mViewPrototype, mViewPrototype.getClass());
}
@@ -59,25 +60,8 @@ public class NativeView extends NativeJavaObjectWithPrototype {
return super.has(name, start);
}
@Override
public void put(String name, Scriptable start, Object value) {
if (value != null && (value instanceof CharSequence ||
value.getClass().getName().equals("org.mozilla.javascript.NativeString"))) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
attribute.set(ScriptRuntime.toString(value));
return;
}
}
super.put(name, start, value);
}
@Override
public Object get(String name, Scriptable start) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
return attribute.get();
}
if (super.has(name, start)) {
return super.get(name, start);
} else {

View File

@@ -7,6 +7,7 @@ import android.widget.CompoundButton;
import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.ui.BaseEvent;
import com.stardust.autojs.core.ui.attribute.ViewAttributes;
import com.stardust.autojs.core.ui.widget.JsListView;
import com.stardust.autojs.runtime.ScriptRuntime;
@@ -20,13 +21,34 @@ public class ViewPrototype {
private final View mView;
private final HashSet<String> mRegisteredEvents = new HashSet<>();
private final Scriptable mScope;
private final ViewAttributes mViewAttributes;
public ViewPrototype(View view, Scriptable scope, ScriptRuntime runtime) {
public ViewPrototype(View view, ViewAttributes viewAttributes, Scriptable scope, ScriptRuntime runtime) {
mView = view;
mViewAttributes = viewAttributes;
mEventEmitter = runtime.events.emitter();
mScope = scope;
}
public ViewAttributes getViewAttributes() {
return mViewAttributes;
}
public Object attr(String name) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
return attribute.get();
}
return null;
}
public void attr(String name, Object value) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
attribute.set(org.mozilla.javascript.ScriptRuntime.toString(value));
}
}
public void click() {
mView.performClick();
}

View File

@@ -2,6 +2,8 @@ package com.stardust.autojs.core.ui.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.widget.Button;
@@ -23,6 +25,7 @@ public class JsButton extends Button {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public JsButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

View File

@@ -1,24 +1,16 @@
package com.stardust.autojs.core.ui.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Handler;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.stardust.autojs.R;
import com.stardust.autojs.core.ui.ViewExtras;
import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater;
import com.stardust.autojs.core.ui.nativeview.NativeView;
import com.stardust.autojs.core.ui.nativeview.ViewPrototype;
import com.stardust.autojs.runtime.ScriptRuntime;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -143,7 +135,7 @@ public class JsListView extends RecyclerView {
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
try {
mDynamicLayoutInflater.setInflateFlags(DynamicLayoutInflater.FLAG_IGNORES_DYNAMIC_ATTRS);
return new ViewHolder(mDynamicLayoutInflater.inflate(mItemTemplate, parent, false));
return new ViewHolder(mDynamicLayoutInflater.inflate(mDynamicLayoutInflater.newInflateContext(), mItemTemplate, parent, false));
} catch (Exception e) {
mScriptRuntime.exit(e);
return new ViewHolder(new View(parent.getContext()));
@@ -170,7 +162,7 @@ public class JsListView extends RecyclerView {
}
private void applyDynamicAttrs(Node node, View itemView, ViewGroup parent) {
mDynamicLayoutInflater.applyAttributes(itemView, mDynamicLayoutInflater.getAttributesMap(node), parent);
mDynamicLayoutInflater.applyAttributes(mDynamicLayoutInflater.newInflateContext(), itemView, mDynamicLayoutInflater.getAttributesMap(node), parent);
if (!(itemView instanceof ViewGroup))
return;
ViewGroup viewGroup = (ViewGroup) itemView;

View File

@@ -100,11 +100,7 @@ public class XmlConverter {
.handler("paddingRight", new AttributeHandler.DimenHandler("paddingRight"))
.handler("paddingTop", new AttributeHandler.DimenHandler("paddingTop"))
.handler("paddingBottom", new AttributeHandler.DimenHandler("paddingBottom"))
.defaultHandler(new AttributeHandler.MappedAttributeHandler()
.mapName("align", "layout_gravity")
.mapName("bg", "background")
.mapName("color", "textColor")
);
.defaultHandler(new AttributeHandler.MappedAttributeHandler());
public static String convertToAndroidLayout(String xml) throws IOException, SAXException, ParserConfigurationException {
return convertToAndroidLayout(new InputSource(new StringReader(xml)));

View File

@@ -454,7 +454,7 @@ public class ScriptRuntime {
PrintWriter writer = new PrintWriter(stringWriter);
e.printStackTrace(writer);
writer.close();
BufferedReader bufferedReader = new BufferedReader(new StringReader(writer.toString()));
BufferedReader bufferedReader = new BufferedReader(new StringReader(stringWriter.toString()));
String line;
while ((line = bufferedReader.readLine()) != null) {
scriptTrace.append("\n").append(line);

View File

@@ -40,13 +40,13 @@ public class Floaty {
mLayoutInflater = ui.getLayoutInflater();
}
public JsResizableWindow window(String xml) {
public JsResizableWindow window(BaseResizableFloatyWindow.ViewSupplier supplier) {
try {
FloatingPermission.waitForPermissionGranted(mContext);
} catch (InterruptedException e) {
throw new ScriptInterruptedException();
}
JsResizableWindow window = new JsResizableWindow((context, parent) -> mLayoutInflater.inflate(xml, parent));
JsResizableWindow window = new JsResizableWindow(supplier);
addWindow(window);
return window;
}
@@ -63,13 +63,13 @@ public class Floaty {
return window;
}
public JsRawWindow rawWindow(String xml) {
public JsRawWindow rawWindow(RawWindow.RawFloaty floaty) {
try {
FloatingPermission.waitForPermissionGranted(mContext);
} catch (InterruptedException e) {
throw new ScriptInterruptedException();
}
JsRawWindow window = new JsRawWindow((context, parent) -> mLayoutInflater.inflate(xml, parent));
JsRawWindow window = new JsRawWindow(floaty);
addWindow(window);
return window;
}

View File

@@ -3,8 +3,11 @@ package com.stardust.autojs.script;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.stardust.autojs.rhino.TokenStream;
import com.stardust.util.MapBuilder;
import org.mozilla.javascript.Token;
import java.io.Reader;
import java.io.StringReader;
import java.util.Map;
@@ -63,13 +66,17 @@ public abstract class JavaScriptSource extends ScriptSource {
}
private int parseExecutionMode(String script) {
if (script == null || script.length() == 0 || script.charAt(0) != '"')
if (script == null || script.length() == 0)
return EXECUTION_MODE_NORMAL;
int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2);
if (i == -1)
return EXECUTION_MODE_NORMAL;
String modeString = script.substring(1, i);
return parseExecutionMode(modeString.split(" "));
if(script.charAt(0) == '"'){
int i = script.lastIndexOf("\";", EXECUTION_MODE_STRING_MAX_LENGTH + 2);
if (i >= 0){
String modeString = script.substring(1, i);
return parseExecutionMode(modeString.split(" "));
}
}
return EXECUTION_MODE_NORMAL;
}
private int parseExecutionMode(String[] modeStrings) {