From bac87f2591736d438aa5f08910eb5d6d73ac8439 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Thu, 29 Mar 2018 16:50:21 +0800 Subject: [PATCH] refactor(ui): refactor dynamic layout inflater feat(ui): xml one way data binding feat(ui): label `list` --- .../main/assets/sample/界面控件/列表控件.js | 33 ++ autojs/src/main/assets/init.js | 5 + autojs/src/main/assets/modules/__ui__.js | 311 ++++++++++++------ .../main/assets/modules/array-observe.min.js | 3 + .../assets/modules/object-observe-lite.min.js | 3 + .../autojs/core/templatematching/Test.java | 15 - .../autojs/core/ui/ConvertLayoutInflater.java | 35 -- .../autojs/core/ui/JsLayoutInflater.java | 14 - .../ui/inflater/DynamicLayoutInflater.java | 227 ++++++++----- .../ui/inflater/LayoutInflaterDelegate.java | 136 ++++++++ .../{ValueParser.java => ResourceParser.java} | 4 +- ...{ViewAttrSetter.java => ViewInflater.java} | 6 +- .../BaseViewInflater.java} | 28 +- .../CanvasViewInflater.java} | 14 +- .../DatePickerInflater.java} | 10 +- .../{attrsetter => inflaters}/Exceptions.java | 2 +- .../FrameLayoutInflater.java} | 12 +- .../ImageViewInflater.java} | 11 +- .../JsImageViewInflater.java} | 11 +- .../inflaters/JsListViewInflater.java | 57 ++++ .../LinearLayoutInflater.java} | 11 +- .../MapAttrbuteSet.java | 2 +- .../ProgressBarInflater.java} | 11 +- .../RadioGroupInflater.java} | 12 +- .../SpinnerInflater.java} | 11 +- .../TextViewInflater.java} | 11 +- .../TimePickerInflater.java} | 10 +- .../ToolbarInflater.java} | 10 +- .../ViewGroupInflater.java} | 12 +- .../autojs/core/ui/widget/JsListView.java | 117 +++++++ .../autojs/core/ui/xml/XmlConverter.java | 3 + .../autojs/runtime/ScriptBridges.java | 8 + .../autojs/runtime/ScriptRuntime.java | 2 +- .../stardust/autojs/runtime/api/Floaty.java | 10 +- .../stardust/autojs/runtime/api/Media.java | 8 +- .../com/stardust/autojs/runtime/api/UI.java | 64 ++-- 36 files changed, 885 insertions(+), 354 deletions(-) create mode 100644 app/src/main/assets/sample/界面控件/列表控件.js create mode 100644 autojs/src/main/assets/modules/array-observe.min.js create mode 100644 autojs/src/main/assets/modules/object-observe-lite.min.js delete mode 100644 autojs/src/main/java/com/stardust/autojs/core/templatematching/Test.java delete mode 100644 autojs/src/main/java/com/stardust/autojs/core/ui/ConvertLayoutInflater.java delete mode 100644 autojs/src/main/java/com/stardust/autojs/core/ui/JsLayoutInflater.java create mode 100644 autojs/src/main/java/com/stardust/autojs/core/ui/inflater/LayoutInflaterDelegate.java rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{ValueParser.java => ResourceParser.java} (79%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{ViewAttrSetter.java => ViewInflater.java} (77%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/BaseViewAttrSetter.java => inflaters/BaseViewInflater.java} (97%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/CanvasViewAttrSetter.java => inflaters/CanvasViewInflater.java} (55%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/DatePickerAttrSetter.java => inflaters/DatePickerInflater.java} (91%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter => inflaters}/Exceptions.java (94%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/FrameLayoutAttrSetter.java => inflaters/FrameLayoutInflater.java} (73%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/ImageViewAttrSetter.java => inflaters/ImageViewInflater.java} (91%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/JsImageViewAttrSetter.java => inflaters/JsImageViewInflater.java} (91%) create mode 100644 autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/JsListViewInflater.java rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/LinearLayoutAttrSetter.java => inflaters/LinearLayoutInflater.java} (82%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter => inflaters}/MapAttrbuteSet.java (98%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/ProgressBarAttrSetter.java => inflaters/ProgressBarInflater.java} (92%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/RadioGroupAttrSetter.java => inflaters/RadioGroupInflater.java} (66%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/SpinnerAttrSetter.java => inflaters/SpinnerInflater.java} (90%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/TextViewAttrSetter.java => inflaters/TextViewInflater.java} (98%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/TimePickerAttrSetter.java => inflaters/TimePickerInflater.java} (71%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/ToolbarAttrSetter.java => inflaters/ToolbarInflater.java} (76%) rename autojs/src/main/java/com/stardust/autojs/core/ui/inflater/{attrsetter/ViewGroupAttrSetter.java => inflaters/ViewGroupInflater.java} (89%) create mode 100644 autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java diff --git a/app/src/main/assets/sample/界面控件/列表控件.js b/app/src/main/assets/sample/界面控件/列表控件.js new file mode 100644 index 00000000..fed03fcb --- /dev/null +++ b/app/src/main/assets/sample/界面控件/列表控件.js @@ -0,0 +1,33 @@ +"ui"; + +ui.layout( + + + + + + + + +); + +var items = [ + {name: "小明", age: 18}, {name: "小红", age: 30}, + {name: "小东", age: 19}, {name: "小强", age: 31}, + {name: "小满", age: 20}, {name: "小一", age: 32}, + {name: "小和", age: 21}, {name: "小二", age: 1}, + {name: "小贤", age: 22}, {name: "小三", age: 2}, + {name: "小伟", age: 23}, {name: "小四", age: 3}, + {name: "小黄", age: 24}, {name: "小五", age: 4}, + {name: "小健", age: 25}, {name: "小六", age: 5}, + {name: "小啦", age: 26}, {name: "小七", age: 6}, + {name: "小哈", age: 27}, {name: "小八", age: 7}, + {name: "小啊", age: 28}, {name: "小九", age: 8}, + {name: "小啪", age: 29}, {name: "小十", age: 9} +]; + +ui.list.setDataSource(items); + +ui.list.on("item_click", function(i, item, itemView, listView){ + toast("被点击的人名字为: " + item.name + ",年龄为: " + item.age); +}); \ No newline at end of file diff --git a/autojs/src/main/assets/init.js b/autojs/src/main/assets/init.js index 63ee9547..9bc42ce6 100644 --- a/autojs/src/main/assets/init.js +++ b/autojs/src/main/assets/init.js @@ -52,6 +52,11 @@ runtime.init(); }, toString: function(o){ return String(o); + }, + eval: function(context, expr){ + with(context){ + return eval(expr); + } } }); diff --git a/autojs/src/main/assets/modules/__ui__.js b/autojs/src/main/assets/modules/__ui__.js index ae9f2803..9124709d 100644 --- a/autojs/src/main/assets/modules/__ui__.js +++ b/autojs/src/main/assets/modules/__ui__.js @@ -1,120 +1,212 @@ -module.exports = function(__runtime__, scope){ +module.exports = function (runtime, global) { + + require("object-observe-lite.min")(); + require("array-observe.min")(); + + var ui = {}; ui.__view_cache__ = {}; - ui.layout = function(xml){ - var view = __runtime__.ui.layoutInflater.inflate(activity, xml.toString()); + ui.layout = function (xml) { + runtime.ui.layoutInflater.setContext(activity); + var view = runtime.ui.layoutInflater.inflate(xml.toString()); ui.setContentView(view); } - ui.setContentView = function(view){ + ui.setContentView = function (view) { ui.view = view; ui.__view_cache__ = {}; - ui.run(function(){ + ui.run(function () { activity.setContentView(view); }); } - ui.findById = function(id){ - if(!ui.view) + ui.findById = function (id) { + if (!ui.view) return null; var v = ui.findByStringId(ui.view.getChildAt(0), id); - if(v){ + if (v) { v = decorate(v); } return v; } - ui.isUiThread = function(){ + ui.isUiThread = function () { importClass(android.os.Looper); return Looper.myLooper() == Looper.getMainLooper(); } - ui.run = function(action){ - if(ui.isUiThread()){ + ui.run = function (action) { + if (ui.isUiThread()) { return action(); } var err = null; var result; - var disposable = scope.threads.disposable(); - __runtime__.uiHandler.post(function(){ - try{ + var disposable = global.threads.disposable(); + runtime.uiHandler.post(function () { + try { result = action(); disposable.setAndNotify(true); - }catch(e){ + } catch (e) { err = e; disposable.setAndNotify(true); } }); disposable.blockedGet(); - if(err){ + if (err) { throw err; } return result; } - ui.post = function(action, delay){ + ui.post = function (action, delay) { delay = delay || 0; - __runtime__.getUiHandler().postDelay(wrapUiAction(action), delay); + runtime.getUiHandler().postDelay(wrapUiAction(action), delay); } - ui.statusBarColor = function(color){ - if(typeof(color) == 'string'){ + ui.statusBarColor = function (color) { + if (typeof (color) == 'string') { color = android.graphics.Color.parseColor(color); } - if(android.os.Build.VERSION.SDK_INT >= 21){ - ui.run(function(){ + if (android.os.Build.VERSION.SDK_INT >= 21) { + ui.run(function () { activity.getWindow().setStatusBarColor(color); }); } } - ui.finish = function(){ - ui.run(function(){ + ui.finish = function () { + ui.run(function () { activity.finish(); }); } - ui.findByStringId = function(view, id){ + ui.findByStringId = function (view, id) { return com.stardust.autojs.core.ui.JsViewHelper.findViewByStringId(view, id); } - function decorate(view){ - var view = scope.events.__asEmitter__(Object.create(view)); + runtime.ui.bindingContext = global; + runtime.ui.layoutInflater.setLayoutInflaterDelegate({ + beforeConvertXml: function (xml) { + return null; + }, + afterConvertXml: function (xml) { + return xml; + }, + afterInflation: function (result, xml, parent) { + return result; + }, + beforeInflation: function (xml, parent) { + return null; + }, + beforeInflateView: function (node, parent, attachToParent) { + return null; + }, + afterInflateView: function (view, node, parent, attachToParent) { + return view; + }, + beforeCreateView: function (node, viewName, attrs) { + return null; + }, + afterCreateView: function (view, node, viewName, attrs) { + if (view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsListView") { + initListView(view); + } + return view; + }, + beforeApplyAttributes: function (view, inflater, attrs, parent) { + return false; + }, + afterApplyAttributes: function (view, inflater, attrs, parent) { + + }, + beforeInflateChildren: function (inflater, node, parent) { + return false; + }, + afterInflateChildren: function (inflater, node, parent) { + + }, + afterApplyPendingAttributesOfChildren: function (inflater, view) { + + }, + beforeApplyPendingAttributesOfChildren: function (inflater, view) { + return false; + }, + beforeApplyAttribute: function (inflater, view, ns, attrName, value, parent, attrs) { + value = bind(value); + inflater.setAttr(view, ns, attrName, value, parent, attrs); + this.afterApplyAttribute(inflater, view, ns, attrName, value, parent, attrs); + return true; + }, + afterApplyAttribute: function (inflater, view, ns, attrName, value, parent, attrs) { + + } + }); + + function bind(value) { + var ctx = runtime.ui.bindingContext; + if (ctx == null) + return; + var i = -1; + while ((i = value.indexOf("{{", i + 1)) >= 0) { + var j = value.indexOf("}}", i + 1); + if (j < 0) + return value; + value = value.substring(0, i) + evalInContext(value.substring(i + 2, j), ctx) + value.substring(j + 2); + i = j + 1; + } + return value; + } + + function evalInContext(expr, ctx) { + return global.__exitIfError__(function () { + log(ctx.toString()); + with(ctx){ + return eval(expr); + } + }); + + } + + function decorate(view) { + var view = global.events.__asEmitter__(Object.create(view)); + if (view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsListView") { + view = decorateList(view); + } var gestureDetector = new android.view.GestureDetector(context, { - onDown: function(e){ + onDown: function (e) { e = wrapMotionEvent(e); emit("touch_down", e, view); return e.consumed; }, - onShowPress: function(e){ + onShowPress: function (e) { e = wrapMotionEvent(e); emit("show_press", e, view); }, - onSingleTapUp: function(e){ - e = wrapMotionEvent(e); - emit("single_tap", e, view); - return e.consumed; + onSingleTapUp: function (e) { + e = wrapMotionEvent(e); + emit("single_tap", e, view); + return e.consumed; }, - onScroll: function(e1, e2, distanceX, distanceY){ - e1 = wrapMotionEvent(e1); - e2 = wrapMotionEvent(e2); - emit("scroll", e1, e2, distanceX, distanceY, view); - return e1.consumed || e2.consumed; + onScroll: function (e1, e2, distanceX, distanceY) { + e1 = wrapMotionEvent(e1); + e2 = wrapMotionEvent(e2); + emit("scroll", e1, e2, distanceX, distanceY, view); + return e1.consumed || e2.consumed; }, - onLongPress: function(e){ - e = wrapMotionEvent(e); - emit("long_press", e, view); + onLongPress: function (e) { + e = wrapMotionEvent(e); + emit("long_press", e, view); }, - onFling: function(e1, e2, velocityX, velocityY){ - e1 = wrapMotionEvent(e1); - e2 = wrapMotionEvent(e2); - emit("fling", e1, e2, velocityX, velocityY, view); - return e1.consumed || e2.consumed; + onFling: function (e1, e2, velocityX, velocityY) { + e1 = wrapMotionEvent(e1); + e2 = wrapMotionEvent(e2); + emit("fling", e1, e2, velocityX, velocityY, view); + return e1.consumed || e2.consumed; } }); - view.setOnTouchListener(function(v, event){ - if(gestureDetector.onTouchEvent(event)){ + view.setOnTouchListener(function (v, event) { + if (gestureDetector.onTouchEvent(event)) { return true; } event = wrapMotionEvent(event); @@ -122,106 +214,141 @@ module.exports = function(__runtime__, scope){ emit("touch", event, view); return event.consumed; }) - view.setOnLongClickListener(function(v){ + view.setOnLongClickListener(function (v) { var event = {}; event.consumed = false; emit("long_click", event, view); return event.consumed; }); - view.setOnClickListener(function(v){ + view.setOnClickListener(function (v) { emit("click", view); }); - view.setOnKeyListener(function(v, keyCode, event){ + view.setOnKeyListener(function (v, keyCode, event) { event = wrapMotionEvent(event); emit("key", keyCode, event, v); return event.consumed; }); - if(typeof(view.setOnCheckedChangeListener) == 'function'){ - view.setOnCheckedChangeListener(function(v, isChecked){ + if (typeof (view.setOnCheckedChangeListener) == 'function') { + view.setOnCheckedChangeListener(function (v, isChecked) { emit("check", isChecked, view); }); } - view._id = function(id){ - return ui.findByStringId(view, id); + view._id = function (id) { + return ui.findById(view, id); } - view.click = function(listener){ - if(listener){ + view.click = function (listener) { + if (listener) { view.setOnClickListener(new android.view.View.OnClickListener(wrapUiAction(listener))); - }else{ + } else { view.performClick(); } } - view.longClick = function(listener){ - if(listener){ + view.longClick = function (listener) { + if (listener) { view.setOnLongClickListener(wrapUiAction(listener, false)); - }else{ + } else { view.performLongClick(); } } - function emit(){ + function emit() { var args = arguments; - scope.__exitIfError__(function(){ + global.__exitIfError__(function () { //不支持使用apply的原因是rhino会把参数中的primitive变成object functionApply(view.emit, args); - //view.emit.apply(view, args); + //view.emit.apply(view, args); }); } return view; } + + + function initListView(list) { + list.setDataSourceAdapter({ + getItemCount: function (data) { + return data.length; + }, + getItem: function (data, i) { + return data[i]; + }, + setDataSource: function (data) { + var adapter = list.getAdapter(); + Array.observe(data, function (changes) { + changes.forEach(change => { + if (change.type == 'splice') { + if (change.removed && change.removed.length > 0) { + adapter.notifyItemRangeRemoved(change.index, change.removed.length); + } + if (change.addedCount > 0) { + adapter.notifyItemRangeInserted(change.index, change.addedCount); + } + } else if (change.type == 'update') { + adapter.notifyItemChanged(parseInt(change.name)); + } + }); + }); + } + }); + } + + function decorateList(list) { + + return list; + } + ui.__decorate__ = decorate; - function wrapUiAction(action, defReturnValue){ - if(typeof(activity) != 'undefined'){ - return function(){return action();}; + function wrapUiAction(action, defReturnValue) { + if (typeof (activity) != 'undefined') { + return function () { return action(); }; } - return function(){ + return function () { return __exitIfError__(action, defReturnValue); } } - function wrapMotionEvent(e){ + function wrapMotionEvent(e) { e = Object.create(e); e.consumed = false; return e; } - function functionApply(func, args){ - if(args.length == 0) + function functionApply(func, args) { + if (args.length == 0) return func(); - if(args.length == 1) + if (args.length == 1) return func(args[0]); - if(args.length == 2) + if (args.length == 2) return func(args[0], args[1]); - if(args.length == 3) + if (args.length == 3) return func(args[0], args[1], args[2]); - if(args.length == 4) + if (args.length == 4) return func(args[0], args[1], args[2], args[3]); - if(args.length == 5) + if (args.length == 5) return func(args[0], args[1], args[2], args[3], args[4]); - if(args.length == 6) + if (args.length == 6) return func(args[0], args[1], args[2], args[3], args[4], args[5]); throw new Error("too many arguments: " + args.length); } - var proxy = __runtime__.ui; + var proxy = runtime.ui; proxy.__proxy__ = { - set: function(name, value){ + set: function (name, value) { ui[name] = value; }, - get: function(name) { - if(!ui[name] && ui.view){ - var cacheView = ui.__view_cache__[name]; - if(cacheView){ - return cacheView; - } - cacheView = ui.findById(name); - if(cacheView){ - ui.__view_cache__[name] = cacheView; - return cacheView; - } - } - return ui[name]; + get: function (name) { + if (!ui[name] && ui.view) { + var cache = ui.__view_cache__[name]; + if (cache) { + return cache; + } + cache = ui.findById(name); + if (cache) { + ui.__view_cache__[name] = cache; + return cache; + } + } + return ui[name]; } }; diff --git a/autojs/src/main/assets/modules/array-observe.min.js b/autojs/src/main/assets/modules/array-observe.min.js new file mode 100644 index 00000000..bfbb5104 --- /dev/null +++ b/autojs/src/main/assets/modules/array-observe.min.js @@ -0,0 +1,3 @@ +module.exports = function(){ + Object.observe&&!Array.observe&&function(t,e){"use strict";var n=t.getNotifier,r="performChange",i="_original",o="splice";var u={push:function h(t){var e=arguments,u=h[i].apply(this,e);n(this)[r](o,function(){return{index:u-e.length,addedCount:e.length,removed:[]}});return u},unshift:function d(t){var e=arguments,u=d[i].apply(this,e);n(this)[r](o,function(){return{index:0,addedCount:e.length,removed:[]}});return u},pop:function a(){var t=this.length,e=a[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:this.length,addedCount:0,removed:[e]}},this);return e},shift:function l(){var t=this.length,e=l[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:0,addedCount:0,removed:[e]}},this);return e},splice:function f(t,e){var u=arguments,s=f[i].apply(this,u);if(s.length||u.length>2)n(this)[r](o,function(){return{index:t,addedCount:u.length-2,removed:s}},this);return s}};for(var s in u){u[s][i]=e.prototype[s];e.prototype[s]=u[s]}e.observe=function(e,n){return t.observe(e,n,["add","update","delete",o])};e.unobserve=t.unobserve}(Object,Array); +} \ No newline at end of file diff --git a/autojs/src/main/assets/modules/object-observe-lite.min.js b/autojs/src/main/assets/modules/object-observe-lite.min.js new file mode 100644 index 00000000..61a22aee --- /dev/null +++ b/autojs/src/main/assets/modules/object-observe-lite.min.js @@ -0,0 +1,3 @@ +module.exports = function(){ + Object.observe||function(e,t,n,r){"use strict";var o,i,c=["add","update","delete","reconfigure","setPrototype","preventExtensions"],a=t.isArray||function(e){return function(t){return"[object Array]"===e.call(t)}}(e.prototype.toString),f=t.prototype.indexOf?t.indexOf||function(e,n,r){return t.prototype.indexOf.call(e,n,r)}:function(e,t,n){for(var r=n||0;r-1},get:function(n){return t[f(e,n)]},set:function(n,r){var o=f(e,n);-1===o?(e.push(n),t.push(r),this.size++):t[o]=r},"delete":function(n){var r=f(e,n);r>-1&&(e.splice(r,1),t.splice(r,1),this.size--)},forEach:function(n){for(var r=0;r-1&&n.splice(o,1);return n})}return t}():function(t){var n,r,o=[];if("hasOwnProperty"in t)for(n in t)t.hasOwnProperty(n)&&o.push(n);else{r=e.hasOwnProperty;for(n in t)r.call(t,n)&&o.push(n)}return a(t)&&o.push("length"),o},p=n.requestAnimationFrame||n.webkitRequestAnimationFrame||function(){var e=+new Date,t=e;return function(n){return setTimeout(function(){n((t=+new Date)-e)},17)}}(),l=function(e,t,n){var r=o.get(e);r?(v(r,e),g(e,r,t,n)):(r=h(e),g(e,r,t,n),1===o.size&&p(d))},h=function(e,t){for(var n=u(e),r=[],i=0,t={handlers:s(),properties:n,values:r,notifier:b(e,t)};i-1&&t.changeRecords.push(n)})};o=s(),i=s(),e.observe=function(t,n,o){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.observe cannot observe non-object");if("function"!=typeof n)throw new TypeError("Object.observe cannot deliver to non-function");if(e.isFrozen&&e.isFrozen(n))throw new TypeError("Object.observe cannot deliver to a frozen function object");if(o===r)o=c;else if(!o||"object"!=typeof o)throw new TypeError("Third argument to Object.observe must be an array of strings.");return l(t,n,o),t},e.unobserve=function(e,t){if(null===e||"object"!=typeof e&&"function"!=typeof e)throw new TypeError("Object.unobserve cannot unobserve non-object");if("function"!=typeof t)throw new TypeError("Object.unobserve cannot deliver to non-function");var n,r=i.get(t);return r&&(n=r.observed.get(e))&&(r.observed.forEach(function(e,t){v(e.data,t)}),p(function(){y(r,t)}),1===r.observed.size&&r.observed.has(e)?i["delete"](t):r.observed["delete"](e),1===n.data.handlers.size?o["delete"](e):n.data.handlers["delete"](t)),e},e.getNotifier=function(t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("Object.getNotifier cannot getNotifier non-object");return e.isFrozen&&e.isFrozen(t)?null:b(t)},e.deliverChangeRecords=function(e){if("function"!=typeof e)throw new TypeError("Object.deliverChangeRecords cannot deliver to non-function");var t=i.get(e);t&&(t.observed.forEach(function(e,t){v(e.data,t)}),y(t,e))}}(Object,Array,this); +} \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/core/templatematching/Test.java b/autojs/src/main/java/com/stardust/autojs/core/templatematching/Test.java deleted file mode 100644 index 63a8e87c..00000000 --- a/autojs/src/main/java/com/stardust/autojs/core/templatematching/Test.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.stardust.autojs.core.templatematching; - -import android.media.Image; - -/** - * Created by Stardust on 2017/10/5. - */ - -public class Test { - - public void test(Image image) { - - } - -} diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/ConvertLayoutInflater.java b/autojs/src/main/java/com/stardust/autojs/core/ui/ConvertLayoutInflater.java deleted file mode 100644 index 3823194d..00000000 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/ConvertLayoutInflater.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.stardust.autojs.core.ui; - -import android.content.Context; -import android.view.View; - -import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater; -import com.stardust.autojs.core.ui.widget.JsFrameLayout; -import com.stardust.autojs.core.ui.xml.XmlConverter; - - -/** - * Created by Stardust on 2017/5/14. - */ - -public class ConvertLayoutInflater implements JsLayoutInflater { - - private DynamicLayoutInflater mDynamicLayoutInflater; - - public ConvertLayoutInflater(DynamicLayoutInflater dynamicLayoutInflater) { - mDynamicLayoutInflater = dynamicLayoutInflater; - } - - @Override - public View inflate(Context context, String xml) { - try { - String androidLayoutXml = XmlConverter.convertToAndroidLayout(xml); - JsFrameLayout root = new JsFrameLayout(context); - mDynamicLayoutInflater.setContext(context); - mDynamicLayoutInflater.inflate(androidLayoutXml, root); - return root; - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/JsLayoutInflater.java b/autojs/src/main/java/com/stardust/autojs/core/ui/JsLayoutInflater.java deleted file mode 100644 index b0635818..00000000 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/JsLayoutInflater.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.stardust.autojs.core.ui; - -import android.content.Context; -import android.view.View; - -/** - * Created by Stardust on 2017/5/14. - */ - -public interface JsLayoutInflater { - - View inflate(Context context, String xml); - -} diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/DynamicLayoutInflater.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/DynamicLayoutInflater.java index 6e5bad88..ff23d8a7 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/DynamicLayoutInflater.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/DynamicLayoutInflater.java @@ -2,6 +2,7 @@ package com.stardust.autojs.core.ui.inflater; import android.content.Context; import android.os.Build; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; @@ -20,20 +21,20 @@ import android.widget.Spinner; import android.widget.TextView; import android.widget.TimePicker; -import com.stardust.autojs.core.ui.inflater.attrsetter.BaseViewAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.DatePickerAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.FrameLayoutAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.ImageViewAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.LinearLayoutAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.ProgressBarAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.RadioGroupAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.SpinnerAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.TextViewAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.TimePickerAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.ToolbarAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.ViewGroupAttrSetter; -import com.stardust.autojs.core.ui.inflater.util.Drawables; +import com.stardust.autojs.core.ui.inflater.inflaters.BaseViewInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.DatePickerInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.FrameLayoutInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.ImageViewInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.LinearLayoutInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.ProgressBarInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.RadioGroupInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.SpinnerInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.TextViewInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.TimePickerInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.ToolbarInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.ViewGroupInflater; import com.stardust.autojs.core.ui.inflater.util.Res; +import com.stardust.autojs.core.ui.xml.XmlConverter; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; @@ -41,8 +42,6 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; import java.util.HashMap; import java.util.Map; @@ -53,16 +52,30 @@ import javax.xml.parsers.DocumentBuilderFactory; public class DynamicLayoutInflater { private static final String LOG_TAG = "DynamicLayoutInflater"; - private Map> mViewAttrSetters = new HashMap<>(); - private Map> mViewCreators = new HashMap<>(); + private Map> mViewAttrSetters = new HashMap<>(); + private Map> mViewCreators = new HashMap<>(); private Context mContext; - private ValueParser mValueParser; + private ResourceParser mResourceParser; + @NonNull + private LayoutInflaterDelegate mLayoutInflaterDelegate = LayoutInflaterDelegate.NO_OP; - public DynamicLayoutInflater(ValueParser valueParser) { - mValueParser = valueParser; + public DynamicLayoutInflater(ResourceParser resourceParser) { + mResourceParser = resourceParser; registerViewAttrSetters(); } + @SuppressWarnings("IncompleteCopyConstructor") + public DynamicLayoutInflater(DynamicLayoutInflater inflater) { + this.mResourceParser = inflater.mResourceParser; + this.mContext = inflater.mContext; + this.mViewAttrSetters = new HashMap<>(inflater.mViewAttrSetters); + this.mViewCreators = new HashMap<>(inflater.mViewCreators); + } + + public ResourceParser getResourceParser() { + return mResourceParser; + } + public Context getContext() { return mContext; } @@ -71,82 +84,121 @@ public class DynamicLayoutInflater { mContext = context; } - protected void registerViewAttrSetters() { - registerViewAttrSetter(TextView.class.getName(), new TextViewAttrSetter<>(mValueParser)); - registerViewAttrSetter(EditText.class.getName(), new TextViewAttrSetter<>(mValueParser)); - registerViewAttrSetter(ImageView.class.getName(), new ImageViewAttrSetter<>(mValueParser)); - registerViewAttrSetter(LinearLayout.class.getName(), new LinearLayoutAttrSetter<>(mValueParser)); - registerViewAttrSetter(FrameLayout.class.getName(), new FrameLayoutAttrSetter<>(mValueParser)); - registerViewAttrSetter(View.class.getName(), new BaseViewAttrSetter<>(mValueParser)); - registerViewAttrSetter(Toolbar.class.getName(), new ToolbarAttrSetter<>(mValueParser)); - registerViewAttrSetter(DatePicker.class.getName(), new DatePickerAttrSetter(mValueParser)); - registerViewAttrSetter(RadioGroup.class.getName(), new RadioGroupAttrSetter<>(mValueParser)); - registerViewAttrSetter(ProgressBar.class.getName(), new ProgressBarAttrSetter<>(mValueParser)); - registerViewAttrSetter(Spinner.class.getName(), new SpinnerAttrSetter(mValueParser)); - registerViewAttrSetter(TimePicker.class.getName(), new TimePickerAttrSetter(mValueParser)); + @NonNull + public LayoutInflaterDelegate getLayoutInflaterDelegate() { + return mLayoutInflaterDelegate; } - public void registerViewAttrSetter(String fullName, ViewAttrSetter setter) { - mViewAttrSetters.put(fullName, setter); - com.stardust.autojs.core.ui.inflater.ViewCreator creator = setter.getCreator(); + public void setLayoutInflaterDelegate(@Nullable LayoutInflaterDelegate layoutInflaterDelegate) { + if (layoutInflaterDelegate == null) + layoutInflaterDelegate = LayoutInflaterDelegate.NO_OP; + mLayoutInflaterDelegate = layoutInflaterDelegate; + } + + protected void registerViewAttrSetters() { + registerViewAttrSetter(TextView.class.getName(), new TextViewInflater<>(mResourceParser)); + registerViewAttrSetter(EditText.class.getName(), new TextViewInflater<>(mResourceParser)); + registerViewAttrSetter(ImageView.class.getName(), new ImageViewInflater<>(mResourceParser)); + registerViewAttrSetter(LinearLayout.class.getName(), new LinearLayoutInflater<>(mResourceParser)); + registerViewAttrSetter(FrameLayout.class.getName(), new FrameLayoutInflater<>(mResourceParser)); + registerViewAttrSetter(View.class.getName(), new BaseViewInflater<>(mResourceParser)); + registerViewAttrSetter(Toolbar.class.getName(), new ToolbarInflater<>(mResourceParser)); + registerViewAttrSetter(DatePicker.class.getName(), new DatePickerInflater(mResourceParser)); + registerViewAttrSetter(RadioGroup.class.getName(), new RadioGroupInflater<>(mResourceParser)); + registerViewAttrSetter(ProgressBar.class.getName(), new ProgressBarInflater<>(mResourceParser)); + registerViewAttrSetter(Spinner.class.getName(), new SpinnerInflater(mResourceParser)); + registerViewAttrSetter(TimePicker.class.getName(), new TimePickerInflater(mResourceParser)); + } + + public void registerViewAttrSetter(String fullName, ViewInflater inflater) { + mViewAttrSetters.put(fullName, inflater); + ViewCreator creator = inflater.getCreator(); if (creator != null) { mViewCreators.put(fullName, creator); } } public View inflate(String xml) { - InputStream inputStream = new ByteArrayInputStream(xml.getBytes()); - return inflate(inputStream); + return inflate(xml, null); } - public View inflate(String xml, ViewGroup parent) { - InputStream inputStream = new ByteArrayInputStream(xml.getBytes()); - return inflate(inputStream, parent); + public View inflate(String xml, @Nullable ViewGroup parent) { + View view = mLayoutInflaterDelegate.beforeInflation(xml, parent); + if (view != null) + return view; + xml = convertXml(xml); + return mLayoutInflaterDelegate.afterInflation(doInflation(xml, parent), xml, parent); } - public View inflate(InputStream inputStream) { - return inflate(inputStream, null); - } - - public View inflate(InputStream inputStream, ViewGroup parent) { + protected View doInflation(String xml, @Nullable ViewGroup parent) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); - Document document = db.parse(inputStream); - return inflate(document.getDocumentElement(), parent); + Document document = db.parse(new ByteArrayInputStream(xml.getBytes())); + return inflate(document.getDocumentElement(), parent, true); + } catch (Exception e) { + throw new InflateException(e); + } + } + + protected String convertXml(String xml) { + String str = mLayoutInflaterDelegate.beforeConvertXml(xml); + if (str != null) + return str; + try { + return mLayoutInflaterDelegate.afterConvertXml(XmlConverter.convertToAndroidLayout(xml)); } catch (Exception e) { throw new InflateException(e); - } finally { - try { - inputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } } } @SuppressWarnings("unchecked") - private View inflate(Node node, ViewGroup parent) { + public View inflate(Node node, @Nullable ViewGroup parent, boolean attachToParent) { + View view = mLayoutInflaterDelegate.beforeInflateView(node, parent, attachToParent); + if (view != null) + return view; HashMap attrs = getAttributesMap(node); - View view = createViewForName(node.getNodeName(), attrs); - if (parent != null) { + view = doCreateView(node, node.getNodeName(), attrs); + if (parent != null && attachToParent) { parent.addView(view); // have to add to parent to enable certain layout attrs } - ViewAttrSetter setter = (ViewAttrSetter) getViewAttrSetter(view); - applyAttributes(view, setter, attrs, parent); - if (view instanceof ViewGroup && node.hasChildNodes()) { - inflateChildren(node, (ViewGroup) view); - if (setter instanceof ViewGroupAttrSetter) { - ((ViewGroupAttrSetter) setter).applyPendingAttributesAboutChildren((ViewGroup) view); - } + ViewInflater inflater = applyAttributes(view, attrs, parent); + if (!(view instanceof ViewGroup) || !node.hasChildNodes()) { + return view; } - return view; + inflateChildren(inflater, node, (ViewGroup) view); + if (inflater instanceof ViewGroupInflater) { + applyPendingAttributesOfChildren((ViewGroupInflater) inflater, (ViewGroup) view); + } + return mLayoutInflaterDelegate.afterInflateView(view, node, parent, attachToParent); + } + + @SuppressWarnings("unchecked") + protected void applyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view) { + if (mLayoutInflaterDelegate.beforeApplyPendingAttributesOfChildren(inflater, view)) { + return; + } + inflater.applyPendingAttributesOfChildren(view); + mLayoutInflaterDelegate.afterApplyPendingAttributesOfChildren(inflater, view); + + } + + + @SuppressWarnings("unchecked") + public ViewInflater applyAttributes(View view, HashMap attrs, @Nullable ViewGroup parent) { + ViewInflater inflater = (ViewInflater) getViewInflater(view); + if (mLayoutInflaterDelegate.beforeApplyAttributes(view, inflater, attrs, parent)) { + return inflater; + } + applyAttributes(view, inflater, attrs, parent); + mLayoutInflaterDelegate.afterApplyAttributes(view, inflater, attrs, parent); + return inflater; } @Nullable - private ViewAttrSetter getViewAttrSetter(View view) { - ViewAttrSetter setter = mViewAttrSetters.get(view.getClass().getName()); + public ViewInflater getViewInflater(View view) { + ViewInflater setter = mViewAttrSetters.get(view.getClass().getName()); Class c = view.getClass(); while (setter == null && c != View.class) { c = c.getSuperclass(); @@ -155,16 +207,34 @@ public class DynamicLayoutInflater { return setter; } - private void inflateChildren(Node node, ViewGroup parent) { + protected void inflateChildren(ViewInflater inflater, Node node, ViewGroup parent) { + if (mLayoutInflaterDelegate.beforeInflateChildren(inflater, node, parent)) { + return; + } + if (inflater.inflateChildren(this, node, parent)) { + return; + } + inflateChildren(node, parent); + mLayoutInflaterDelegate.afterInflateChildren(inflater, node, parent); + } + + public void inflateChildren(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); // this recursively can call inflateChildren + inflate(currentNode, parent, true); } } - private View createViewForName(String name, HashMap attrs) { + protected View doCreateView(Node node, String viewName, HashMap attrs) { + View view = mLayoutInflaterDelegate.beforeCreateView(node, viewName, attrs); + if (view != null) + return view; + return mLayoutInflaterDelegate.afterCreateView(createViewForName(viewName, attrs), node, viewName, attrs); + } + + public View createViewForName(String name, HashMap attrs) { try { if (name.equals("View")) { return new View(mContext); @@ -191,7 +261,7 @@ public class DynamicLayoutInflater { } - private HashMap getAttributesMap(Node currentNode) { + public HashMap getAttributesMap(Node currentNode) { NamedNodeMap attributeMap = currentNode.getAttributes(); int attributeCount = attributeMap.getLength(); HashMap attributes = new HashMap<>(attributeCount); @@ -204,14 +274,14 @@ public class DynamicLayoutInflater { } @SuppressWarnings("unchecked") - private void applyAttributes(View view, ViewAttrSetter setter, Map attrs, ViewGroup parent) { + protected void applyAttributes(View view, ViewInflater setter, Map attrs, @Nullable ViewGroup parent) { if (setter != null) { for (Map.Entry entry : attrs.entrySet()) { String[] attr = entry.getKey().split(":"); if (attr.length == 1) { - setter.setAttr(view, attr[0], entry.getValue(), parent, attrs); + applyAttribute(setter, view, null, attr[0], entry.getValue(), parent, attrs); } else if (attr.length == 2) { - setter.setAttr(view, attr[0], attr[1], entry.getValue(), parent, attrs); + applyAttribute(setter, view, attr[0], attr[1], entry.getValue(), parent, attrs); } else { throw new InflateException("illegal attr name: " + entry.getKey()); } @@ -223,5 +293,14 @@ public class DynamicLayoutInflater { } + protected void applyAttribute(ViewInflater inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map attrs) { + if (mLayoutInflaterDelegate.beforeApplyAttribute(inflater, view, ns, attrName, value, parent, attrs)) { + return; + } + inflater.setAttr(view, ns, attrName, value, parent, attrs); + mLayoutInflaterDelegate.afterApplyAttribute(inflater, view, ns, attrName, value, parent, attrs); + + } + } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/LayoutInflaterDelegate.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/LayoutInflaterDelegate.java new file mode 100644 index 00000000..1ab4340b --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/LayoutInflaterDelegate.java @@ -0,0 +1,136 @@ +package com.stardust.autojs.core.ui.inflater; + +import android.view.View; +import android.view.ViewGroup; + +import com.stardust.autojs.core.ui.inflater.inflaters.ViewGroupInflater; + +import org.w3c.dom.Node; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Stardust on 2018/3/29. + */ + +public interface LayoutInflaterDelegate { + + LayoutInflaterDelegate NO_OP = new NoOp(); + + View beforeInflation(String xml, ViewGroup parent); + + View afterInflation(View doInflation, String xml, ViewGroup parent); + + String beforeConvertXml(String xml); + + String afterConvertXml(String xml); + + View beforeInflateView(Node node, ViewGroup parent, boolean attachToParent); + + View afterInflateView(View view, Node node, ViewGroup parent, boolean attachToParent); + + View beforeCreateView(Node node, String viewName, HashMap attrs); + + View afterCreateView(View view, Node node, String viewName, HashMap attrs); + + boolean beforeApplyAttributes(View view, ViewInflater inflater, HashMap attrs, ViewGroup parent); + + void afterApplyAttributes(View view, ViewInflater inflater, HashMap attrs, ViewGroup parent); + + boolean beforeInflateChildren(ViewInflater inflater, Node node, ViewGroup parent); + + void afterInflateChildren(ViewInflater inflater, Node node, ViewGroup parent); + + void afterApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view); + + boolean beforeApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view); + + boolean beforeApplyAttribute(ViewInflater inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map attrs); + + + void afterApplyAttribute(ViewInflater inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map attrs); + + + class NoOp implements LayoutInflaterDelegate { + @Override + public String beforeConvertXml(String xml) { + return null; + } + + @Override + public String afterConvertXml(String xml) { + return xml; + } + + @Override + public View afterInflation(View result, String xml, ViewGroup parent) { + return result; + } + + @Override + public View beforeInflation(String xml, ViewGroup parent) { + return null; + } + + @Override + public View beforeInflateView(Node node, ViewGroup parent, boolean attachToParent) { + return null; + } + + @Override + public View afterInflateView(View view, Node node, ViewGroup parent, boolean attachToParent) { + return view; + } + + @Override + public View beforeCreateView(Node node, String viewName, HashMap attrs) { + return null; + } + + @Override + public View afterCreateView(View view, Node node, String viewName, HashMap attrs) { + return view; + } + + @Override + public boolean beforeApplyAttributes(View view, ViewInflater inflater, HashMap attrs, ViewGroup parent) { + return false; + } + + @Override + public void afterApplyAttributes(View view, ViewInflater inflater, HashMap attrs, ViewGroup parent) { + + } + + @Override + public boolean beforeInflateChildren(ViewInflater inflater, Node node, ViewGroup parent) { + return false; + } + + @Override + public void afterInflateChildren(ViewInflater inflater, Node node, ViewGroup parent) { + + } + + @Override + public void afterApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view) { + + } + + @Override + public boolean beforeApplyPendingAttributesOfChildren(ViewGroupInflater inflater, ViewGroup view) { + return false; + } + + @Override + public boolean beforeApplyAttribute(ViewInflater inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map attrs) { + return false; + } + + @Override + public void afterApplyAttribute(ViewInflater inflater, View view, String ns, String attrName, String value, ViewGroup parent, Map attrs) { + + } + } +} diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ValueParser.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ResourceParser.java similarity index 79% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ValueParser.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ResourceParser.java index 69a0c023..0c6b3f62 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ValueParser.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ResourceParser.java @@ -6,13 +6,13 @@ import com.stardust.autojs.core.ui.inflater.util.Drawables; * Created by Stardust on 2018/1/24. */ -public class ValueParser { +public class ResourceParser { private final Drawables mDrawables; - public ValueParser(Drawables drawables) { + public ResourceParser(Drawables drawables) { mDrawables = drawables; } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ViewAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ViewInflater.java similarity index 77% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ViewAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ViewInflater.java index dd2b93c5..1d437495 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ViewAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ViewInflater.java @@ -5,6 +5,8 @@ import android.view.View; import android.view.ViewGroup; +import org.w3c.dom.Node; + import java.util.Map; /** @@ -12,7 +14,7 @@ import java.util.Map; */ -public interface ViewAttrSetter { +public interface ViewInflater { boolean setAttr(V view, String attrName, String value, ViewGroup parent, Map attrs); @@ -20,6 +22,8 @@ public interface ViewAttrSetter { void applyPendingAttributes(V view, ViewGroup parent); + boolean inflateChildren(DynamicLayoutInflater inflater, Node node, V parent); + @Nullable ViewCreator getCreator(); } \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/BaseViewAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java similarity index 97% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/BaseViewAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java index de6447c0..b91d8f3a 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/BaseViewAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java @@ -1,4 +1,4 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.content.res.ColorStateList; import android.graphics.PorterDuff; @@ -12,8 +12,9 @@ import android.widget.LinearLayout; import android.widget.RelativeLayout; -import com.stardust.autojs.core.ui.inflater.ValueParser; -import com.stardust.autojs.core.ui.inflater.ViewAttrSetter; +import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater; +import com.stardust.autojs.core.ui.inflater.ResourceParser; +import com.stardust.autojs.core.ui.inflater.ViewInflater; import com.stardust.autojs.core.ui.inflater.ViewCreator; import com.stardust.autojs.core.ui.inflater.util.Colors; import com.stardust.autojs.core.ui.inflater.util.Dimensions; @@ -23,6 +24,8 @@ import com.stardust.autojs.core.ui.inflater.util.Ids; import com.stardust.autojs.core.ui.inflater.util.Strings; import com.stardust.autojs.core.ui.inflater.util.ValueMapper; +import org.w3c.dom.Node; + import java.lang.reflect.Method; import java.util.Map; @@ -30,7 +33,7 @@ import java.util.Map; * Created by Stardust on 2017/11/3. */ -public class BaseViewAttrSetter implements ViewAttrSetter { +public class BaseViewInflater implements ViewInflater { protected static final ValueMapper TINT_MODES = new ValueMapper("tintMode") @@ -91,14 +94,14 @@ public class BaseViewAttrSetter implements ViewAttrSetter { .map("viewEnd", 6) .map("viewStart", 5); - private final ValueParser mValueParser; + private final ResourceParser mResourceParser; - public BaseViewAttrSetter(ValueParser valueParser) { - mValueParser = valueParser; + public BaseViewInflater(ResourceParser resourceParser) { + mResourceParser = resourceParser; } - public Drawables getDrawables(){ - return mValueParser.getDrawables(); + public Drawables getDrawables() { + return mResourceParser.getDrawables(); } @@ -584,7 +587,7 @@ public class BaseViewAttrSetter implements ViewAttrSetter { @Override public boolean setAttr(V view, String ns, String attrName, String value, ViewGroup parent, Map attrs) { - if (ns.equals("android")) { + if (ns == null || ns.equals("android")) { return setAttr(view, attrName, value, parent, attrs); } return false; @@ -606,6 +609,11 @@ public class BaseViewAttrSetter implements ViewAttrSetter { } + @Override + public boolean inflateChildren(DynamicLayoutInflater inflater, Node node, V parent) { + return false; + } + @Nullable @Override public ViewCreator getCreator() { diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/CanvasViewAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/CanvasViewInflater.java similarity index 55% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/CanvasViewAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/CanvasViewInflater.java index a25aa738..5fe1a47b 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/CanvasViewAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/CanvasViewInflater.java @@ -1,26 +1,22 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; -import android.content.Context; import android.support.annotation.Nullable; -import com.stardust.autojs.core.eventloop.EventEmitter; import com.stardust.autojs.core.graphics.ScriptCanvasView; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.ViewCreator; import com.stardust.autojs.runtime.ScriptRuntime; -import java.util.Map; - /** * Created by Stardust on 2018/3/16. */ -public class CanvasViewAttrSetter extends BaseViewAttrSetter { +public class CanvasViewInflater extends BaseViewInflater { private ScriptRuntime mScriptRuntime; - public CanvasViewAttrSetter(ValueParser valueParser, ScriptRuntime runtime) { - super(valueParser); + public CanvasViewInflater(ResourceParser resourceParser, ScriptRuntime runtime) { + super(resourceParser); mScriptRuntime = runtime; } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/DatePickerAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/DatePickerInflater.java similarity index 91% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/DatePickerAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/DatePickerInflater.java index b4d6e73c..b03f73f1 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/DatePickerAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/DatePickerInflater.java @@ -1,4 +1,4 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.os.Build; import android.support.annotation.Nullable; @@ -9,7 +9,7 @@ import android.widget.DatePicker; import com.stardust.autojs.R; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.ViewCreator; import java.text.ParseException; @@ -21,12 +21,12 @@ import java.util.Map; * Created by Stardust on 2017/11/29. */ -public class DatePickerAttrSetter extends BaseViewAttrSetter { +public class DatePickerInflater extends BaseViewInflater { private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("mm/dd/yyyy", Locale.getDefault()); - public DatePickerAttrSetter(ValueParser valueParser) { - super(valueParser); + public DatePickerInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/Exceptions.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/Exceptions.java similarity index 94% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/Exceptions.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/Exceptions.java index 81537d4e..b7ea2c5d 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/Exceptions.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/Exceptions.java @@ -1,4 +1,4 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.view.View; diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/FrameLayoutAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/FrameLayoutInflater.java similarity index 73% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/FrameLayoutAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/FrameLayoutInflater.java index 0bf1c2bc..bfc678db 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/FrameLayoutAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/FrameLayoutInflater.java @@ -1,10 +1,10 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.Gravities; import java.util.Map; @@ -13,12 +13,12 @@ import java.util.Map; * Created by Stardust on 2017/11/29. */ -public class FrameLayoutAttrSetter extends ViewGroupAttrSetter { +public class FrameLayoutInflater extends ViewGroupInflater { private Integer mGravity; - public FrameLayoutAttrSetter(ValueParser valueParser) { - super(valueParser); + public FrameLayoutInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override @@ -31,7 +31,7 @@ public class FrameLayoutAttrSetter extends ViewGroupAttrS } @Override - public void applyPendingAttributesAboutChildren(V view) { + public void applyPendingAttributesOfChildren(V view) { if (mGravity == null) return; for (int i = 0; i < view.getChildCount(); i++) { diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ImageViewAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ImageViewInflater.java similarity index 91% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ImageViewAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ImageViewInflater.java index fb77c0f8..6903b33b 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ImageViewAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ImageViewInflater.java @@ -1,14 +1,13 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.os.Build; import android.view.InflateException; import android.view.ViewGroup; import android.widget.ImageView; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.Colors; import com.stardust.autojs.core.ui.inflater.util.Dimensions; -import com.stardust.autojs.core.ui.inflater.util.Drawables; import java.util.Map; @@ -16,10 +15,10 @@ import java.util.Map; * Created by Stardust on 2017/11/3. */ -public class ImageViewAttrSetter extends BaseViewAttrSetter { +public class ImageViewInflater extends BaseViewInflater { - public ImageViewAttrSetter(ValueParser valueParser) { - super(valueParser); + public ImageViewInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/JsImageViewAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/JsImageViewInflater.java similarity index 91% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/JsImageViewAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/JsImageViewInflater.java index b48357bd..8fda1810 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/JsImageViewAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/JsImageViewInflater.java @@ -1,12 +1,11 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; -import android.content.Context; import android.support.annotation.Nullable; import android.view.ViewGroup; import android.widget.ImageView.ScaleType; import com.makeramen.roundedimageview.Corner; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.ViewCreator; import com.stardust.autojs.core.ui.inflater.util.Colors; import com.stardust.autojs.core.ui.inflater.util.Dimensions; @@ -20,7 +19,7 @@ import java.util.Map; * Created by Stardust on 2017/11/30. */ -public class JsImageViewAttrSetter extends ImageViewAttrSetter { +public class JsImageViewInflater extends ImageViewInflater { protected static final ValueMapper SCALE_TYPES = new ValueMapper("scaleType") @@ -33,8 +32,8 @@ public class JsImageViewAttrSetter extends ImageViewAttrSetter { .map("fitXY", ScaleType.FIT_XY) .map("matrix", ScaleType.MATRIX); - public JsImageViewAttrSetter(ValueParser valueParser) { - super(valueParser); + public JsImageViewInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/JsListViewInflater.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/JsListViewInflater.java new file mode 100644 index 00000000..2f40b566 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/JsListViewInflater.java @@ -0,0 +1,57 @@ +package com.stardust.autojs.core.ui.inflater.inflaters; + +import android.support.annotation.Nullable; +import android.view.ViewGroup; + +import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater; +import com.stardust.autojs.core.ui.inflater.ResourceParser; +import com.stardust.autojs.core.ui.inflater.ViewCreator; +import com.stardust.autojs.core.ui.widget.JsListView; +import com.stardust.autojs.runtime.ScriptRuntime; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.util.Map; + +/** + * Created by Stardust on 2018/3/28. + */ + +public class JsListViewInflater extends BaseViewInflater { + + private ScriptRuntime mRuntime; + + public JsListViewInflater(ResourceParser resourceParser, ScriptRuntime runtime) { + super(resourceParser); + mRuntime = runtime; + } + + @Override + public boolean setAttr(JsListView view, String attr, String value, ViewGroup parent, Map attrs) { + return super.setAttr(view, attr, value, parent, attrs); + } + + @Override + public boolean setAttr(JsListView view, String ns, String attrName, String value, ViewGroup parent, Map attrs) { + return super.setAttr(view, ns, attrName, value, parent, attrs); + } + + @Override + public boolean inflateChildren(DynamicLayoutInflater inflater, Node node, JsListView parent) { + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node child = nodeList.item(i); + if (child.getNodeType() != Node.ELEMENT_NODE) continue; + parent.setItemTemplate(inflater, child); + return true; + } + return false; + } + + @Nullable + @Override + public ViewCreator getCreator() { + return (context, attrs) -> new JsListView(context, mRuntime); + } +} diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/LinearLayoutAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/LinearLayoutInflater.java similarity index 82% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/LinearLayoutAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/LinearLayoutInflater.java index 586c2adb..5ee771ac 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/LinearLayoutAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/LinearLayoutInflater.java @@ -1,10 +1,9 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.view.ViewGroup; import android.widget.LinearLayout; -import com.stardust.autojs.core.ui.inflater.ValueParser; -import com.stardust.autojs.core.ui.inflater.util.Drawables; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.Gravities; import com.stardust.autojs.core.ui.inflater.util.ValueMapper; @@ -14,14 +13,14 @@ import java.util.Map; * Created by Stardust on 2017/11/4. */ -public class LinearLayoutAttrSetter extends ViewGroupAttrSetter { +public class LinearLayoutInflater extends ViewGroupInflater { private static final ValueMapper ORIENTATIONS = new ValueMapper("orientation") .map("vertical", LinearLayout.VERTICAL) .map("horizontal", LinearLayout.HORIZONTAL); - public LinearLayoutAttrSetter(ValueParser valueParser) { - super(valueParser); + public LinearLayoutInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/MapAttrbuteSet.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/MapAttrbuteSet.java similarity index 98% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/MapAttrbuteSet.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/MapAttrbuteSet.java index 9d2b2604..e2b4d90d 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/MapAttrbuteSet.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/MapAttrbuteSet.java @@ -1,4 +1,4 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.util.AttributeSet; diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ProgressBarAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ProgressBarInflater.java similarity index 92% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ProgressBarAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ProgressBarInflater.java index e4fd65cf..a9cc93c1 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ProgressBarAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ProgressBarInflater.java @@ -1,14 +1,13 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.content.res.ColorStateList; import android.os.Build; import android.view.ViewGroup; import android.widget.ProgressBar; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.Colors; import com.stardust.autojs.core.ui.inflater.util.Dimensions; -import com.stardust.autojs.core.ui.inflater.util.Drawables; import java.util.Map; @@ -16,10 +15,10 @@ import java.util.Map; * Created by Stardust on 2017/11/29. */ -public class ProgressBarAttrSetter extends BaseViewAttrSetter { +public class ProgressBarInflater extends BaseViewInflater { - public ProgressBarAttrSetter(ValueParser valueParser) { - super(valueParser); + public ProgressBarInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/RadioGroupAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/RadioGroupInflater.java similarity index 66% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/RadioGroupAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/RadioGroupInflater.java index a92210f6..3ecb5e45 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/RadioGroupAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/RadioGroupInflater.java @@ -1,9 +1,9 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.view.ViewGroup; import android.widget.RadioGroup; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.Ids; import java.util.Map; @@ -12,12 +12,12 @@ import java.util.Map; * Created by Stardust on 2017/11/29. */ -public class RadioGroupAttrSetter extends LinearLayoutAttrSetter { +public class RadioGroupInflater extends LinearLayoutInflater { private Integer mCheckedButton; - public RadioGroupAttrSetter(ValueParser valueParser) { - super(valueParser); + public RadioGroupInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override @@ -31,7 +31,7 @@ public class RadioGroupAttrSetter extends LinearLayoutAttr } @Override - public void applyPendingAttributesAboutChildren(V view) { + public void applyPendingAttributesOfChildren(V view) { if (mCheckedButton != null) { view.check(mCheckedButton); mCheckedButton = null; diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/SpinnerAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/SpinnerInflater.java similarity index 90% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/SpinnerAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/SpinnerInflater.java index 90f4fdb5..c7fb8724 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/SpinnerAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/SpinnerInflater.java @@ -1,4 +1,4 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.content.Context; import android.os.Build; @@ -8,10 +8,9 @@ import android.widget.ArrayAdapter; import android.widget.SimpleAdapter; import android.widget.Spinner; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.ViewCreator; 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.Strings; import com.stardust.autojs.core.ui.inflater.util.ValueMapper; @@ -22,14 +21,14 @@ import java.util.Map; * Created by Stardust on 2017/11/29. */ -public class SpinnerAttrSetter extends BaseViewAttrSetter { +public class SpinnerInflater extends BaseViewInflater { protected static final ValueMapper SPINNER_MODES = new ValueMapper("spinnerMode") .map("dialog", Spinner.MODE_DIALOG) .map("dropdown", Spinner.MODE_DROPDOWN); - public SpinnerAttrSetter(ValueParser valueParser) { - super(valueParser); + public SpinnerInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/TextViewAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/TextViewInflater.java similarity index 98% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/TextViewAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/TextViewInflater.java index 97a30398..f92ae9d9 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/TextViewAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/TextViewInflater.java @@ -1,4 +1,4 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.graphics.Typeface; import android.graphics.drawable.Drawable; @@ -14,10 +14,9 @@ import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.widget.TextView; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.Colors; 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.Res; import com.stardust.autojs.core.ui.inflater.util.Strings; @@ -29,7 +28,7 @@ import java.util.Map; * Created by Stardust on 2017/11/3. */ -public class TextViewAttrSetter extends BaseViewAttrSetter { +public class TextViewInflater extends BaseViewInflater { private static final ValueMapper AUTO_LINK_MASKS = new ValueMapper("autoLink") .map("all", Linkify.ALL) @@ -123,8 +122,8 @@ public class TextViewAttrSetter extends BaseViewAttrSetter { +public class TimePickerInflater extends BaseViewInflater { - public TimePickerAttrSetter(ValueParser valueParser) { - super(valueParser); + public TimePickerInflater(ResourceParser resourceParser) { + super(resourceParser); } @Nullable diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ToolbarAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ToolbarInflater.java similarity index 76% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ToolbarAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ToolbarInflater.java index ea95fee6..80d67acd 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ToolbarAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ToolbarInflater.java @@ -1,9 +1,9 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.support.v7.widget.Toolbar; import android.view.ViewGroup; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.Strings; import java.util.Map; @@ -12,11 +12,11 @@ import java.util.Map; * Created by Stardust on 2017/11/5. */ -public class ToolbarAttrSetter extends BaseViewAttrSetter { +public class ToolbarInflater extends BaseViewInflater { - public ToolbarAttrSetter(ValueParser valueParser) { - super(valueParser); + public ToolbarInflater(ResourceParser resourceParser) { + super(resourceParser); } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ViewGroupAttrSetter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ViewGroupInflater.java similarity index 89% rename from autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ViewGroupAttrSetter.java rename to autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ViewGroupInflater.java index 64df8e2b..dbec63b1 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/attrsetter/ViewGroupAttrSetter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/ViewGroupInflater.java @@ -1,10 +1,10 @@ -package com.stardust.autojs.core.ui.inflater.attrsetter; +package com.stardust.autojs.core.ui.inflater.inflaters; import android.animation.LayoutTransition; import android.os.Build; import android.view.ViewGroup; -import com.stardust.autojs.core.ui.inflater.ValueParser; +import com.stardust.autojs.core.ui.inflater.ResourceParser; import com.stardust.autojs.core.ui.inflater.util.ValueMapper; import java.util.Map; @@ -13,7 +13,7 @@ import java.util.Map; * Created by Stardust on 2017/11/4. */ -public class ViewGroupAttrSetter extends BaseViewAttrSetter { +public class ViewGroupInflater extends BaseViewInflater { private static final ValueMapper PERSISTENT_DRAWING_CACHE = new ValueMapper("persistentDrawingCache") .map("all", ViewGroup.PERSISTENT_ALL_CACHES) @@ -30,8 +30,8 @@ public class ViewGroupAttrSetter extends BaseViewAttrSetter .map("beforeDescendants", ViewGroup.FOCUS_BEFORE_DESCENDANTS) .map("blocksDescendants", ViewGroup.FOCUS_BLOCK_DESCENDANTS); - public ViewGroupAttrSetter(ValueParser valueParser) { - super(valueParser); + public ViewGroupInflater(ResourceParser resourceParser) { + super(resourceParser); } @@ -79,7 +79,7 @@ public class ViewGroupAttrSetter extends BaseViewAttrSetter return true; } - public void applyPendingAttributesAboutChildren(V view) { + public void applyPendingAttributesOfChildren(V view) { } } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java new file mode 100644 index 00000000..8d6b97b9 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsListView.java @@ -0,0 +1,117 @@ +package com.stardust.autojs.core.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; + +import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater; +import com.stardust.autojs.core.ui.inflater.ViewInflater; +import com.stardust.autojs.runtime.ScriptRuntime; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.util.Map; + +/** + * Created by Stardust on 2018/3/28. + */ + +public class JsListView extends RecyclerView { + + public interface DataSourceAdapter { + + int getItemCount(Object dataSource); + + Object getItem(Object dataSource, int i); + + void setDataSource(Object dataSource); + } + + private Node mItemTemplate; + private DynamicLayoutInflater mDynamicLayoutInflater; + private ScriptRuntime mScriptRuntime; + private Object mDataSource; + private DataSourceAdapter mDataSourceAdapter; + + public JsListView(Context context, ScriptRuntime scriptRuntime) { + super(context); + mScriptRuntime = scriptRuntime; + init(); + } + + private void init() { + setAdapter(new Adapter()); + setLayoutManager(new LinearLayoutManager(getContext())); + } + + public void setDataSourceAdapter(DataSourceAdapter dataSourceAdapter) { + mDataSourceAdapter = dataSourceAdapter; + getAdapter().notifyDataSetChanged(); + } + + public Object getDataSource() { + return mDataSource; + } + + public void setDataSource(Object dataSource) { + mDataSource = dataSource; + if (mDataSourceAdapter != null) + mDataSourceAdapter.setDataSource(dataSource); + getAdapter().notifyDataSetChanged(); + } + + public void setItemTemplate(DynamicLayoutInflater inflater, Node itemTemplate) { + mDynamicLayoutInflater = inflater; + mItemTemplate = itemTemplate; + } + + private class ViewHolder extends RecyclerView.ViewHolder { + + public ViewHolder(View itemView) { + super(itemView); + } + } + + private class Adapter extends RecyclerView.Adapter { + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new ViewHolder(mDynamicLayoutInflater.inflate(mItemTemplate, parent, false)); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + Object oldCtx = mScriptRuntime.ui.getBindingContext(); + mScriptRuntime.ui.setBindingContext(mDataSourceAdapter.getItem(mDataSource, position)); + applyDynamicAttrs(mItemTemplate, holder.itemView, (ViewGroup) holder.itemView.getParent()); + mScriptRuntime.ui.setBindingContext(oldCtx); + } + + private void applyDynamicAttrs(Node node, View itemView, ViewGroup parent) { + mDynamicLayoutInflater.applyAttributes(itemView, mDynamicLayoutInflater.getAttributesMap(node), parent); + if (!(itemView instanceof ViewGroup)) + return; + ViewGroup viewGroup = (ViewGroup) itemView; + NodeList nodeList = node.getChildNodes(); + int j = 0; + for (int i = 0; i < nodeList.getLength(); i++) { + Node child = nodeList.item(i); + if (child.getNodeType() != Node.ELEMENT_NODE) continue; + applyDynamicAttrs(child, viewGroup.getChildAt(j), viewGroup); + j++; + } + } + + @Override + public int getItemCount() { + return mDataSource == null ? 0 + : mDataSourceAdapter == null ? 0 + : mDataSourceAdapter.getItemCount(mDataSource); + } + } + +} diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/xml/XmlConverter.java b/autojs/src/main/java/com/stardust/autojs/core/ui/xml/XmlConverter.java index 609386e2..eea0ad5f 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/xml/XmlConverter.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/xml/XmlConverter.java @@ -1,5 +1,6 @@ package com.stardust.autojs.core.ui.xml; +import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.webkit.WebView; import android.widget.CheckBox; @@ -18,6 +19,7 @@ import com.stardust.autojs.core.ui.widget.JsEditText; import com.stardust.autojs.core.ui.widget.JsFrameLayout; import com.stardust.autojs.core.ui.widget.JsImageView; import com.stardust.autojs.core.ui.widget.JsLinearLayout; +import com.stardust.autojs.core.ui.widget.JsListView; import com.stardust.autojs.core.ui.widget.JsRelativeLayout; import com.stardust.autojs.core.ui.widget.JsTextView; import com.stardust.autojs.core.ui.widget.JsWebView; @@ -66,6 +68,7 @@ public class XmlConverter { .map("scroll", ScrollView.class.getName()) .map("toolbar", Toolbar.class.getName()) .map("canvas", ScriptCanvasView.class.getName()) + .map("list", JsListView.class.getName()) ); private static final AttributeHandler ATTRIBUTE_HANDLER = new AttributeHandler.AttrNameRouter() diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java index 570088cf..e1c77afa 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java @@ -18,6 +18,8 @@ public class ScriptBridges { Object toArray(Object o); Object toString(Object obj); + + Object eval(Object context, String expr); } private Bridges mBridges; @@ -47,4 +49,10 @@ public class ScriptBridges { checkBridges(); return mBridges.toString(obj); } + + public Object eval(Object context, String expr) { + checkBridges(); + return mBridges.eval(context, expr); + + } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java index ac95f3c0..73c064f2 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java @@ -212,7 +212,7 @@ public class ScriptRuntime { device = new Device(context); floaty = new Floaty(uiHandler, ui, this); files = new Files(this); - media = new Media(context); + media = new Media(context, this); } public void init() { diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java index e6c50ff6..e8b89347 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Floaty.java @@ -8,8 +8,8 @@ import android.view.View; import com.stardust.autojs.R; import com.stardust.autojs.core.floaty.FloatyWindow; -import com.stardust.autojs.core.ui.JsLayoutInflater; import com.stardust.autojs.core.ui.JsViewHelper; +import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.util.FloatingPermission; @@ -26,7 +26,7 @@ import java.util.concurrent.CopyOnWriteArraySet; public class Floaty { - private JsLayoutInflater mJsLayoutInflater; + private DynamicLayoutInflater mLayoutInflater; private Context mContext; private UiHandler mUiHandler; private CopyOnWriteArraySet mWindows = new CopyOnWriteArraySet<>(); @@ -36,7 +36,7 @@ public class Floaty { mUiHandler = uiHandler; mRuntime = runtime; mContext = new ContextThemeWrapper(mUiHandler.getContext(), R.style.AppTheme); - mJsLayoutInflater = ui.getJsLayoutInflater(); + mLayoutInflater = ui.getLayoutInflater(); } public JsFloatyWindow window(String xml) { @@ -64,10 +64,10 @@ public class Floaty { private View inflate(String xml) { if (Looper.getMainLooper() == Looper.myLooper()) { - return mJsLayoutInflater.inflate(mContext, xml); + return mLayoutInflater.inflate(xml); } else { VolatileDispose dispose = new VolatileDispose<>(); - mUiHandler.post(() -> dispose.setAndNotify(mJsLayoutInflater.inflate(mContext, xml))); + mUiHandler.post(() -> dispose.setAndNotify(mLayoutInflater.inflate(xml))); return dispose.blockedGetOrThrow(ScriptInterruptedException.class); } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Media.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Media.java index 8ea7fe70..b1008920 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Media.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Media.java @@ -5,6 +5,7 @@ import android.media.MediaPlayer; import android.media.MediaScannerConnection; import android.net.Uri; +import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.pio.UncheckedIOException; import com.stardust.util.MimeTypes; @@ -18,15 +19,17 @@ public class Media implements MediaScannerConnection.MediaScannerConnectionClien private MediaScannerConnection mScannerConnection; private MediaPlayerWrapper mMediaPlayer; + private ScriptRuntime mRuntime; - public Media(Context context) { + public Media(Context context, ScriptRuntime runtime) { mScannerConnection = new MediaScannerConnection(context, this); + mRuntime = runtime; mScannerConnection.connect(); } public void scanFile(String path) { String mimeType = MimeTypes.fromFileOr(path, null); - mScannerConnection.scanFile(path, mimeType); + mScannerConnection.scanFile(mRuntime.files.path(path), mimeType); } @Override @@ -43,6 +46,7 @@ public class Media implements MediaScannerConnection.MediaScannerConnectionClien } public void playMusic(String path, float volume, boolean looping) { + path = mRuntime.files.path(path); if (mMediaPlayer == null) { mMediaPlayer = new MediaPlayerWrapper(); } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java index 06dfaaff..dfdcb9bf 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java @@ -4,13 +4,13 @@ import android.content.Context; import android.graphics.drawable.Drawable; import com.stardust.autojs.core.graphics.ScriptCanvasView; -import com.stardust.autojs.core.ui.ConvertLayoutInflater; -import com.stardust.autojs.core.ui.JsLayoutInflater; import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater; -import com.stardust.autojs.core.ui.inflater.ValueParser; -import com.stardust.autojs.core.ui.inflater.attrsetter.CanvasViewAttrSetter; -import com.stardust.autojs.core.ui.inflater.attrsetter.JsImageViewAttrSetter; +import com.stardust.autojs.core.ui.inflater.ResourceParser; +import com.stardust.autojs.core.ui.inflater.inflaters.CanvasViewInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.JsImageViewInflater; +import com.stardust.autojs.core.ui.inflater.inflaters.JsListViewInflater; import com.stardust.autojs.core.ui.widget.JsImageView; +import com.stardust.autojs.core.ui.widget.JsListView; import com.stardust.autojs.rhino.ProxyObject; import com.stardust.autojs.runtime.ScriptRuntime; @@ -29,26 +29,36 @@ public class UI extends ProxyObject { private Context mContext; private Map mProperties = new ConcurrentHashMap<>(); - private JsLayoutInflater mJsLayoutInflater; + private DynamicLayoutInflater mDynamicLayoutInflater; private ScriptRuntime mRuntime; - private ValueParser mValueParser; + private ResourceParser mResourceParser; public UI(Context context, ScriptRuntime runtime) { mContext = context; mRuntime = runtime; - mValueParser = new ValueParser(new Drawables()); - DynamicLayoutInflater inflater = new DynamicLayoutInflater(mValueParser); - inflater.registerViewAttrSetter(JsImageView.class.getName(), - new JsImageViewAttrSetter(mValueParser)); - inflater.registerViewAttrSetter(ScriptCanvasView.class.getName(), - new CanvasViewAttrSetter(mValueParser, runtime)); - mJsLayoutInflater = new ConvertLayoutInflater(inflater); - mProperties.put("layoutInflater", mJsLayoutInflater); + mResourceParser = new ResourceParser(new Drawables()); + mDynamicLayoutInflater = new DynamicLayoutInflater(mResourceParser); + mDynamicLayoutInflater.setContext(context); + mDynamicLayoutInflater.registerViewAttrSetter(JsImageView.class.getName(), + new JsImageViewInflater(mResourceParser)); + mDynamicLayoutInflater.registerViewAttrSetter(JsListView.class.getName(), + new JsListViewInflater(mResourceParser, runtime)); + mDynamicLayoutInflater.registerViewAttrSetter(ScriptCanvasView.class.getName(), + new CanvasViewInflater(mResourceParser, runtime)); + mProperties.put("layoutInflater", this.mDynamicLayoutInflater); + } + + public Object getBindingContext() { + return mProperties.get("bindingContext"); + } + + public void setBindingContext(Object context) { + mProperties.put("bindingContext", context); } - public JsLayoutInflater getJsLayoutInflater() { - return mJsLayoutInflater; + public DynamicLayoutInflater getLayoutInflater() { + return mDynamicLayoutInflater; } @Override @@ -59,16 +69,24 @@ public class UI extends ProxyObject { @Override public Object get(String name, Scriptable start) { - Object value = super.get(name, start); - if (value != null && value != UniqueTag.NOT_FOUND && !value.equals(org.mozilla.javascript.Context.getUndefinedValue())) { - return value; - } - value = mProperties.get(name); + Object value = mProperties.get(name); if (value != null) return value; - return UniqueTag.NOT_FOUND; + return super.get(name, start); } + @Override + public void put(String name, Scriptable start, Object value) { + if (mProperties.containsKey(name)) { + if (value == null) { + mProperties.remove(name); + } else { + mProperties.put(name, value); + } + } else { + super.put(name, start, value); + } + } private class Drawables extends com.stardust.autojs.core.ui.inflater.util.Drawables {