diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..65f66343
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+# Idea
+.Idea
+
+# Xcode
+*.xcuserstate
+project.xcworkspace/
+xcuserdata/
+
+# others
+.git_old_branch
+
+# Pods
+TaobaoEnv
+IOS/Demo/Pods/*
diff --git a/Android/.gitignore b/Android/.gitignore
new file mode 100644
index 00000000..c286a992
--- /dev/null
+++ b/Android/.gitignore
@@ -0,0 +1,9 @@
+# Created by .ignore support plugin (hsz.mobi)
+# IntelliJ project files
+.idea
+.gradle
+build
+gradle
+local.properties
+*.iml
+build/intermediates/dex-cache/cache.xml
\ No newline at end of file
diff --git a/Android/.gradle/2.2/taskArtifacts/cache.properties.lock b/Android/.gradle/2.2/taskArtifacts/cache.properties.lock
new file mode 100644
index 00000000..b821389f
Binary files /dev/null and b/Android/.gradle/2.2/taskArtifacts/cache.properties.lock differ
diff --git a/Android/.gradle/2.2/taskArtifacts/fileHashes.bin b/Android/.gradle/2.2/taskArtifacts/fileHashes.bin
new file mode 100644
index 00000000..ef6abf8c
Binary files /dev/null and b/Android/.gradle/2.2/taskArtifacts/fileHashes.bin differ
diff --git a/Android/.gradle/2.2/taskArtifacts/fileSnapshots.bin b/Android/.gradle/2.2/taskArtifacts/fileSnapshots.bin
new file mode 100644
index 00000000..ea706a56
Binary files /dev/null and b/Android/.gradle/2.2/taskArtifacts/fileSnapshots.bin differ
diff --git a/Android/.gradle/2.2/taskArtifacts/outputFileStates.bin b/Android/.gradle/2.2/taskArtifacts/outputFileStates.bin
new file mode 100644
index 00000000..56023c2d
Binary files /dev/null and b/Android/.gradle/2.2/taskArtifacts/outputFileStates.bin differ
diff --git a/Android/.gradle/2.2/taskArtifacts/taskArtifacts.bin b/Android/.gradle/2.2/taskArtifacts/taskArtifacts.bin
new file mode 100644
index 00000000..5bd253b3
Binary files /dev/null and b/Android/.gradle/2.2/taskArtifacts/taskArtifacts.bin differ
diff --git a/Android/LICENSE b/Android/LICENSE
new file mode 100644
index 00000000..f2d12cc5
--- /dev/null
+++ b/Android/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Alibaba Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/Android/LuaViewDemo/.gitignore b/Android/LuaViewDemo/.gitignore
new file mode 100644
index 00000000..b3fdf275
--- /dev/null
+++ b/Android/LuaViewDemo/.gitignore
@@ -0,0 +1,2 @@
+build
+target
\ No newline at end of file
diff --git a/Android/LuaViewDemo/AndroidManifest.xml b/Android/LuaViewDemo/AndroidManifest.xml
new file mode 100644
index 00000000..27ba6fb2
--- /dev/null
+++ b/Android/LuaViewDemo/AndroidManifest.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/LuaViewDemo.iml b/Android/LuaViewDemo/LuaViewDemo.iml
new file mode 100644
index 00000000..5a9396ff
--- /dev/null
+++ b/Android/LuaViewDemo/LuaViewDemo.iml
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/luaview/test.szip b/Android/LuaViewDemo/assets/luaview/test.szip
new file mode 100644
index 00000000..f9727acc
Binary files /dev/null and b/Android/LuaViewDemo/assets/luaview/test.szip differ
diff --git a/Android/LuaViewDemo/assets/test-standard/NUI_AudioPlayer.lua b/Android/LuaViewDemo/assets/test-standard/NUI_AudioPlayer.lua
new file mode 100644
index 00000000..2d870595
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test-standard/NUI_AudioPlayer.lua
@@ -0,0 +1,65 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+w, h = System:screenSize();
+
+local player1 = AudioPlayer();
+
+button1 = Button();
+button1:title("播放音效-url");
+button1:callback(function()
+ if (player1) then
+ player1:play("http://dx.sc.chinaz.com/files/download/sound1/201308/3381.wav", 2);
+ end
+end)
+
+button2 = Button();
+button2:title("播放音效-本地");
+button2:xy(200, 0)
+button2:callback(function()
+ if (player1) then
+ player1:play("music/test.mp3", 0);
+ end
+end)
+
+button1_pause = Button();
+button1_pause:title("pause")
+button1_pause:xy(0, 50)
+button1_pause:callback(function()
+ if (player1) then
+ player1:pause();
+ end
+end)
+
+button1_resume = Button();
+button1_resume:title("resume")
+button1_resume:xy(200, 50)
+button1_resume:callback(function()
+ if (player1) then
+ player1:resume();
+ end
+end)
+
+t = {
+ a = function()
+ print('a called', t.c)
+ end,
+ b = function()
+ print('b called', t.c)
+ end,
+ c = 1
+}
+
+t.a()
+t.b()
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test-standard/NUI_DynamicCode.lua b/Android/LuaViewDemo/assets/test-standard/NUI_DynamicCode.lua
new file mode 100644
index 00000000..8ede8555
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test-standard/NUI_DynamicCode.lua
@@ -0,0 +1,35 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+code = [[
+ a = {}
+ a.x = function()
+ local btn = Button()
+ btn:frame(0, 0, 100, 100)
+ btn:text("button")
+-- btn:callback(function
+-- Toast("btn clicked")
+-- end)
+ end
+
+ a.x()
+]]
+
+
+--hi = load(code)
+--hi()
+
+
+
+load("local btn = Button(); btn:text('yyy'); btn:callback(function Toast('x') end)")()
+
+
diff --git a/Android/LuaViewDemo/assets/test-standard/NUI_File.lua b/Android/LuaViewDemo/assets/test-standard/NUI_File.lua
new file mode 100644
index 00000000..c3b2bfc0
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test-standard/NUI_File.lua
@@ -0,0 +1,97 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+
+local label = Label()
+label:text("请看日志输出")
+label:frame(0, 0, System.screenSize())
+
+http = Http()
+http:get("http://www.baidu.com", {
+ query = 1
+}, function(response)
+ local data = response:data()
+
+ print(data)
+ test1(data)
+ test2(data)
+ test3(data)
+end)
+
+
+function test1(data)
+ print("-------------------------test1---------------------")
+ print("save", File.save(data, "test.html"))
+ print("read", File.read("test.html"))
+ print("path", File.path("test.html"))
+ print("exists", File.exists("test.html"))
+ print("--------------------------test1---------------------")
+end
+
+function test2(data)
+ print("-------------------------test2---------------------")
+ print("save", File.save(data, "demo/test.html"))
+ print("read", File.read("demo/test.html"))
+ print("path", File.path("demo/test.html"))
+ print("exists", File.exists("demo/test.html"))
+ print("--------------------------test2---------------------")
+end
+
+function test3(data)
+ print("-------------------------test3---------------------")
+ print("save", File.save(data, "../../../common/test.html"))
+ print("read", File.read("../../../common/test.html"))
+ print("path", File.path("../../../common/test.html"))
+ print("exists", File.exists("../../../common/test.html"))
+ print("--------------------------test3---------------------")
+end
+
+function test4(data)
+ print("-------------------------test4---------------------")
+
+ File.save(data, "test1.html", function(status)
+ print("file saved", status, File.exists("test1.html"))
+ print("read1", File.read("test1.html"), "xxx")
+
+
+ print("path2", File.path("test1.html"))
+ print("exists1", File.exists("test1.html"))
+ print("exists3", File.exists("test2.html"))
+
+ File.read("test1.html", function(data)
+ print("read2", data)
+ print("-------------------------test4---------------------")
+ end)
+ end)
+
+
+end
+
+
+
+
+http = Http()
+http:get("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg", function(response)
+ local data = response:data()
+
+ File.save(data, "../common/test.png")
+
+ File.read("../common/test.png", function(data)
+ local img = Image()
+ img:frame(0, 0, 100, 100)
+ img:image("../common/test.png")
+
+ local img2 = Image()
+ img2:frame(101, 0, 100, 100)
+ img2:image(data)
+ end)
+end)
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test-standard/UI_HScrollView.lua b/Android/LuaViewDemo/assets/test-standard/UI_HScrollView.lua
new file mode 100644
index 00000000..f1462922
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test-standard/UI_HScrollView.lua
@@ -0,0 +1,26 @@
+-- 活动指示器
+local SCREEN_WIDTH = System:screenSize()
+
+local scrollView = HScrollView()
+
+
+for i = 0, 10, 1 do
+ local btn = Label()
+ btn:text("BTN" .. i)
+ btn:frame(i * 60, 10, 59, 80)
+ btn:backgroundColor(0xff00ff00)
+ scrollView:addView(btn)
+end
+
+scrollView:xy(0, 300)
+scrollView:size(SCREEN_WIDTH, 100)
+scrollView:backgroundColor(0xffcccccc)
+scrollView:showScrollIndicator(false)
+
+
+scrollView:callback({
+ Scrolling = function(x, y)
+ print("Scrolling", x, y)
+ print(scrollView:offset())
+ end
+})
diff --git a/Android/LuaViewDemo/assets/test-standard/music/test.mp3 b/Android/LuaViewDemo/assets/test-standard/music/test.mp3
new file mode 100644
index 00000000..6ce1f6ee
Binary files /dev/null and b/Android/LuaViewDemo/assets/test-standard/music/test.mp3 differ
diff --git a/Android/LuaViewDemo/assets/test/11UI_Matrix.lua b/Android/LuaViewDemo/assets/test/11UI_Matrix.lua
new file mode 100644
index 00000000..9e57074f
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/11UI_Matrix.lua
@@ -0,0 +1,24 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+view = Image();
+view.backgroundColor(0xff0000, 0.3)
+view.image("animate1")
+view.frame(0, 64, 200, 200)
+
+view.callback(function()
+ --view.matrix( {2,3,4,5,6,7} );
+ view.matrix(1, 2, 1, 1, 0, 1);
+
+ arr = view.matrix();
+ print(arr[1],arr[2],arr[3],arr[4],arr[5],arr[6] );
+
+ view.invalidate()
+
+ Toast("done")
+
+end)
+
diff --git a/Android/LuaViewDemo/assets/test/DEMO_Time.lua b/Android/LuaViewDemo/assets/test/DEMO_Time.lua
new file mode 100644
index 00000000..beb3eeb8
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/DEMO_Time.lua
@@ -0,0 +1,44 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+view1 = View()
+view1.cornerRadius(25)
+view1.frame(50, 50, 100, 20)
+view1.backgroundColor(0x0000ff, 0.5)
+
+
+container = View()
+container.frame(51, 51, 10, 20)
+
+
+view2 = View()
+container.addView(view2)
+view2.cornerRadius(25)
+view2.frame(0, 0, 98, 18)
+view2.backgroundColor(0xff0000, 0.8)
+
+local time = os:time();
+local t = os:date("*t", time);
+print("time", time, "t.year", t.year, "t.month", t.month,"t.day", t.day,"t.hour", t.hour,"t.min", t.min,"t.sec", t.sec);
+local tb1 = {year=t.year, month=t.month, day=t.day, hour=10, min=0, sec=0, isdst=false};
+local time1 = os:time(tb1) * 1000;
+print("time1", time1);
+
+local tb2 = {year=t.year, month=t.month, day=t.day, hour=20, min=0, sec=0, isdst=false};
+local time2 = os:time(tb2) * 1000;
+print("time2", time2);
+
+local tb3 = {year=t.year, month=t.month, day=t.day, hour=25, min=0, sec=0, isdst=false};
+local time3 = os:time(tb3) * 1000;
+print("time3", time3);
+
+local tb4 = {year=t.year, month=t.month, day=t.day, min=0, sec=0, isdst=false};
+local time4 = os:time(tb4) * 1000;
+print("time4", time4);
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/NUI_AudioPlayer.lua b/Android/LuaViewDemo/assets/test/NUI_AudioPlayer.lua
new file mode 100644
index 00000000..69f8f501
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_AudioPlayer.lua
@@ -0,0 +1,53 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+w, h = System.screenSize();
+
+
+local player1 = AudioPlayer();
+
+button1 = Button();
+button1.title("播放音效-url");
+button1.callback(function()
+ if (player1) then
+ player1.play("http://dx.sc.chinaz.com/files/download/sound1/201308/3381.wav", 2);
+ end
+end)
+
+button2 = Button();
+button2.title("播放音效-本地");
+button2.xy(200, 0)
+button2.callback(function()
+ if (player1) then
+ player1.play("music/test.mp3", 0);
+ end
+end)
+
+button1_pause = Button();
+button1_pause.title("pause")
+button1_pause.xy(0, 50)
+button1_pause.callback(function()
+ if (player1) then
+ player1.pause();
+ end
+end)
+
+button1_resume = Button();
+button1_resume.title("resume")
+button1_resume.xy(200, 50)
+button1_resume.callback(function()
+ if (player1) then
+ player1.resume();
+ end
+end)
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/NUI_Bridge.lua b/Android/LuaViewDemo/assets/test/NUI_Bridge.lua
new file mode 100644
index 00000000..7efd2b73
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_Bridge.lua
@@ -0,0 +1,28 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+local label = Label()
+label.text("请看日志输出")
+label.frame(0, 0, System.screenSize())
+
+
+bridge.testParams({"a", "b"})
+
+bridge.testParams({aa="a", bb="b"})
+
+-- 从Native注册一个bridge对象给lua,并在lua中调用native函数
+print("Map", type(bridge.testMap()), bridge.testMap(), bridge.testMap().get("key1"))
+print("List", type(bridge.testList()), bridge.testList(), bridge.testList().get(1))
+print("String", type(bridge.testString()), bridge.testString())
+print("int", type(bridge.testInt()), bridge.testInt())
+print("Int2", type(bridge.testInt2()), bridge.testInt2())
+print("long", type(bridge.testLong()), bridge.testLong())
+print("Long2", type(bridge.testLong2()), bridge.testLong2())
+print("double", type(bridge.testDouble()), bridge.testDouble())
+print("Double2", type(bridge.testDouble2()), bridge.testDouble2())
+print("boolean", type(bridge.testBoolean()), bridge.testBoolean())
+print("Boolean", type(bridge.testBoolean2()), bridge.testBoolean2())
+
diff --git a/Android/LuaViewDemo/assets/test/NUI_CallLua.lua b/Android/LuaViewDemo/assets/test/NUI_CallLua.lua
new file mode 100644
index 00000000..03dae0f8
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_CallLua.lua
@@ -0,0 +1,51 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+-- 全局函数
+function global_fun_test1(a, b, c)
+ print("global_fun_test1 called params:", a, b, c)
+ return "global_fun_test1"
+end
+
+
+function global_fun_test2(a, b, c)
+ print("global_fun_test2 called params:", a, b, c)
+ return {
+ "global_fun_test2_a",
+ "global_fun_test2_b"
+ }
+end
+
+-- 注册window的回调函数
+window.callback({
+ onHide=function()
+ print("onHide")
+ end,
+ window_fun1 = function(a, b, c)
+ print("window_fun1 called params:", a, b, c)
+ return "window_fun1"
+ end,
+ window_fun2 = function(a, b, c)
+ print("window_fun2 called params:", a, b, c)
+ return 2
+ end
+})
+
+
+local title = Label()
+
+title.text("请看后台log输出")
+title.frame(0, 0, 200, 200)
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/NUI_DataAndJson.lua b/Android/LuaViewDemo/assets/test/NUI_DataAndJson.lua
new file mode 100644
index 00000000..7a99251d
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_DataAndJson.lua
@@ -0,0 +1,86 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+require("kit/lv_kit")
+
+
+local label = Label()
+label.text("请看日志输出")
+label.frame(0, 0, System.screenSize())
+
+
+data = Data(97, "abc", "def")
+print("1", data)
+
+
+data1 = Data("a")
+data2 = Data("b")
+
+print("2", data1 + data2)
+
+
+print("3", Data('a').toString("latin-1"))
+
+printTable("4", Data('{"a":"1"}').toTable())
+
+print("5", Data('{"a":"1"}').toJson())
+
+-- not json
+print("6", Data('a').toJson())
+
+print("7", Data('{"a":"1"}'))
+
+
+print("-----Json------")
+
+printTable("8", Json.toTable('{"a":"1"}'))
+
+printTable("9", Json.toTable(Data('{"a":"1"}')))
+
+printTable("10", Json.toTable("a"))
+
+printTable("11", Json.toTable())
+
+
+print("-----isValid------")
+
+print("12", Json.isValid('{"a":"1"}'))
+
+print("13", Json.isValid(Data('{"a":"1"}')))
+
+print("14", Json.isValid("a"))
+
+print("15", Json.isValid())
+
+print("-----nil------")
+print("16")
+local table = Json.toTable('{}')
+printTable(table)
+
+print("17")
+table = Json.toTable('')
+printTable(table)
+
+print("18")
+printTable(Json.toTable({
+ a = '1'
+}))
+
+print("-----async------")
+Json.toTable('{"a":"1"}', function(result)
+ print("19")
+ printTable(result)
+end)
+
+data = '{"a"=1,"b"="3","c"={"c1"=1}}'
+printTable(Json.toTable(data))
+
+Json.toTable(data, function(result)
+ printTable(result)
+end)
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/NUI_DynamicCode.lua b/Android/LuaViewDemo/assets/test/NUI_DynamicCode.lua
new file mode 100644
index 00000000..939534d7
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_DynamicCode.lua
@@ -0,0 +1,56 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+
+---------------------------------------------------------------------------
+print("case1:")
+
+code = [[
+ param = "Hello world!!!"
+ print(param)
+]]
+
+
+hi = load(code)
+hi()
+
+---------------------------------------------------------------------------
+
+print("case2:")
+
+hi2 = load("param = param .. 'ha ha ha '; x = 1; x = x+1; print(param, x)")
+hi2()
+
+hi3 = load("x=x+1; print(param, x)")
+hi3()
+
+hi4 = load("fun = function() print('this is a function') end")
+hi4()
+fun()
+
+fun2 = nil
+hi5 = load("fun2 = function(p) print('this is a function', p) end")
+hi5()
+fun2("hahaha")
+
+
+
+---------------------------------------------------------------------------
+print("case3:")
+
+x = "hello abc"
+
+dump = string:dump(function() print(x) end)
+
+hello = load(dump)
+hello()
+
+---------------------------------------------------------------------------
+print("case4:")
+
+audioplayer = loadfile("NUI_AudioPlayer.lua")
+audioplayer()
+
diff --git a/Android/LuaViewDemo/assets/test/NUI_File.lua b/Android/LuaViewDemo/assets/test/NUI_File.lua
new file mode 100644
index 00000000..f906aa0e
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_File.lua
@@ -0,0 +1,92 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+require "kit/lv_kit"
+
+local label = Label()
+label.text("请看日志输出")
+label.frame(0, 0, System.screenSize())
+
+http = Http()
+http.get("http://www.baidu.com", {
+ query = 1
+}, function(response)
+ local data = response:data()
+
+ print(data)
+ test1(data)
+ test2(data)
+ test3(data)
+end)
+
+
+function test1(data)
+ print("-------------------------test1---------------------")
+ print("save", File.save(data, "test.html"))
+ print("read", File.read("test.html"))
+ print("path", File.path("test.html"))
+ print("exists", File.exists("test.html"))
+ print("--------------------------test1---------------------")
+end
+
+function test2(data)
+ print("-------------------------test2---------------------")
+ print("save", File.save(data, "demo/test.html"))
+ print("read", File.read("demo/test.html"))
+ print("path", File.path("demo/test.html"))
+ print("exists", File.exists("demo/test.html"))
+ print("--------------------------test2---------------------")
+end
+
+function test3(data)
+ print("-------------------------test3---------------------")
+ print("save", File.save(data, "../../../common/test.html"))
+ print("read", File.read("../../../common/test.html"))
+ print("path", File.path("../../../common/test.html"))
+ print("exists", File.exists("../../../common/test.html"))
+ print("--------------------------test3---------------------")
+end
+
+function test4(data)
+ print("-------------------------test4---------------------")
+
+ File.save(data, "test1.html", function(status)
+ print("file saved", status, File.exists("test1.html"))
+ print("read1", File.read("test1.html"), "xxx")
+
+
+ print("path2", File.path("test1.html"))
+ print("exists1", File.exists("test1.html"))
+ print("exists3", File.exists("test2.html"))
+
+ File.read("test1.html", function(data)
+ print("read2", data)
+ print("-------------------------test4---------------------")
+ end)
+ end)
+
+
+end
+
+
+
+
+http = Http()
+http.get("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg", function(response)
+ local data = response:data()
+
+ File.save(data, "../common/test.png")
+
+ File.read("../common/test.png", function(data)
+ local img = Image()
+ img.frame(0, 0, 100, 100)
+ img.image("../common/test.png")
+
+ local img2 = Image()
+ img2.frame(101, 0, 100, 100)
+ img2.image(data)
+ end)
+end)
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/NUI_Http.lua b/Android/LuaViewDemo/assets/test/NUI_Http.lua
new file mode 100644
index 00000000..6a9dcfe2
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_Http.lua
@@ -0,0 +1,22 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+require "kit/lv_kit"
+
+local label = Label()
+label.text("请看日志输出")
+label.frame(0, 0, System.screenSize())
+
+http = Http()
+http.get("http://www.baidu.com", {
+ query = 1
+}, function(response)
+ print(response)
+ printTable(response)
+ print(response.data())
+end)
+
+
diff --git a/Android/LuaViewDemo/assets/test/NUI_System.lua b/Android/LuaViewDemo/assets/test/NUI_System.lua
new file mode 100644
index 00000000..e48f28d0
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_System.lua
@@ -0,0 +1,51 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+require "kit/lv_kit"
+
+print(type(System))
+print(System.ios())
+print(System.android())
+print(System.vmVersion())
+print(System.osVersion())
+print(System.platform())
+print(System.scale())
+printTable(System.device())
+print(System.screenSize())
+
+-- network
+Timer(function()
+ print("Timer--" .. System.network())
+end).start(1, true)
+
+System.gc()
+
+print(window.size())
+
+btn1 = Button();
+btn1.text("Screen-On")
+btn1.xy(0, 0)
+btn1.callback(function()
+ System.keepScreenOn()
+end)
+
+btn2 = Button()
+btn2.xy(120, 0)
+btn2.text("Screen-Off")
+btn2.callback(function()
+ System.keepScreenOn(false)
+end)
+
+
+
+print("System.ios = " , System.ios() )
+print("System.android = ", System.android() )
+print("System.vmVersion = ", System.vmVersion() )
+print("System.osVersion = ", System.osVersion() ) --获取手机操作系统版本号
+print("System.platform = ", System.platform() ) --获取平台信息
+print("System.scale = ", System.scale() ) --获取屏幕分辨率
+print("System.device = ", System.device() ) --获取设备信息
+print("System.screenSize() = ", System.screenSize() );
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/NUI_Timer.lua b/Android/LuaViewDemo/assets/test/NUI_Timer.lua
new file mode 100644
index 00000000..c7a720e8
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_Timer.lua
@@ -0,0 +1,42 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+scrW,scrH = System.screenSize();
+label = Label();
+label.frame(0,0,scrW,scrH-64);
+label.lineCount(100);
+
+function myprint( s , s2 )
+ s = s .. " " .. tostring(s2)
+ print(s);
+ local text = label.text();
+ if( text ) then
+ label.text( text .. "\n" .. s);
+ else
+ label.text( s);
+ end
+end
+
+---- 1
+--timer1 = Timer(function()
+-- myprint("Timer1 Run")
+--end);
+--timer1 = timer1.start(0.1, false);
+
+--2
+index2 = 1;
+timer2 = Timer()
+timer2.callback(
+ function()
+ myprint("Timer2 Run",index2)
+ index2 = index2 + 1;
+
+ if(index2 > 10) then
+ timer2.cancel()
+ end
+ end
+ )
+timer2.start(0.2, true)
diff --git a/Android/LuaViewDemo/assets/test/NUI_Vibrator.lua b/Android/LuaViewDemo/assets/test/NUI_Vibrator.lua
new file mode 100644
index 00000000..dabbf977
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/NUI_Vibrator.lua
@@ -0,0 +1,63 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+w, h = System.screenSize();
+
+
+local vibrator = Vibrator();
+
+button1 = Button();
+button1.title("震动-1");
+button1.callback(function()
+ if (vibrator) then
+ vibrator.vibrate();
+ end
+end)
+
+button2 = Button();
+button2.title("震动-2");
+button2.xy(100, 0)
+button2.callback(function()
+ if (vibrator) then
+ vibrator.vibrate(2)
+ end
+end)
+
+button3 = Button();
+button3.title("震动-3")
+button3.xy(0, 50)
+button3.callback(function()
+ if (vibrator) then
+ vibrator.vibrate({3})
+ end
+end)
+
+button4 = Button();
+button4.title("震动-4")
+button4.xy(100, 50)
+button4.callback(function()
+ if (vibrator) then
+ vibrator.vibrate({1, 2, 1, 0.3, 0.2, 0.1, 0.01, 1.1}, 4)
+ end
+end)
+
+
+button5 = Button();
+button5.title("震动-cancel")
+button5.xy(100, 100)
+button5.callback(function()
+ if (vibrator) then
+ vibrator.cancel()
+ end
+end)
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_Alert.lua b/Android/LuaViewDemo/assets/test/UI_Alert.lua
new file mode 100644
index 00000000..d50f2169
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Alert.lua
@@ -0,0 +1,37 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--
+-- Created by IntelliJ IDEA.
+-- User: song
+
+--1 一个按钮
+as1 = StyledString("一个按钮", { fontColor = 0xffff0000, backgroundColor = 0xff00ff00, fontSize = 30 })
+as2 = StyledString("两个按钮", { fontColor = 0xffff0000, backgroundColor = 0xff00ff00, fontSize = 30 })
+as3 = StyledString("只有内容", { fontColor = 0xffff0000, backgroundColor = 0xff00ff00, fontSize = 30 })
+
+text = StyledString("文字", { fontColor = 0xffff0000, backgroundColor = 0xff00ff00, fontSize = 30 })
+
+
+ok = StyledString("确定", { fontColor = 0xffff0000, backgroundColor = 0xff00ff00, fontSize = 30 })
+
+
+Alert(as1, text, ok, function()
+ print("点击了")
+end)
+
+--2 两个按钮
+Alert(as2, text, ok, "取消", function()
+ print("点击了")
+end, function()
+ print("取消了")
+end)
+
+--3 只有内容
+Alert(nil, as3)
+
+--4 只有标题
+Alert("只有标题")
diff --git a/Android/LuaViewDemo/assets/test/UI_Animator.lua b/Android/LuaViewDemo/assets/test/UI_Animator.lua
new file mode 100644
index 00000000..443dc3f0
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Animator.lua
@@ -0,0 +1,125 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+-- 简单动画
+startBtn = Button();
+startBtn.frame(10, 10, 80, 50)
+
+resumeBtn = Button()
+resumeBtn.frame(100, 10, 80, 50)
+
+stateLabel = Label()
+stateLabel.frame(200, 10, 100, 50)
+
+local function isRunning()
+ return translation.isRunning()
+end
+
+local function isPaused()
+ return translation.isPaused()
+end
+
+local function updateControlBtns()
+ local running, paused = isRunning(), isPaused()
+ print("Running=", running, " Paused=", paused)
+
+ startBtn.text(running and "Cancel" or "Start")
+ resumeBtn.enabled(running)
+ resumeBtn.text(paused and "Resume" or "Pause")
+end
+
+translation = Animation().translation(100, -100).duration(3).repeatCount(-1).interpolator(Interpolator.ACCELERATE_DECELERATE).callback({
+ onStart = function()
+ stateLabel.text("Running")
+ end,
+ onCancel = function()
+ stateLabel.text("Canceled")
+ updateControlBtns()
+ end,
+ onEnd = function()
+ stateLabel.text("End")
+ updateControlBtns()
+ end,
+ onPause = function()
+ stateLabel.text("Paused")
+ end,
+ onResume = function()
+ stateLabel.text("Running")
+ end,
+})
+scale = Animation().scale(2, 0.5).duration(2).delay(1)
+
+local startAnimations, cancelAnimations, pauseAnimations, resumeAnimations
+
+function startAnimations()
+ if animationView then
+ animationView.removeFromSuper()
+ end
+ if isRunning() then
+ cancelAnimations()
+ end
+
+ animationView = View()
+ animationView.frame(50, 300, 100, 100)
+ animationView.backgroundColor(0xff0000, 1)
+ child = Label()
+ child.frame(10, 10, 80, 80)
+ child.backgroundColor(0x00ff00)
+ child.text("child view")
+ animationView.addView(child)
+ animationView.callback({
+ onClick = function()
+ print("scale:", animationView.scale())
+ print("translation:", animationView.translation())
+ end
+ })
+
+ translation.with(animationView).start()
+ scale.with(animationView).start()
+end
+
+function cancelAnimations()
+ translation.cancel()
+ scale.cancel()
+end
+
+function pauseAnimations()
+ if isRunning() and not isPaused() then
+ translation.pause()
+ scale.pause()
+ end
+end
+
+function resumeAnimations()
+ if isRunning() and isPaused() then
+ translation.resume()
+ scale.resume()
+ end
+end
+
+startBtn.callback({
+ onClick = function()
+ if isRunning() then
+ cancelAnimations()
+ else
+ startAnimations()
+ end
+ updateControlBtns()
+ end
+})
+
+resumeBtn.callback({
+ onClick = function()
+ if isPaused() then
+ resumeAnimations()
+ else
+ pauseAnimations()
+ end
+ updateControlBtns()
+ end
+})
+
+updateControlBtns()
diff --git a/Android/LuaViewDemo/assets/test/UI_Animator2.lua b/Android/LuaViewDemo/assets/test/UI_Animator2.lua
new file mode 100644
index 00000000..77ac30ee
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Animator2.lua
@@ -0,0 +1,89 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+sw, sh = System.screenSize()
+x = sw / 2 - 50
+y = sh / 2 - 50
+
+w = 100
+h = 100
+
+sw = 100
+sh = 100
+
+dx = 20
+dy = 20
+
+xr = x + w
+yb = y + h
+
+
+container = View()
+container.frame(x, y, w, h)
+container.borderColor(0xff0000)
+container.borderWidth(1)
+
+
+x = 0
+y = 0
+xr = x + w
+yb = y + h
+
+--左
+v1 = View()
+v1.frame(x - sw + dx, y, sw, sh)
+v1.backgroundColor(0xf00000, 0.5)
+container.addView(v1)
+
+--上
+v2 = View()
+v2.frame(x, y - sh + dy, sw, sh)
+v2.backgroundColor(0x0f0000, 0.5)
+container.addView(v2)
+
+-- 右
+v3 = View()
+v3.frame(xr - dx, y, sw, sh)
+v3.backgroundColor(0x00f000, 0.5)
+container.addView(v3)
+
+-- 下
+v4 = View()
+v4.frame(x, yb - dy, sw, sh)
+v4.backgroundColor(0x0000f0, 0.5)
+container.addView(v4)
+
+container.nativeView().setClipChildren(true)
+container.callback(function()
+ t = 2
+
+ print("v1", v1.frame())
+ print("v2", v2.frame())
+ print("v3", v3.frame())
+ print("v4", v4.frame())
+
+
+ --V1
+ tx, ty = v1.xy()
+ Animation().with(v1).translation(-tx, -ty).duration(t).start()
+
+ --V2
+ tx, ty = v2.xy()
+ Animation().with(v2).translation(-tx, -ty).delay(t).duration(t).start()
+
+ --V3
+ tx, ty = v3.xy()
+ Animation().with(v3).translation(-tx, -ty).delay(2 * t).duration(t).start()
+
+ --v4
+ tx, ty = v4.xy()
+ Animation().with(v4).translation(-tx, -ty).delay(3 * t).duration(t).start()
+
+ print("container clicked")
+
+end)
+
+print("end")
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/UI_AnimatorSet.lua b/Android/LuaViewDemo/assets/test/UI_AnimatorSet.lua
new file mode 100644
index 00000000..2390d61a
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_AnimatorSet.lua
@@ -0,0 +1,125 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+-- 简单动画
+startBtn = Button();
+startBtn.frame(10, 10, 80, 50)
+
+resumeBtn = Button()
+resumeBtn.frame(100, 10, 80, 50)
+
+stateLabel = Label()
+stateLabel.frame(200, 10, 100, 50)
+
+local function isRunning()
+ return translation.isRunning()
+end
+
+local function isPaused()
+ return translation.isPaused()
+end
+
+local function updateControlBtns()
+ local running, paused = isRunning(), isPaused()
+ print("Running=", running, " Paused=", paused)
+
+ startBtn.text(running and "Cancel" or "Start")
+ resumeBtn.enabled(running)
+ resumeBtn.text(paused and "Resume" or "Pause")
+end
+
+translation = AnimationSet("Attention.Bounce").duration(1).interpolator(Interpolator.ACCELERATE_DECELERATE).callback({
+ onStart = function()
+ stateLabel.text("Running")
+ end,
+ onCancel = function()
+ stateLabel.text("Canceled")
+ updateControlBtns()
+ end,
+ onEnd = function()
+ stateLabel.text("End")
+ updateControlBtns()
+ end,
+ onPause = function()
+ stateLabel.text("Paused")
+ end,
+ onResume = function()
+ stateLabel.text("Running")
+ end,
+})
+scale = AnimationSet("Fade.In").duration(1).delay(1)
+
+local startAnimations, cancelAnimations, pauseAnimations, resumeAnimations
+
+function startAnimations()
+ if animationView then
+ animationView.removeFromSuper()
+ end
+ if isRunning() then
+ cancelAnimations()
+ end
+
+ animationView = View()
+ animationView.frame(50, 300, 100, 100)
+ animationView.backgroundColor(0xff0000, 1)
+ child = Label()
+ child.frame(10, 10, 80, 80)
+ child.backgroundColor(0x00ff00)
+ child.text("child view")
+ animationView.addView(child)
+ animationView.callback({
+ onClick = function()
+ print("scale:", animationView.scale())
+ print("translation:", animationView.translation())
+ end
+ })
+
+ translation.with(animationView).start()
+ scale.with(animationView).start()
+end
+
+function cancelAnimations()
+ translation.cancel()
+ scale.cancel()
+end
+
+function pauseAnimations()
+ if isRunning() and not isPaused() then
+ translation.pause()
+ scale.pause()
+ end
+end
+
+function resumeAnimations()
+ if isRunning() and isPaused() then
+ translation.resume()
+ scale.resume()
+ end
+end
+
+startBtn.callback({
+ onClick = function()
+ if isRunning() then
+ cancelAnimations()
+ else
+ startAnimations()
+ end
+ updateControlBtns()
+ end
+})
+
+resumeBtn.callback({
+ onClick = function()
+ if isPaused() then
+ resumeAnimations()
+ else
+ pauseAnimations()
+ end
+ updateControlBtns()
+ end
+})
+
+updateControlBtns()
diff --git a/Android/LuaViewDemo/assets/test/UI_Bitmap.lua b/Android/LuaViewDemo/assets/test/UI_Bitmap.lua
new file mode 100644
index 00000000..2c455361
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Bitmap.lua
@@ -0,0 +1,65 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--1. 普通设置url,size,center
+view = Image()
+view.frame(0, 0, 200, 200)
+view.backgroundColor(0xffaa0000)
+
+
+--view.image("animate1")
+
+--2. 普通构造传url
+bmp = Bitmap("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg", function(ok)
+ if(ok) then
+ view.image(bmp)
+ else
+ view.image("animate1")
+ end
+end)
+
+
+spriteBmp = function(t)
+ local w, h = t.size()
+ t.sprite(0, 0, w / 2, h / 2, function(newBmp)
+ view.image(newBmp)
+ bmp = newBmp
+ end)
+ Toast("width = " .. w .. " height = " .. h)
+end
+
+
+view.callback(function()
+ spriteBmp(bmp)
+end)
+
+
+view2 = Image()
+view2.frame(0, 200, 200, 200)
+bmp2 = Bitmap("animate1", function(ok)
+ view2.image(ok and bmp2)
+end)
+
+view2.callback(function()
+ local n = 5;
+ local w, h = bmp2.size()
+ local sw = w / 5;
+ local vw = view2.width() / 5
+ local x = 0
+ local vx = 0;
+ for i = 1, n do
+ x = (i - 1) * sw
+ vx = (i - 1) * vw + (i - 1) * 2
+ local v = Image()
+ v.frame(vx, 403, vw, h)
+ v.image(bmp2.sprite(x, 0, sw, h))
+ end
+end)
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_BorderAndCorner.lua b/Android/LuaViewDemo/assets/test/UI_BorderAndCorner.lua
new file mode 100644
index 00000000..d6eca63b
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_BorderAndCorner.lua
@@ -0,0 +1,29 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+view = Image()
+view.frame(10, 10, 100, 100)
+view.image("animate3")
+view.cornerRadius(50)
+view.borderColor(0x33ff0000)
+view.borderWidth(2)
+
+
+view2 = Image()
+view2.frame(120, 10, 100, 100)
+view2.image("animate1")
+view2.cornerRadius(20)
+view2.borderColor(0xff0000)
+view2.borderWidth(2)
+
+
+view3 = Image()
+view3.frame(230, 10, 100, 100)
+view3.image("animate1")
+view3.cornerRadius(20)
+view3.borderColor(0xff0000)
+view3.borderWidth(2)
+view3.borderDash(5, 2)
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/UI_Button.lua b/Android/LuaViewDemo/assets/test/UI_Button.lua
new file mode 100644
index 00000000..3c5caff2
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Button.lua
@@ -0,0 +1,45 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+function createButton(text, x, y, w, h, callback)
+ local button = Button();
+ button.frame(x, y, w, h);
+ button.text(text);
+ button.backgroundColor(0xfa0000);
+ button.callback(function()
+ if (callback) then
+ callback();
+ end
+ end);
+ button.adjustSize()
+ return button;
+end
+
+button1 = createButton("123456中文", 10, 10, 1000, 60);
+
+button2 = Image();
+button2.frame(10, 100 + 80, 100, 100);
+button2.image("http://g.alicdn.com/ju/lua/2.0.25/doc/icon.png");
+
+button2.callback(function()
+ print("我是图片按钮");
+ button2.adjustSize();
+end);
+
+obj = {};
+
+function obj.test(a)
+ print(self, a);
+end
+
+obj.test "good";
+
+button3 = Button()
+button3.frame(150, 180, 100, 100)
+button3.image("animate2", "http://online.sccnn.com/icon/517/actionIcons_006.png")
+button3.callback(function()
+ print("button3 clicked")
+end)
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/UI_CollectionView.lua b/Android/LuaViewDemo/assets/test/UI_CollectionView.lua
new file mode 100644
index 00000000..34aa636f
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_CollectionView.lua
@@ -0,0 +1,97 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+-- 变量定义
+local s_width, s_height = System.screenSize()
+local tableView
+
+local tableViewData = {
+ Section = {
+ SectionCount = 2, -- section数量
+ RowCount = function(section)
+ if(section == 1) then
+ return 50
+ else
+ return 50
+ end
+ end
+ },
+ Cell = {
+ Id = function(section, row) -- 指定section和row对应的Cell类型唯一识别号
+ local id = "Cell1" .. section .. row
+ print("Id", id)
+ return id;
+ end,
+
+ Cell1 = {
+ Size = function(section, row)
+ print("Size", section, row, 10 + row * 2)
+ return 10 + row * 2
+ end,
+ Init = function(cell, section, row) -- 初始化cell
+ print("Init", section, row, 10 + row * 2)
+ cell.title = Label();
+ cell.title.backgroundColor(section == 1 and 0xff0000 or 0x00ff00)
+ end,
+ Layout = function(cell, section, row) -- cell复用时调用
+ print("Layout", section, row, 10 + row * 2)
+-- cell.title.frame(0, 0, s_width, 10 + row * 2)
+ cell.title.text(section .. '--' .. row)
+ end,
+ Callback = function(cell, section, row) -- 用户点击了section和row
+ Toast("Section " .. section .. ", Row " .. row);
+ end
+ }
+ }
+}
+
+local cellData = function(_, key)
+ print(key)
+ return {
+ Size = function(section, row)
+ print("Size", section, row, 10 + row * 2)
+-- return 10 + row * 2
+ return s_width, 200
+ end,
+ Init = function(cell, section, row) -- 初始化cell
+ print("Init", section, row, 10 + row * 2)
+ cell.title = Label();
+ cell.title.backgroundColor(section == 1 and 0xff0000 or 0x00ff00)
+ cell.title.lines(10)
+ cell.title.maxLine(10)
+ end,
+ Layout = function(cell, section, row) -- cell复用时调用
+ print("Layout", section, row, 10 + row * 2)
+-- cell.title.frame(0, 0, s_width, 10 + row * 2)
+
+ cell.title.text("sfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfssfadfs")
+
+ print("cell-size 11", cell.title.height())
+
+ cell.title.adjustSize()
+
+ print("cell-size 22", cell.title.height())
+
+ end,
+ Callback = function(cell, section, row) -- 用户点击了section和row
+ Toast("Section " .. section .. ", Row " .. row);
+ end
+ }
+end
+
+setmetatable(tableViewData.Cell, { __index = cellData })
+tableView = CollectionView(tableViewData)
+tableView.miniSpacing(1)
+tableView.frame(0, 0, s_width, s_height)
+tableView.showScrollIndicator(false)
+tableView.enabled(false)
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_CollectionView_reload.lua b/Android/LuaViewDemo/assets/test/UI_CollectionView_reload.lua
new file mode 100644
index 00000000..fa5d8ad8
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_CollectionView_reload.lua
@@ -0,0 +1,189 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+w, h = System.screenSize()
+cellHeight = 100
+imageUrl1 = "http://gju2.alicdn.com/bao/uploaded/i1/10000073270926575/TB2fpg0cXXXXXb6XpXXXXXXXXXX_!!0-0-juitemmedia.jpg"
+imageUrl2 = "http://img4.duitang.com/uploads/item/201306/25/20130625045508_sairr.thumb.600_0.jpeg"
+
+sectionCount = 2
+rowCount1 = 1
+rowCount2 = 1
+rowTitle = "x"
+tableView = CollectionView {
+ Section = {
+ SectionCount = function()
+ return sectionCount
+ end,
+ RowCount = function(section)
+ if(section == 1) then
+ return rowCount1
+ else
+ return rowCount2
+ end
+ end
+ },
+ Cell = {
+ Id = function(section, row)
+ if (section == 1) then
+ return "ImageAndLabel"
+ elseif(section == 2) then
+ return "ImageAndImage"
+ else
+ return "Label"
+ end
+ end,
+ Label = {
+ Size = function(section, row)
+ return w, cellHeight
+ end,
+ Init = function(cell, section, row)
+ cell.title = Label()
+ end,
+ Layout = function(cell, section, row)
+ cell.title.frame(0, 0, w - cellHeight, cellHeight)
+ cell.title.text("测试" .. section .. "--" .. row .. "--" .. rowTitle)
+ cell.title.backgroundColor(0xdcdcdc)
+ end
+ },
+ ImageAndLabel = {
+ Size = function(section, row)
+ return w, cellHeight
+ end,
+ Init = function(cell, section, row)
+ cell.icon = Image()
+ cell.title = Label()
+ cell.bg = Button()
+ end,
+ Layout = function(cell, section, row)
+ cell.icon.frame(20, 0, cellHeight, cellHeight)
+ cell.icon.image(imageUrl1)
+
+ cell.title.frame(20 + cellHeight, 0, w - cellHeight, cellHeight)
+ cell.title.text("测试" .. section .. "--" .. row .. "--" .. rowTitle)
+
+ cell.bg.frame(0, 0, w, cellHeight)
+ cell.bg.image(nil, imageUrl1)
+ end,
+ Callback = function(section, row)
+ print(section, row)
+ tableView.stopRefreshing()
+ System.gc()
+ end
+ },
+ ImageAndImage = {
+ Size = function(section, row)
+ return cellHeight
+ end,
+ Init = function(cell, section, row)
+ cell.icon = Image()
+ cell.icon2 = Image()
+ end,
+ Layout = function(cell, section, row)
+ local cellWdith, cellHeight = cell.window.size()
+ cell.icon.frame(0, 0, cellHeight, cellHeight)
+ cell.icon.image(imageUrl1)
+
+
+ cell.icon2.frame(cellHeight + 10, 0, cellHeight, cellHeight)
+ cell.icon2.image(imageUrl1)
+ end,
+ Callback = function(section, row)
+ print(section, row)
+ tableView.stopRefreshing()
+ System.gc()
+ end
+ }
+ }
+}
+
+tableView.frame(0, 152, w, h - 64 - 152)
+
+
+local btn = Button()
+btn.text("reload")
+btn.frame(0, 0, 80, 50)
+btn.callback(function()
+ print("reload")
+ tableView.reload()
+end)
+
+local btn2 = Button()
+btn2.text("+rows")
+btn2.frame(81, 0, 80, 50)
+btn2.callback(function()
+ rowCount1 = rowCount1 + 2
+ print("+rows", 1, rowCount1)
+ tableView.reload(1)
+end)
+
+local btn3 = Button()
+btn3.text("-rows")
+btn3.frame(162, 0, 80, 50)
+btn3.callback(function()
+ rowCount1 = rowCount1 - 2
+ rowCount1 = math:max(rowCount1, 1)
+ print("-rows", 1, rowCount1)
+ tableView.reload(1)
+end)
+
+local btn4 = Button()
+btn4.text("update-rows")
+btn4.frame(243, 0, 80, 50)
+btn4.callback(function()
+ rowTitle = rowTitle .. "y"
+ print("update-rows", 1)
+ tableView.reload(1)
+end)
+
+local btn5 = Button()
+btn5.text("+row")
+btn5.frame(0, 51, 80, 50)
+btn5.callback(function()
+ rowCount1 = rowCount1 + 1
+ print("+row", 1, rowCount1)
+ tableView.reload(1, 1)
+end)
+
+local btn6 = Button()
+btn6.text("-row")
+btn6.frame(81, 51, 80, 50)
+btn6.callback(function()
+ rowCount1 = rowCount1 - 1
+ rowCount1 = math:max(rowCount1, 1)
+ print("-row", 1, rowCount1)
+ tableView.reload(1, 1)
+end)
+
+local btn7 = Button()
+btn7.text("update-row")
+btn7.frame(162, 51, 80, 50)
+btn7.callback(function()
+ rowTitle = rowTitle .. "x"
+ print("update-row", 1, 1)
+ tableView.reload(1, 1)
+end)
+
+
+local btn8 = Button()
+btn8.text("+section")
+btn8.frame(0, 102, 80, 50)
+btn8.callback(function()
+ sectionCount = sectionCount + 1
+ print("+section", sectionCount)
+ tableView.reload(sectionCount)
+end)
+
+local btn9 = Button()
+btn9.text("-section")
+btn9.frame(91, 102, 80, 50)
+btn9.callback(function()
+ sectionCount = sectionCount - 1
+ sectionCount = math:max(sectionCount, 1)
+ print("-section", sectionCount)
+ tableView.reload(sectionCount)
+end)
+
diff --git a/Android/LuaViewDemo/assets/test/UI_CustomPanel.lua b/Android/LuaViewDemo/assets/test/UI_CustomPanel.lua
new file mode 100644
index 00000000..2ed04485
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_CustomPanel.lua
@@ -0,0 +1,21 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+panel = CustomError()
+panel.backgroundColor(0xff0000)
+panel.frame(0, 0, 200, 200)
+panel.callback(function(message, arg1, arg2, arg3, arg4)
+ print(message, arg1, arg2, arg3, arg4)
+ if(value == "success") then
+ -- do
+ else
+ -- do
+ end
+end)
+
+print("rootView", panel.nativeView().getAlpha())
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_CustomView.lua b/Android/LuaViewDemo/assets/test/UI_CustomView.lua
new file mode 100644
index 00000000..f1b5bd67
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_CustomView.lua
@@ -0,0 +1,233 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+img = Image()
+
+view = CustomView()
+view.frame(100, 100, 200, 200)
+view.backgroundColor(0x000000, 0.3)
+
+img.hidden(true)
+
+view.onDraw(function(canvas)
+ testCanvasAndroidAndIos(canvas)
+end)
+
+view.onClick(function()
+ view.invalidate()
+ Toast("invalidate")
+end)
+
+bmp = Bitmap("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+
+function testCanvasAndroidAndIos(canvas)
+ print(canvas)
+ -- drawLine
+ canvas.color(0xff0000)
+ canvas.strokeWidth(2)
+ canvas.drawLine(0, 50, 100, 50)
+ canvas.drawLine(50, 0, 50, 100)
+
+ canvas.resetPaint()
+ canvas.color(0x00ff00)
+ canvas.alpha(0.5)
+ canvas.drawLine(0, 0, 100, 0)
+ canvas.drawLine(100, 0, 100, 100)
+ canvas.drawLine(100, 100, 0, 100)
+ canvas.drawLine(0, 100, 0, 0)
+ canvas.drawLine(0, 0, 100, 100)
+ canvas.drawLine(100, 0, 0, 100)
+
+ -- drawPoint
+ canvas.color(0xff0000)
+ canvas.strokeWidth(2)
+ canvas.drawPoint(1, 5)
+ canvas.drawPoint(99, 93)
+
+ -- drawRect
+ canvas.resetPaint()
+ canvas.style(PaintStyle.STROKE)
+ canvas.drawRect(5, 5, 5, 5)
+ canvas.style(PaintStyle.FILL)
+ canvas.drawRect(10, 10, 5, 5)
+
+ -- drawRoundRects
+ canvas.drawRoundRect(45, 1, 5, 5, 2, 2)
+ canvas.drawRoundRect(45, 5, 10, 5, 2, 2)
+
+ -- drawCircle
+ canvas.drawCircle(80, 0, 5)
+ canvas.drawCircle(80, 15, 5)
+
+ -- drawText
+ canvas.textSize(20)
+ canvas.drawText("x", 20, 55)
+ canvas.textSize(14)
+ canvas.drawText("y", 20, 65)
+ canvas.resetPaint()
+
+ -- drawOval
+ canvas.drawOval(45, 50, 25, 10)
+ canvas.drawOval(45, 60, 25, 10)
+
+ -- draw Arc
+ canvas.drawArc(30, 30, 20, 20, 0, 90, true)
+
+ -- drawBitmap
+ canvas.save()
+ canvas.rotate(-10, 100, 100)
+ canvas.skew(100)
+ canvas.scale(1.2)
+ canvas.translate(-10, -10)
+ canvas.strokeWidth(10)
+ canvas.textSize(15)
+ canvas.bold(true)
+ canvas.drawText("测试一下", 20, 150)
+ canvas.alpha(0.5)
+ canvas.drawImage("animate1", 0, 100, 100, 100)
+ canvas.restore()
+ canvas.resetPaint()
+
+ print(img)
+ if(img) then
+ canvas.drawImage(img, 100, 0, 100, 100)
+ end
+
+ canvas.drawImage(bmp, 0, 0, 100, 100)
+
+ -- clipRect
+ canvas.clipRect(100, 100, 35, 35)
+ canvas.drawCircle(100, 100, 40)
+
+ canvas.clipRect(150, 150, 30, 30)
+ canvas.drawText("TestABCDEFGHEFGHIJKLMOPQRST", 150, 150)
+
+ print(canvas.nativeObj())
+end
+
+
+img.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg", function()
+ view.invalidate()
+ print("image load finish")
+end)
+
+
+
+function testCanvasAndroid(canvas)
+ print(canvas)
+
+
+ -- drawLine
+
+ canvas.drawLine(0, 50, 100, 50, { color = 0xff0000 })
+ canvas.drawLine(50, 0, 50, 100, { strokeWidth = 2 })
+
+ canvas.drawLine({
+ { 0, 0, 100, 0 },
+ { 100, 0, 100, 100 },
+ { 100, 100, 0, 100 },
+ { 0, 100, 0, 0 },
+ { 0, 0, 100, 100 },
+ { 100, 0, 0, 100 }
+ }, { color = 0x00ff00, alpha = 0.5 })
+
+ canvas.resetPaint()
+
+
+ -- drawPoint
+ canvas.drawPoint(1, 3)
+ canvas.drawPoint(99, 97)
+
+ canvas.drawPoint({
+ { 3, 1 },
+ { 97, 99 },
+ { 1, 97 },
+ { 97, 1 }
+ })
+
+
+ -- drawRect
+ canvas.drawRect(5, 5, 5, 5, { style = "stroke" })
+ canvas.drawRect(10, 10, 5, 5, { style = "fillStroke" })
+
+ canvas.drawRect({
+ { 15, 15, 5, 5 },
+ { 20, 20, 5, 5 },
+ { 26, 26, 5, 5 },
+ }, { style = 2 })
+
+ -- drawRoundRects
+ canvas.drawRoundRect(45, 1, 10, 5, 2, 2)
+ canvas.drawRoundRect(45, 5, 10, 5, 2, 2)
+
+ canvas.drawRoundRect({
+ { 45, 10, 10, 5, 2, 2 },
+ { 45, 16, 20, 4, 1, 1 },
+ })
+
+ -- drawCircle
+ canvas.drawCircle(80, 0, 5)
+ canvas.drawCircle(80, 15, 5)
+
+ canvas.drawCircle({
+ { 80, 30, 5 },
+ { 80, 45, 2 },
+ })
+
+ -- drawText
+
+ canvas.drawText("x", 20, 55, { textSize = 20, textAlign = TextAlign.RIGHT })
+ canvas.drawText("y", 20, 65, { textSize = 14 })
+
+ canvas.drawText({
+ { "xx", 20, 75, { color = 0x0000ff, strikeThrough = true, textSize = 20, textSkewX = 1.5, bold = true } },
+ { "yy", 20, 85 },
+ }, { color = 0x0fff00, underline = true, textSize = 10, textScaleX = 3, letterSpacing = 0.2, linearText = true })
+ canvas.resetPaint()
+
+ -- drawOval
+ canvas.drawOval(45, 50, 25, 20)
+ canvas.drawOval(45, 60, 25, 20)
+
+ canvas.drawOval({
+ { 45, 70, 25, 5 },
+ { 45, 80, 25, 5 }
+ })
+
+ -- draw Arc
+ canvas.drawArc(30, 30, 20, 20, 0, 90, true)
+
+ canvas.drawArc({
+ { 10, 30, 20, 10, 91, 180, true },
+ { 30, 30, 20, 20, 182, 100, false }
+ })
+
+ -- drawBitmap
+ canvas.save()
+ canvas.rotate(-10, 100, 100)
+ canvas.skew(100)
+ canvas.scale(1.2)
+ canvas.translate(-10, -10)
+ canvas.drawText("测试一下", 20, 150, { strokeWidth = 10, textSize = 15, filterBitmap = true, bold = true })
+ canvas.drawBitmap("animate1", 0, 100, 100, 100, { alpha = 0.5 })
+ canvas.restore()
+ canvas.resetPaint()
+
+ print(img)
+ if (img) then
+ canvas.drawBitmap(img, 100, 0, 200, 100)
+ end
+
+ -- clipRect
+ canvas.clipRect(100, 100, 35, 35)
+ canvas.drawCircle(100, 100, 40)
+
+ canvas.clipRect(150, 150, 30, 30)
+ canvas.drawText("TestABCDEFGHEFGHIJKLMOPQRST", 150, 150)
+
+ print(canvas.nativeObj())
+end
+
diff --git a/Android/LuaViewDemo/assets/test/UI_FlexboxLayout.lua b/Android/LuaViewDemo/assets/test/UI_FlexboxLayout.lua
new file mode 100644
index 00000000..e2b49c63
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_FlexboxLayout.lua
@@ -0,0 +1,92 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+LIGHT_GRAY = 0xf5edb3
+RED_COLOR = 0xf61d4b
+BLUE_COLOR = 0x26a96d
+GREEN_COLOR = 0x05A5D1
+MAGENTA_COLOR = 0xff00ff
+MOCCASIN_COLOR = 0xffe4b5
+OLIVEDRAB_COLOR = 0x6b8e23
+
+w,h = System.screenSize()
+
+-- 依次从上往下对应
+contentView = View()
+contentView.frame(0, 0, w, 400)
+contentView.backgroundColor(LIGHT_GRAY)
+
+-- 对应第一个纯色的红色的view
+view1 = View()
+view1.backgroundColor(RED_COLOR)
+view1.flexCss("flex: 1, margin: 5")
+
+-- 对应第二个绿色的View,这个View有5个子View,从左往右排列
+view2 = View()
+view2.backgroundColor(BLUE_COLOR)
+
+-- 左边红色与相邻的蓝色,宽度关系表示为1:3
+view3 = View()
+view3.backgroundColor(RED_COLOR)
+view3.flexCss("flex: 1")
+
+-- View4 蓝色这块也有一些子view, 这里解释了如何换行
+view4 = View()
+view4.backgroundColor(GREEN_COLOR)
+view4.flexCss("flex: 3, flex-direction: row-reverse, align-items: stretch, flex-wrap: 1, align-content: flex-start, justify-content: center")
+
+view41 = View()
+view41.backgroundColor(MAGENTA_COLOR)
+view41.flexCss("width: 50, align-self: stretch, margin: 5, height: 25")
+
+view42 = Label()
+view42.backgroundColor(MOCCASIN_COLOR)
+view42.text("flex box")
+view42.lineCount(0)
+view42.flexCss("margin: 5, sizetofit: 1, align-self: center, margin-top: 20")
+
+view43 = Label()
+view43.backgroundColor(OLIVEDRAB_COLOR)
+view43.flexCss("margin-left: 10, sizetofit: 1, align-self: center")
+view43.text("you will like it!")
+view43.lineCount(1)
+
+view4.flexChildren(view41, view42, view43)
+
+view5 = View()
+view5.backgroundColor(RED_COLOR)
+view5.flexCss("width: 40, height: 40, margin-left: 10, align-self: center")
+
+image = Image()
+image.image("http://img4.tbcdn.cn/L1/461/1/img_20151116194256.JPEG_240x240")
+image.flexCss("width: 30, height: 30, align-self: flex-end")
+
+-- 一个绝对定位的view,黑色的那块,与其他子不发生关系,只与父发生关系
+view6 = View()
+view6.backgroundColor(0x00)
+view6.flexCss("width: 50, height: 50, position: absolute, left: 5, top: 5")
+
+view2.flexChildren(view3, view4, image, view5, view6)
+view2.flexCss("flex: 2, padding: 10.0, flex-direction: row, align-items: stretch")
+
+label = Label()
+label.backgroundColor(GREEN_COLOR)
+label.text("The Réunion parrot or Dubois's parrot (Necropsittacus borbonicus) is a hypothetical extinct species of parrot based on descriptions of birds from the Mascarene island of Réunion. ")
+label.flexCss("margin: 20, sizetofit: 1")
+label.lineCount(0)
+
+contentView.flexChildren(view1, view2, label)
+contentView.flexCss("flex-direction: column")
+contentView.flxLayout(true, function()
+ print("cccc")
+end)
+
+view2.callback(function()
+ view3.flexCss("flex: 2")
+ view4.flexCss("flex: 1")
+
+ contentView.flxLayout()
+end)
diff --git a/Android/LuaViewDemo/assets/test/UI_HScrollView.lua b/Android/LuaViewDemo/assets/test/UI_HScrollView.lua
new file mode 100644
index 00000000..ed0b18b9
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_HScrollView.lua
@@ -0,0 +1,54 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+
+-- 活动指示器
+local SCREEN_WIDTH = System.screenSize()
+
+local scrollView = HScrollView()
+b0 = Button()
+b0.text("scrollTo")
+b0.callback(function()
+ scrollView.offset(2, 0)
+end)
+
+b1 = Button()
+b1.text("scrollBy")
+b1.xy(100, 0)
+b1.callback(function()
+ scrollView.scrollBy(20, 0)
+end)
+
+b3 = Button()
+b3.text("smoothScrollTo")
+b3.xy(0, 75)
+b3.callback(function()
+ scrollView.offset(20, 0, true)
+end)
+
+b4 = Button()
+b4.text("smoothScrollBy")
+b4.xy(150, 75)
+b4.callback(function()
+ scrollView.smoothScrollBy(20, 0)
+end)
+
+
+for i = 0, 10, 1 do
+ local btn = Label()
+ btn.text("BTN" .. i)
+ btn.frame(i * 60, 10, 59, 80)
+ btn.backgroundColor(0xff00ff00)
+ scrollView.addView(btn)
+end
+
+scrollView.xy(0, 300)
+scrollView.size(SCREEN_WIDTH, 100)
+scrollView.backgroundColor(0xffcccccc)
+scrollView.showScrollIndicator(false)
diff --git a/Android/LuaViewDemo/assets/test/UI_HelloLuaView.lua b/Android/LuaViewDemo/assets/test/UI_HelloLuaView.lua
new file mode 100644
index 00000000..c6ef71c8
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_HelloLuaView.lua
@@ -0,0 +1,23 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+local screenWidth, screenHeight = System.screenSize()
+
+-- Test Label
+local label = Label()
+label.text(System.ios() and "iOS" or "Android")
+label.textColor(0x000000)
+label.frame(0, 0, screenWidth, screenHeight)
+label.textAlign(TextAlign.CENTER)
+
+-- Test Button
+local btn = Button()
+btn.size(200, 200)
+btn.text("Click Me")
+btn.backgroundColor(0xff0000)
+btn.callback(function()
+ Alert("Hello LuaView")
+end)
diff --git a/Android/LuaViewDemo/assets/test/UI_Image.lua b/Android/LuaViewDemo/assets/test/UI_Image.lua
new file mode 100644
index 00000000..0201b69f
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Image.lua
@@ -0,0 +1,88 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--1. 普通设置url,size,center
+view = Image()
+view.size(100, 100)
+view.center(50, 50)
+print(view.size())
+view.backgroundColor(0xffaa0000)
+view.callback(function()
+ print("Button Clicked")
+end)
+view.image("animate1")
+
+print("view-url", view.image())
+
+
+--2. 普通构造传url
+view2 = Image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+view2.frame(150, 0, 150, 100)
+print("view2-url", view2.image())
+
+
+
+scrW, scrH = System.screenSize();
+window.backgroundColor("#FFFF00", 0.5);
+
+w = scrW / 3;
+X0 = scrW / 10;
+Y0 = scrH / 4;
+
+
+imageView = Image();
+imageView.frame(X0, Y0, w, w);
+imageView.backgroundColor(0xff0000, 0.5);
+imageView.startAnimationImages({"animate1", "animate2"}, 3.0, 1);
+
+imageView.callback({
+ onShow = function()
+ print("show")
+ end,
+ onHide = function()
+ print("hide")
+ end
+})
+
+window.callback({
+ onShow = function()
+ print("window show")
+ end,
+ onHide = function()
+ print("window hide")
+ end
+})
+
+label = Label();
+
+imageView2 = Image();
+imageView2.frame(X0 + w + X0, Y0, w, w);
+imageView2.image("http://g.alicdn.com/ju/lua/2.0.24/doc/icon.png",
+ function()
+ --这里的text会报一个bug
+ print("图片加载成功!");
+ label.text("图片加载成功!")
+ label.adjustSize();
+ label.center(scrW / 2, scrH / 2);
+ end);
+
+
+
+-- gif
+imageView3 = Image()
+imageView3.image("http://static1.squarespace.com/static/552a5cc4e4b059a56a050501/565f6b57e4b0d9b44ab87107/565f6ddee4b0d9b44ab89215/1449098068446/NYCGifathon2.gif", function() end)
+imageView3.frame(scrW / 2 - 50, scrH / 2 + 100, 100, 100)
+imageView3.callback(function()
+ imageView3.adjustSize()
+end)
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_Label.lua b/Android/LuaViewDemo/assets/test/UI_Label.lua
new file mode 100644
index 00000000..5e20ce67
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Label.lua
@@ -0,0 +1,80 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+screenWidth, screenHeight = System.screenSize()
+bg = View()
+bg.backgroundColor(0xdddddd, 0.5)
+bg.size(screenWidth, 60)
+
+a = Label()
+a.text("测试")
+a.backgroundColor(0xaaaa00)
+a.xy(10, 10)
+a.size(100, 50)
+
+b = Label()
+b.text(StyledString("测试说", {fontColor=0xff0000, fontWeight=FontWeight.BOLD--[[fontStyle="bold", fontWeight="bold"]]}))
+b.fontSize(12)
+b.backgroundColor(0xaa00aa)
+b.cornerRadius(5)
+b.xy(50, 10)
+
+c = Label()
+c.font("fonts/iconfont.ttf", 40)
+c.text(Unicode(0xe617) .. "123")
+c.backgroundColor(0x999999)
+c.xy(180, 10)
+
+view = Label()
+view.text("测试1")
+view.font(20)
+view.lines(2)
+view.backgroundColor(0xaaaa00)
+view.frame(50, 120, 50, 50)
+
+
+view2 = Label()
+view2.text("测试2")
+view2.font(20)
+view2.lines(2)
+view2.backgroundColor(0xaaaa00)
+view2.frame(50, 190, 50, 50)
+
+view3 = Label()
+view3.text("测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3测试3")
+view3.font(20)
+view3.lines(2)
+view3.backgroundColor(0xaaaa00)
+view3.frame(50, 270, 100, 100)
+
+view4 = Label()
+view4.text("测试4测试4测试4测试4测试4")
+view4.font(20)
+view4.lines(1)
+view4.backgroundColor(0xaaaa00)
+view4.frame(50, 400, 100, 100)
+
+btn = Button()
+btn.text("adjustFontSize")
+btn.xy(0, 70)
+btn.callback(function()
+ view.text(view.text() .. "测试1")
+ view.adjustFontSize()
+end)
+
+
+btn2 = Button()
+btn2.xy(200, 70)
+btn2.text("adjustSize")
+btn2.callback(function()
+ view2.adjustSize()
+ view3.adjustSize()
+ view4.adjustSize()
+end)
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_LoadingDialog.lua b/Android/LuaViewDemo/assets/test/UI_LoadingDialog.lua
new file mode 100644
index 00000000..1832b7e9
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_LoadingDialog.lua
@@ -0,0 +1,31 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+local loading
+local width = System.screenSize()
+local timer = Timer()
+
+btn1 = Button()
+btn1.callback(function()
+ loading = LoadingDialog();
+ loading.show()
+
+ if (timer) then
+ timer.start(5).callback(function()
+ Toast("canceld by Timer")
+ if (loading) then
+ loading.hide()
+ end
+ end)
+ end
+end)
+
+btn1.text("Start")
+btn1.frame(0, 0, width, 100)
+
diff --git a/Android/LuaViewDemo/assets/test/UI_LoadingIndicator.lua b/Android/LuaViewDemo/assets/test/UI_LoadingIndicator.lua
new file mode 100644
index 00000000..c5d031a1
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_LoadingIndicator.lua
@@ -0,0 +1,39 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+
+
+local loading = LoadingIndicator()
+loading.backgroundColor(0xaaaa0000)
+loading.size(50, 50)
+loading.alignCenter()
+
+local width = System.screenSize()
+
+btn1 = Button()
+btn1.callback(function()
+ if (loading) then
+ loading.show()
+ end
+end)
+
+btn2 = Button()
+btn2.callback(function()
+ if (loading) then
+ loading.hide()
+ end
+end)
+
+
+btn1.text("Start")
+btn1.frame(0, 100, width, 100)
+btn2.text("Stop")
+btn2.frame(0, 300, width, 100)
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_Navigation.lua b/Android/LuaViewDemo/assets/test/UI_Navigation.lua
new file mode 100644
index 00000000..c10ba815
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Navigation.lua
@@ -0,0 +1,40 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+
+scrW, scrH = System.screenSize();
+
+function createButton( text , x,y,w,h, callback)
+ local button = Button();
+ button.frame(x,y,w,h);
+ button.text(text);
+ button.backgroundColor(0xeeeeee);
+ button.callback( function()
+ print("ok",button);
+ if( callback ) then
+ callback();
+ end
+ end );
+ return button;
+end
+
+buttonH = scrH /10;
+
+-----------------
+
+button1 = createButton("设置导航栏 标题",0,buttonH*1,scrW,buttonH, function()
+ Navigation.title("测试view")
+ end);
+
+
+img = Image();
+img.image("http://gtms02.alicdn.com/tps/i2/TB1qmXnHpXXXXcuaXXXQG.m0FXX-640-128.jpg",function()
+ Navigation.background(img, 0xff0000)
+end);
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_NoticeView.lua b/Android/LuaViewDemo/assets/test/UI_NoticeView.lua
new file mode 100644
index 00000000..8a6c4d98
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_NoticeView.lua
@@ -0,0 +1,29 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+local width = System.screenSize()
+
+btn1 = Button()
+btn1.callback(function()
+ Toast(StyledString("测试一下Toast", {fontColor=0xffff0000, backgroundColor=0xff00ff00, fontSize=50}))
+end)
+
+btn2 = Button()
+btn2.callback(function()
+ local notice = Toast();
+ notice.show("xx")
+end)
+
+
+btn1.text("第一")
+btn1.frame(0, 0, width, 100)
+btn2.text("第二")
+btn2.frame(0, 150, width, 100)
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_OnTouch.lua b/Android/LuaViewDemo/assets/test/UI_OnTouch.lua
new file mode 100644
index 00000000..19842bef
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_OnTouch.lua
@@ -0,0 +1,105 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+sw, sh = System.screenSize()
+
+bg = Label()
+bg.text("我是背景,重复进入页面,尝试不同状态。")
+bg.frame(0, 0, sw, sh)
+bg.callback(function()
+ Toast("bg clicked")
+end)
+
+
+view = CustomView()
+view.frame(0, 0, sw,sh)
+view.backgroundColor(0xff0000, 0.5)
+
+lastX = nil
+lastY = nil
+
+x = 0
+y = 0
+w = 4
+dx = 0
+dy = 0
+
+isTouchable = math:random() > 0.5
+
+bg.text(bg.text() .. (isTouchable and " 不可点击" or " 可以点击"))
+
+view.onTouch(function(event)
+ print(event.id, event.pointer, event.action, event.x, event.y)
+ dx = lastX and event.x - lastX or 0
+ dy = lastY and event.y - lastY or 0
+
+
+ x = x + dx
+ y = y + dy
+
+ if(x < 0) then
+ x = 0
+ end
+
+ if(y < 0) then
+ y = 0
+ end
+
+ if(x > sw) then
+ x = sw
+ end
+
+ if (y > sh) then
+ y = sh
+ end
+
+ lastX = event.action == TouchEvent.MOVE and event.x or nil
+ lastY = event.action == TouchEvent.MOVE and event.y or nil
+
+ view.invalidate()
+
+ return isTouchable;
+end)
+
+rect = {}
+
+count = 20
+
+for i = 0, count, 1 do
+ rect[i + 1] = {}
+ rect[i + 1][1] = x
+ rect[i + 1][2] = y
+ rect[i + 1][3] = w
+ rect[i + 1][4] = w
+
+ x = x + 20
+
+ w = 3 + math:random(10)
+end
+
+view.onDraw(function(canvas)
+ print(x, y, w, h)
+
+ for i = 0, count, 1 do
+ canvas.drawRect(rect[i+1][1], rect[i+1][2], rect[i+1][3], rect[i+1][4])
+ end
+
+ for i = 0, count, 1 do
+ rect[i+1][2] = (rect[i+1][2] + math:random()) * 1.005 - dy
+
+ if(rect[i+1][2] + rect[i+1][4] > 500) then
+ rect[i+1][2] = 500 - rect[i + 1][4]
+ end
+ end
+
+ canvas.drawLine(0, 500 - dy, sw, 500-dy)
+
+end)
+
+
+Timer().callback(function()
+ view.invalidate()
+end).start(0.01, true)
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/UI_PagerIndicator.lua b/Android/LuaViewDemo/assets/test/UI_PagerIndicator.lua
new file mode 100644
index 00000000..ed0db0af
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_PagerIndicator.lua
@@ -0,0 +1,53 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+-- 活动指示器
+local SCREEN_WIDTH = System.screenSize()
+
+function createCircleIndicator()
+ local indicator = PagerIndicator()
+-- indicator.size(SCREEN_WIDTH / 2, 100)
+-- indicator.alignCenter()
+ indicator.frame(10, 100, SCREEN_WIDTH / 2, 100)
+ indicator.selectedColor(0xff0000)
+ indicator.unselectedColor(0x00ff00)
+-- indicator.fillColor(0xff0000)
+-- indicator.pageColor(0x00ff00)
+ return indicator
+end
+
+pagerView = PagerView({
+ PageCount = 12,
+ Pages = {
+ Title = function(pos)
+ return "Title"
+ end,
+ Init = function(page, pos)
+ page.icon = Button()
+ end,
+ Layout = function(page, pos)
+ page.icon.text("测试按钮"..pos)
+ page.icon.frame(0, 0, SCREEN_WIDTH, 50)
+ end
+ },
+ Callback = {
+ Scrolling=function(pos, percent, distance)
+ Toast("滑动"..pos)
+ end,
+ Selected=function(pos)
+ Toast("选中"..pos)
+ end
+ }
+})
+
+--活动指示器
+pagerView.indicator(createCircleIndicator())
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_PagerView.lua b/Android/LuaViewDemo/assets/test/UI_PagerView.lua
new file mode 100644
index 00000000..8a567c3c
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_PagerView.lua
@@ -0,0 +1,53 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+local width, height = System.screenSize()
+
+vp = PagerView({
+ PageCount = 4,
+ Pages = {
+ Title = function(pos)
+ return "Title"
+ end,
+ Init = function(page, pos)
+ page.icon = Button()
+ end,
+ Layout = function(page, pos)
+ page.icon.text("测试按钮"..(pos-1))
+ page.icon.frame(0, 0, width, 200)
+ page.icon.callback(function()
+ if(pos == 1) then
+ vp.looping(true)
+ vp.autoScroll(1)
+ elseif(pos == 2) then
+ vp.looping(false)
+ vp.autoScroll(0)
+ elseif(pos == 3) then
+ vp.autoScroll(1, true)
+ elseif(pos == 4) then
+ vp.looping(true)
+ end
+ end)
+ end
+ },
+ Callback = {
+ Scrolling=function(pos, percent, distance)
+ Toast("滑动"..pos)
+ print("滚动"..pos)
+ end,
+ Selected=function(pos)
+ Toast("选中"..pos)
+ print("选中"..pos)
+ end
+ }
+})
+
+vp.backgroundColor(0xaaaa0000)
+vp.frame(0, 20, width, height - 20)
+
diff --git a/Android/LuaViewDemo/assets/test/UI_PagerViewAndCollectionView.lua b/Android/LuaViewDemo/assets/test/UI_PagerViewAndCollectionView.lua
new file mode 100644
index 00000000..6005eda0
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_PagerViewAndCollectionView.lua
@@ -0,0 +1,153 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+w, h = System.screenSize()
+
+cellHeight = 100
+imageUrl1 = "http://gju2.alicdn.com/bao/uploaded/i1/10000073270926575/TB2fpg0cXXXXXb6XpXXXXXXXXXX_!!0-0-juitemmedia.jpg"
+imageUrl2 = "http://img4.duitang.com/uploads/item/201306/25/20130625045508_sairr.thumb.600_0.jpeg"
+
+
+local vp = PagerView({
+ PageCount = 4,
+ Pages = {
+ Title = function(pos)
+ return "Title"
+ end,
+ Init = function(page, pos)
+ local tableView = RefreshCollectionView {
+ Section = {
+ SectionCount = 2,
+ RowCount = function(section)
+ if(section == 1) then
+ return 1
+ elseif(section == 2) then
+ return 10
+ end
+ end
+ },
+ Cell = {
+ Id = function(section, row)
+ if(pos % 2 ~= 0) then
+ if (section == 1) then
+ return "HScroll"
+ else
+ return "ImageAndImage"
+ end
+ else
+ if (section == 2) then
+ return "Pager"
+ else
+ return "ImageAndImage"
+ end
+ end
+ end,
+ HScroll = {
+ Size = function(section, row)
+ return w, 100
+ end,
+ Init = function(cell, section, row)
+ local scrollView = HScrollView()
+ for i = 0, 10, 1 do
+ local btn = Label()
+ btn.text("BTN" .. i)
+ btn.frame(i * 80, 0, 79, 100)
+ btn.backgroundColor(0xff00ff00)
+ btn.callback(function()
+ Toast(btn.text())
+ end)
+ scrollView.addView(btn)
+ end
+ scrollView.size(w, 100)
+ scrollView.backgroundColor(0xffcccccc)
+ cell.container= scrollView
+ end,
+ Layout = function(cell, section, row)
+ end
+ },
+ Pager = {
+ Size = function(section, row)
+ return w, 100
+ end,
+ Init = function(cell, section, row)
+ local vp = PagerView({
+ PageCount = 10,
+ Pages = {
+ Title = function(pos)
+ return "Title"
+ end,
+ Init = function(page, pos)
+ page.icon = Button()
+ end,
+ Layout = function(page, pos)
+ page.icon.text("测试按钮"..pos)
+ page.icon.frame(0, 0, w, 100)
+ page.icon.callback(function()
+ Toast(page.icon.text())
+ end)
+ end
+ }
+ })
+
+ vp.backgroundColor(0xaaaa0000)
+ vp.frame(0, 0, w, 100)
+
+ cell.container = vp
+ end,
+ Layout = function(cell, section, row)
+ end
+ },
+ ImageAndImage = {
+ Size = function(section, row)
+ return cellHeight
+ end,
+ Init = function(cell, section, row)
+ cell.icon = Image()
+ cell.icon2 = Image()
+ end,
+ Layout = function(cell, section, row)
+ local cellWdith, cellHeight = cell.window.size()
+ cell.icon.frame(0, 0, cellHeight, cellHeight)
+ cell.icon.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-1", section, row)
+ end)
+ cell.icon.callback(function()
+ print("cell_icon1")
+ end)
+
+
+ cell.icon2.frame(cellHeight + 10, 0, cellHeight, cellHeight)
+ cell.icon2.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-2", section, row)
+ end)
+ cell.icon2.callback(function()
+ print("cell_icon2")
+ end)
+ end
+ }
+ }
+ }
+ tableView.frame(0, 0, w, h - 64)
+
+ page.view = tableView
+
+ end,
+ Layout = function(page, pos)
+ end
+ }
+})
+
+vp.backgroundColor(0xaaaa0000)
+vp.frame(0, 0, w, h)
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_RecyclerView.lua b/Android/LuaViewDemo/assets/test/UI_RecyclerView.lua
new file mode 100644
index 00000000..957c24d1
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_RecyclerView.lua
@@ -0,0 +1,87 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+-- 变量定义
+local s_width, s_height = System.screenSize()
+local tableView
+
+local tableViewData = {
+ Section = {
+ SectionCount = 2, -- section数量
+ RowCount = function(section)
+ if(section == 1) then
+ return 50
+ else
+ return 50
+ end
+ end
+ },
+ Cell = {
+ Id = function(section, row) -- 指定section和row对应的Cell类型唯一识别号
+ local id = "Cell1" .. section .. row
+ print("Id", id)
+ return id;
+ end,
+
+ Cell1 = {
+ Size = function(section, row)
+ print("Size", section, row, 10 + row * 2)
+ return 10 + row * 2
+ end,
+ Init = function(cell, section, row) -- 初始化cell
+ print("Init", section, row, 10 + row * 2)
+ cell.title = Label();
+ cell.title.backgroundColor(section == 1 and 0xff0000 or 0x00ff00)
+ end,
+ Layout = function(cell, section, row) -- cell复用时调用
+ print("Layout", section, row, 10 + row * 2)
+-- cell.title.frame(0, 0, s_width, 10 + row * 2)
+ cell.title.text(section .. '--' .. row)
+ end,
+ Callback = function(cell, section, row) -- 用户点击了section和row
+ Toast("Section " .. section .. ", Row " .. row);
+ end
+ }
+ }
+}
+
+local cellData = function(_, key)
+ print(key)
+ return {
+ Size = function(section, row)
+ print("Size", section, row, 10 + row * 2)
+ return 10 + row * 2
+ end,
+ Init = function(cell, section, row) -- 初始化cell
+ print("Init", section, row, 10 + row * 2)
+ cell.title = Label();
+ cell.title.backgroundColor(section == 1 and 0xff0000 or 0x00ff00)
+ end,
+ Layout = function(cell, section, row) -- cell复用时调用
+ print("Layout", section, row, 10 + row * 2)
+ cell.title.frame(0, 0, s_width, 10 + row * 2)
+ cell.title.text(section .. '--' .. row)
+ end,
+ Callback = function(cell, section, row) -- 用户点击了section和row
+ Toast("Section " .. section .. ", Row " .. row);
+ end
+ }
+end
+
+setmetatable(tableViewData.Cell, { __index = cellData })
+tableView = CollectionView(tableViewData)
+tableView.reload()
+tableView.miniSpacing(1)
+tableView.frame(0, 0, s_width, s_height)
+tableView.showScrollIndicator(true)
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_RecyclerViewPinned.lua b/Android/LuaViewDemo/assets/test/UI_RecyclerViewPinned.lua
new file mode 100644
index 00000000..3a89c70e
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_RecyclerViewPinned.lua
@@ -0,0 +1,252 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--
+-- Created by IntelliJ IDEA.
+-- User: tuoli
+-- Date: 11/4/16
+-- Time: 7:00 PM
+-- To change this template use File | Settings | File Templates.
+--
+
+w,h = System.screenSize();
+imageUrl1 = "http://gju2.alicdn.com/bao/uploaded/i1/10000073270926575/TB2fpg0cXXXXXb6XpXXXXXXXXXX_!!0-0-juitemmedia.jpg"
+imageUrl2 = "http://img4.duitang.com/uploads/item/201306/25/20130625045508_sairr.thumb.600_0.jpeg"
+collectionView = RefreshCollectionView {
+ Section = {
+ SectionCount = 26,
+ RowCount = function(section, row)
+ return 8;
+ end,
+ },
+ Cell = {
+ Id = function ( section, row )
+ if (section == 1 and row ==1) then
+ return "Pager"
+ end
+
+ if (row == 2) then
+ return "PinnedCell1", Pinned.YES;
+ -- if (section == 2 and row == 1) then
+ -- return "PinnedScrollCell", Pinned.YES;
+ else
+ return "ImageAndLabel"
+ end
+ end,
+ PinnedScrollCell = {
+ Size = function(section, row)
+ return w, 60;
+ end,
+ Init = function(cell, section, row)
+ cell.window.backgroundColor(0xf0ff97)
+ cell.scrollView = HScrollView();
+ cell.scrollView.frame(0, 0, w, 60);
+ cell.views = {};
+ for i = 0, 30, 1 do
+ local btn = Label()
+ btn.text(section .. " BTN " .. i)
+ btn.frame(0, 0, 60, 40)
+ btn.backgroundColor(0xff00ff00)
+ local view = View()
+ view.frame(i * 60, 10, 60, 50)
+ view.callback(
+ function()
+ Toast(btn.text())
+ cell.window.backgroundColor(0x032f00)
+ end
+ )
+ view.addView(btn)
+ cell.scrollView.addView(view)
+ cell.views[i] = view;
+ end
+ cell.scrollView.contentSize(30*60,0);
+ end,
+ Layout = function(cell, section, row)
+ end
+ },
+ PinnedCell1 = {
+ Size = function(section, row)
+ return w, 50;
+ end,
+ Init = function(cell, section, row)
+ cell.title = Label();
+ cell.title.frame(50, 0, 100, 50);
+ cell.title.backgroundColor(0xffffff)
+ if (section % 2 == 1) then
+ cell.window.backgroundColor(0x80ffff)
+ else
+ cell.window.backgroundColor(0x80f56f)
+ end
+ end,
+ Layout = function(cell, section, row)
+ cell.title.text("Type " .. section);
+ if (section % 2 == 1) then
+ cell.title.textColor(0x00f309)
+ else
+ cell.title.textColor(0x000000)
+ end
+
+ end,
+
+ Callback = {
+ Click = function()
+ end,
+ LongClick = function()
+ end
+ }
+ },
+ Pager = {
+ Size = function(section, row)
+ return w, 200;
+ end,
+ Init = function(cell, section, row)
+ local cellWidth ,cellHeight = cell.window.size();
+ cell.pagerView = PagerView({
+ PageCount = function()
+ return 2
+ end,
+ Pages = {
+ Title = function(pos)
+ return "Title"
+ end,
+ Init = function(page, pos)
+ page.icon = Button()
+ if (pos == 1) then
+ page.icon.backgroundColor(0x00ff00)
+ else
+ page.icon.backgroundColor(0x00ffff)
+ end
+ end,
+ Layout = function(page, pos)
+ page.icon.text("测试按钮"..pos)
+ page.icon.frame(0, 0, cell.pagerView.width()-60, 150)
+ end
+ },
+ Callback = {
+ Scrolling=function(pos, percent, distance)
+ Toast("滑动"..pos)
+ end,
+ Selected=function(pos)
+ Toast("选中"..pos)
+ end
+ }
+ })
+ cell.pagerView.frame(0, 0, cellWidth, cellHeight);
+ cell.pagerView.looping(true)
+ cell.pagerView.autoScroll()
+ -- cell.pagerView.nativeView().setClipToPadding(false)
+ -- cell.pagerView.nativeView().setPadding(150, 0, 150, 0)
+ cell.pagerView.previewSide(30, 30)
+ -- cell.pagerView.backgroundColor(0xff0000)
+ local createCircleIndicator = function ()
+ local indicator = PagerIndicator()
+ -- indicator.size(SCREEN_WIDTH / 2, 100)
+ -- indicator.alignCenter()
+ -- print("tuoli", cell.pagerView.width())
+ indicator.frame(0, 180, cell.pagerView.width(), 30)
+ indicator.selectedColor(0xff0000)
+ indicator.unselectedColor(0x00ff00)
+ -- indicator.fillColor(0xff0000)
+ -- indicator.pageColor(0x00ff00)
+ return indicator
+ end
+
+ --活动指示器
+ cell.pagerView.indicator(createCircleIndicator())
+ end,
+ Layout = function(cell , section, row)
+ -- cell.icon.image(imageUrl1, function()
+ -- local x,y,w,h = cell.icon.frame();
+ -- end);
+ end,
+ Callback = function(cell, section, row)
+ end
+ },
+ ImageAndLabel = {
+ Size = function(section, row)
+ return w ,200;
+ end,
+ Init = function(cell, section, row)
+ local cellWidth ,cellHeight = cell.window.size();
+ cellHeight = cellHeight / 2;
+ cell.icon = Image();
+ cell.icon.frame(0, 0, cellHeight, cellHeight);
+ cell.title = Label();
+ cell.title.frame(0, cellHeight, cellHeight, cellHeight/2);
+ cell.title.textColor(0xffFFFF);
+ cell.title.backgroundColor(0xff00ff);
+ end,
+ Layout = function(cell , section, row)
+ cell.icon.image(imageUrl1, function()
+ local x,y,w,h = cell.icon.frame();
+ end);
+ cell.title.text("测试"..section .."--" .. row);
+ cell.window.backgroundColor( section*0x770000 + (row%3)*0x33 );
+ end,
+ Callback = function(cell, section, row)
+ print(section, row);
+ System.gc();
+ collectionView.scrollToCell(section, row);
+ end
+ },
+ ImageAndLabel2 = {
+ Size = function(section, row)
+ return w ,200;
+ end,
+ Init = function(cell)
+ local cellHeight = 100
+ cell.icon = Image();
+ cell.icon.frame(w*0.05, 10, cellHeight, cellHeight);
+ cell.icon2 = Image();
+ cell.icon2.frame(160, 0, cellHeight, cellHeight);
+ cell.button = Button();
+ cell.button.frame(0,0,100,60);
+ cell.button.backgroundColor(0x777777);
+ cell.button.callback(
+ function()
+ Toast("hhhhhhh");
+ end);
+ end,
+ Layout = function(cell , section, row)
+ cell.icon.image(
+ imageUrl1,
+ function()
+ local x,y,w,h = cell.icon.frame();
+ end);
+ cell.icon2.image(imageUrl1)
+ cell.window.backgroundColor( section*0x770000 + (row%3)*0x33 );
+ end,
+ Callback = {
+ Click = function()
+ print("tuoli ImageAndLabel2 Click")
+ end,
+ LongClick = function()
+ end
+ }
+ }
+ },
+ Callback = {
+ Scrolling = function( firstVisibleSection, firstVisibleRow, visibleCellCount )
+ -- print("scrolling", firstVisibleSection,"---" ,firstVisibleRow, "---", visibleCellCount);
+ end,
+ ScrollBegin = function(firstVisibleSection, firstVisibleRow, visibleCellCount )
+ -- print("scrolling begin", firstVisibleSection,"---" ,firstVisibleRow, "---", visibleCellCount);
+ end,
+ ScrollEnd = function(firstVisibleSection, firstVisibleRow, visibleCellCount )
+ -- print("scrolling end", firstVisibleSection,"---" ,firstVisibleRow, "---", visibleCellCount);
+ end,
+ PullDown = function()
+ collectionView.stopRefreshing()
+ collectionView.reload()
+ end
+ }
+};
+collectionView.frame(0,0,w,h-64);
+collectionView.backgroundColor(0xffFFFF);
+collectionView.miniSpacing(5)
+
+print("tuoli System.vmVersion = ", System.vmVersion() )
+
diff --git a/Android/LuaViewDemo/assets/test/UI_RefreshCollectionView.lua b/Android/LuaViewDemo/assets/test/UI_RefreshCollectionView.lua
new file mode 100644
index 00000000..7c299a08
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_RefreshCollectionView.lua
@@ -0,0 +1,125 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+w, h = System.screenSize();
+
+cellHeight = 100
+imageUrl1 = "http://gju2.alicdn.com/bao/uploaded/i1/10000073270926575/TB2fpg0cXXXXXb6XpXXXXXXXXXX_!!0-0-juitemmedia.jpg"
+imageUrl2 = "http://img4.duitang.com/uploads/item/201306/25/20130625045508_sairr.thumb.600_0.jpeg"
+
+collectionView = RefreshCollectionView {
+ Section = {
+ SectionCount = 10,
+ RowCount = function(section)
+ if(section == 4 or section == 6) then
+ return 10;
+ end
+ return 1
+ end
+ },
+ Cell = {
+ Id = function(section, row)
+ if (section == 4) then
+ return "ImageAndLabel";
+ elseif(section == 6) then
+ return "ImageAndImage";
+ end
+ return "NONE"
+ end,
+ NONE = {
+ Init = function(cell)
+ end,
+ Layout = function(cell, section, row)
+ cell.line = View();
+ cell.line.size(w, 1)
+ cell.line.backgroundColor(0xff0000);
+ end,
+ Size = function(section, row)
+ return w, 1;
+ end,
+ Callback = function(cell, section, row)
+ end
+
+ },
+ ImageAndLabel = {
+ Size = function(section, row)
+ return 50, cellHeight;
+ end,
+ Init = function(cell, section, row)
+ cell.bg = View()
+ cell.icon = Image();
+ cell.title = Label();
+ print("构造Cell");
+ end,
+ Layout = function(cell, section, row)
+ cell.icon.frame(0, 0, 20, 50);
+ cell.icon.image(imageUrl1, function()
+ print("imageLoaded-ImageAndLabel", section, row)
+ end);
+
+ cell.title.frame(20, 0, w - 20, cellHeight);
+ cell.title.text("测试" .. section .. "--" .. row);
+
+ cell.bg.addView(cell.bg)
+ end,
+ Callback = function(section, row)
+ print(section, row);
+ collectionView.stopRefreshing();
+ System.gc();
+ end
+ },
+ ImageAndImage = {
+ Size = function(section, row)
+ return cellHeight;
+ end,
+ Init = function(cell, section, row)
+ cell.icon = Image();
+ cell.icon2 = Image();
+ end,
+ Layout = function(cell, section, row)
+ print(window);
+ local cellWdith, cellHeight = cell.window.size();
+ cell.icon.frame(0, 0, cellHeight, cellHeight);
+ cell.icon.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-1", section, row)
+ end);
+
+
+ cell.icon2.frame(cellHeight + 10, 0, cellHeight, cellHeight);
+ cell.icon2.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-2", section, row)
+ end);
+ end,
+ Callback = function(section, row)
+ print(section, row);
+ collectionView.stopRefreshing();
+ System.gc();
+ end
+ }
+ },
+ Callback = {
+ Scrolling = function()
+ print("scrolling");
+ end,
+ ScrollBegin = function()
+ print("scrolling begin");
+ end,
+ ScrollEnd = function()
+ print("scrolling end");
+ end,
+ PullDown = function()
+ print("PullDown");
+ end
+ }
+};
+
+loading = false;
+
+collectionView.frame(0, 0, w, h - 64);
+collectionView.showScrollIndicator(false)
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_RefreshTableView.lua b/Android/LuaViewDemo/assets/test/UI_RefreshTableView.lua
new file mode 100644
index 00000000..15f88dba
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_RefreshTableView.lua
@@ -0,0 +1,108 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+w, h = System.screenSize();
+cellHeight = 100
+imageUrl1 = "http://gju2.alicdn.com/bao/uploaded/i1/10000073270926575/TB2fpg0cXXXXXb6XpXXXXXXXXXX_!!0-0-juitemmedia.jpg"
+imageUrl2 = "http://img4.duitang.com/uploads/item/201306/25/20130625045508_sairr.thumb.600_0.jpeg"
+
+tableView = RefreshTableView {
+ Section = {
+ SectionCount = 2,
+ RowCount = function(section)
+ return 10;
+ end
+ },
+ Cell = {
+ Id = function(section, row)
+ if (section == 1) then
+ return "ImageAndLabel";
+ else
+ return "ImageAndImage";
+ end
+ end,
+ ImageAndLabel = {
+ Size = function(section, row)
+ return cellHeight;
+ end,
+ Init = function(cell, section, row)
+ cell.icon = Image();
+ cell.title = Label();
+ print("构造Cell");
+
+ cell.bg = Button()
+ end,
+ Layout = function(cell, section, row)
+ cell.icon.frame(20, 0, cellHeight, cellHeight);
+ cell.icon.image(imageUrl1, function()
+ print("imageLoaded-ImageAndLabel", section, row)
+ end);
+
+ cell.title.frame(20 + cellHeight, 0, w - cellHeight, cellHeight);
+ cell.title.text("测试" .. section .. "--" .. row);
+
+
+ cell.bg.frame(0, 0, w, cellHeight)
+ cell.bg.image(nil, imageUrl1)
+ end,
+ Callback = function(section, row)
+ print(section, row);
+ tableView.stopRefreshing();
+ System.gc();
+ end
+ },
+ ImageAndImage = {
+ Size = function(section, row)
+ return cellHeight;
+ end,
+ Init = function(cell, section, row)
+ cell.icon = Image();
+ cell.icon2 = Image();
+ end,
+ Layout = function(cell, section, row)
+ print(cell.window, "xxxxx");
+ local cellWdith, cellHeight = cell.window.size();
+ cell.icon.frame(0, 0, cellHeight, cellHeight);
+ cell.icon.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-1", section, row)
+ end);
+
+
+ cell.icon2.frame(cellHeight + 10, 0, cellHeight, cellHeight);
+ cell.icon2.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-2", section, row)
+ end);
+ end,
+ Callback = function(section, row)
+ print(section, row);
+ tableView.stopRefreshing();
+ System.gc();
+ end
+ }
+ },
+ Callback = {
+ Scrolling = function()
+ print("scrolling");
+ end,
+ ScrollBegin = function()
+ print("scrolling begin");
+ end,
+ ScrollEnd = function()
+ print("scrolling end");
+ end,
+ PullDown = function()
+ print("PullDown");
+ end
+ }
+};
+
+loading = false;
+
+tableView.frame(0, 0, w, h - 64);
+tableView.showScrollIndicator(false)
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_ScaleType.lua b/Android/LuaViewDemo/assets/test/UI_ScaleType.lua
new file mode 100644
index 00000000..f39c0fb0
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_ScaleType.lua
@@ -0,0 +1,70 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--
+-- Created by IntelliJ IDEA.
+-- User: song
+-- Date: 16/10/13
+-- Time: 下午2:32
+-- To change this template use File | Settings | File Templates.
+--
+
+--2. 普通构造传url
+v1 = Image()
+v1.frame(0, 0, 100, 100)
+v1.scaleType(ScaleType.FIT_XY)
+v1.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+
+v2 = Image()
+v2.frame(101, 0, 100, 100)
+v2.scaleType(ScaleType.FIT_START)
+v2.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+
+v3 = Image()
+v3.frame(202, 0, 100, 100)
+v3.scaleType(ScaleType.FIT_END)
+v3.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+
+
+v4 = Image()
+v4.scaleType(ScaleType.FIT_CENTER)
+v4.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+v4.frame(0, 101, 100, 100)
+
+v5 = Image()
+v5.scaleType(ScaleType.CENTER)
+v5.frame(101, 101, 100, 100)
+v5.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+
+--TODO
+v6 = Image()
+v6.scaleType(ScaleType.CENTER_CROP)
+v6.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+v6.frame(202, 101, 100, 100)
+
+
+v7 = Image()
+v7.scaleType(ScaleType.CENTER_INSIDE)
+v7.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+v7.frame(0, 202, 100, 100)
+
+--TODO
+v8 = Image()
+v8.scaleType(ScaleType.MATRIX)
+v8.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+v8.frame(101, 202, 100, 100)
+
+
+v9 = Image()
+v9.scaleType(ScaleType.CENTER_CROP)
+v9.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+v9.scale(1.2, 1.2)
+v9.frame(0, 303, 100, 100)
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_StyledString.lua b/Android/LuaViewDemo/assets/test/UI_StyledString.lua
new file mode 100644
index 00000000..dc2e3866
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_StyledString.lua
@@ -0,0 +1,52 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--1. 普通设置url,size,center,contentmode等
+
+as0 = StyledString("测试一啊12345", { fontColor = 0xffffff })
+as1 = StyledString("测试一啊12345", { fontColor = 0xffff0000, fontWeight = 600})
+as11 = StyledString("测试一啊12345", { fontColor = 0xffff0000, fontStyle = "bold" })
+as2 = StyledString("测试2", { backgroundColor = 0xaa00ff00, fontSize = 10 })
+as3 = StyledString("3333", { fontColor = 0xff0000ff, fontSize = 14 })
+as4 = StyledString(Unicode(0xe607), { fontColor = 0xff00aaff, fontSize = 40 })
+
+
+label0 = Label()
+label0.text(as0)
+print(label0.textColor())
+
+label = Label()
+label.xy(0, 20)
+label.text(as1)
+
+label2 = Label()
+label2.xy(0, 40)
+label2.text(as11)
+
+button = Button()
+button.text(as2)
+button.xy(0, 60)
+
+
+button2 = Button()
+button2.text(as1 + as2 + as3)
+button2.xy(0, 150)
+
+
+button3 = Button()
+button3.fontName("fonts/iconfont");
+button3.text(as4 + as2)
+button3.xy(0, 200)
+
+print(button3.fontName())
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_TableView.lua b/Android/LuaViewDemo/assets/test/UI_TableView.lua
new file mode 100644
index 00000000..ac5d3ff1
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_TableView.lua
@@ -0,0 +1,63 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+-- 变量定义
+local s_width, s_height = System.screenSize()
+local tableView
+
+local tableViewData = {
+ Section = {
+ SectionCount = 1, -- section数量
+ RowCount = function(section)
+ return 50
+ end
+ },
+ Cell = {
+ Id = function(section, row) -- 指定section和row对应的Cell类型唯一识别号
+ local id = "Cell1" .. row
+ print("Id", id)
+ return id;
+ end
+ }
+}
+
+local cellData = function(_, key)
+ print(key)
+ return {
+ Size = function(section, row)
+ print("Size", section, row, 10 + row * 2)
+ return 10 + row * 2
+ end,
+ Init = function(cell, section, row) -- 初始化cell
+ print("Init", section, row, 10 + row * 2)
+ cell.title = Label();
+ cell.title.backgroundColor(0xff0000)
+ end,
+ Layout = function(cell, section, row) -- cell复用时调用
+ print("Layout", section, row, 10 + row * 2)
+-- cell.title.frame(0, 0, s_width, 10 + row * 2)
+ cell.title.text(section .. '--' .. row)
+ end,
+ Callback = function(cell, section, row) -- 用户点击了section和row
+ Toast("Section " .. section .. ", Row " .. row .. cell.title.frame());
+ end
+ }
+end
+
+setmetatable(tableViewData.Cell, { __index = cellData })
+tableView = TableView(tableViewData)
+tableView.miniSpacing(1)
+tableView.frame(0, 0, s_width, s_height)
+tableView.showScrollIndicator(false)
+tableView.reload()
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_TextField.lua b/Android/LuaViewDemo/assets/test/UI_TextField.lua
new file mode 100644
index 00000000..807697f0
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_TextField.lua
@@ -0,0 +1,36 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "kit/lv_kit"
+
+local width = System.screenSize()
+
+local tf = TextField()
+tf.hint(StyledString("测试额", {fontColor=0xff0000ff, fontSize=80, fontStyle=3, backgroundColor=0x99ff0000}))
+tf.frame(0, 0, width, 100)
+
+tf.callback({
+ BeginEditing=function()
+ Toast("开始编辑")
+ end,
+
+ EndEditing=function()
+ Toast("结束编辑")
+ end
+})
+
+local btn1 = Button()
+btn1.callback(function()
+ tf.text("点击了")
+end)
+
+
+btn1.text("点我试试")
+btn1.frame(0, 100, width, 100)
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_View.lua b/Android/LuaViewDemo/assets/test/UI_View.lua
new file mode 100644
index 00000000..a3804daa
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_View.lua
@@ -0,0 +1,74 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+view = View()
+view.frame(0, 10, 100, 100)
+view.backgroundColor(0x11001100)
+view.borderColor(0x020304)
+view.borderWidth(0.3)
+local x, y = view.center();
+Toast("中心点位置: " .. x .. "," .. y)
+
+print("background-color", view.backgroundColor(), 0x11001100)
+--print("border-color", view.borderColor(), 0x020304)
+--print("border-width", view.borderWidth(), 0.3)
+
+
+view.backgroundColor(1)
+--print(view.backgroundColor())
+
+view.backgroundColor(0x12000001)
+print(view.backgroundColor())
+
+view.backgroundColor(0x000001, 0.5)
+print(view.backgroundColor())
+
+view.backgroundColor(0xff000001, 0.5)
+print(view.backgroundColor())
+
+
+print(view)
+view.children(function(parent)
+ print(parent)
+ local child1 = View()
+ child1.frame(2, 2, 90, 90)
+ child1.backgroundColor(0x00ff00)
+ print(child1)
+ child1.children(function(parent)
+ print(parent)
+ local child2 = View()
+ child2.frame(2, 2, 80, 80)
+ child2.backgroundColor(0xff0000)
+ print(child2)
+ child2.children(function(parent)
+ print(parent)
+ local child3 = View()
+ child3.frame(2, 2, 60, 60)
+ child3.backgroundColor(0x770000ff)
+ end)
+ end)
+end)
+
+
+
+view3 = View()
+view3.frame(120, 50, 100, 100)
+view3.borderColor(0xff0000)
+view3.borderWidth(2)
+
+view4 = View()
+view4.backgroundColor(0x0fffff)
+
+view3.addView(view4)
+view3.nativeView().setClipChildren(true)
+view4.frame(5, -20, 90, 50)
+
+view3.callback(function()
+ print("view4.frame=", view4.frame())
+ Animation().with(view4).translation(0, 40).duration(3).start()
+end)
+
+print("end")
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/UI_ViewEffect.lua b/Android/LuaViewDemo/assets/test/UI_ViewEffect.lua
new file mode 100644
index 00000000..b584f4fd
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_ViewEffect.lua
@@ -0,0 +1,55 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+view = View()
+view.frame(0, 0, 100, 100)
+view.backgroundColor(0xaaaaaa)
+view.callback(function()
+ print("xxxx")
+end)
+
+local view2 = View()
+view2.frame(102, 0, 100, 100)
+view2.backgroundColor(0x00ff00)
+
+
+local image = Image()
+image.frame(100, 100, 100, 100)
+image.backgroundColor(0xdcdcdc)
+-- 网络图有问题,属于GlideImageProvider造成的问题
+ image.image("https://gju1.alicdn.com/bao/uploaded/i4/100000120700895002/TB2Qu0_fXXXXXb9XpXXXXXXXXXX_!!0-0-juitemmedia.jpg_560x560Q90.jpg")
+--image.image("animate1")
+image.effects(ViewEffect.CLICK, 0xff0000, 0.6)
+image.callback(function()
+ print("yyy")
+end)
+
+
+local button = Button()
+button.frame(100, 200, 100, 100)
+button.text("Button")
+button.backgroundColor(0xdcdcdc)
+button.callback(function()
+ local effect = view.effects()
+ if(effect == ViewEffect.CLICK) then
+ view.effects(ViewEffect.NONE)
+ else
+ view.effects(ViewEffect.CLICK)
+ end
+ print("Change ViewEffect", view.effects())
+end)
+button.effects(ViewEffect.CLICK)
+
+
+imageView2 = Image();
+imageView2.frame( 50, 300, 300, 200);
+imageView2.image("http://g.alicdn.com/ju/lua/2.0.24/doc/icon.png");
+
+imageView2.effects(ViewEffect.PARALLAX, 150, 140)
+imageView2.effects(ViewEffect.CLICK, 0xff0000, 0.6)
+imageView2.callback(function()
+ print("yyy")
+end)
\ No newline at end of file
diff --git a/Android/LuaViewDemo/assets/test/UI_WebView.lua b/Android/LuaViewDemo/assets/test/UI_WebView.lua
new file mode 100644
index 00000000..9f4c6ac5
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_WebView.lua
@@ -0,0 +1,161 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+
+local function createRootView(params)
+ local rootView = View()
+ rootView.frame(params.x, params.y, params.w, params.h)
+ return rootView
+end
+
+local function createWebView(rootView, params)
+ local webview = WebView()
+ webview.frame(params.x, params.y, params.w, params.h)
+ webview.loadUrl(params.url)
+ webview.callback(params.callbacks)
+ webview.removeFromSuper()
+ rootView.addView(webview)
+ return webview
+end
+
+local function test(rootView, params)
+ local button = Button()
+ button.frame(params.x, params.y, params.w, params.h)
+ button.text(params.text)
+ button.callback(params.callback)
+ button.removeFromSuper()
+ rootView.addView(button)
+end
+
+local function main()
+ local scrW, scrH = System.screenSize()
+
+ local rootViewParams = {
+ x = 0,
+ y = 0,
+ w = scrW,
+ h = scrH
+ }
+ local rootView = createRootView(rootViewParams)
+
+ local webViewParams = {
+ x = 0,
+ y = 0,
+ w = scrW,
+ h = scrH - 350,
+ url = "http://m.taobao.com",
+ callbacks = {
+ onPageStarted = function()
+ print("started")
+ end,
+ onPageFinished = function()
+ print("finished")
+ end,
+ onReceiveError = function(errorCode, description, failedUrl)
+ print("error", errorCode, description, failedUrl)
+ end
+ }
+ }
+ local webview = createWebView(rootView, webViewParams)
+
+ local backParams = {
+ x = 0,
+ y = 400,
+ w = 80,
+ h = 80,
+ text = "back",
+ callback = function()
+ if webview.canGoBack() then
+ webview.goBack()
+ end
+ end
+ }
+ test(rootView, backParams)
+
+ local forwardParams = {
+ x = 100,
+ y = 400,
+ w = 80,
+ h = 80,
+ text = "forward",
+ callback = function()
+ if webview.canGoForward() then
+ webview.goForward()
+ end
+ end
+ }
+ test(rootView, forwardParams)
+
+ local reloadParams = {
+ x = 200,
+ y = 400,
+ w = 80,
+ h = 80,
+ text = "reload",
+ callback = function()
+ webview.reload()
+ end
+ }
+ test(rootView, reloadParams)
+
+ local stopLoadingParams = {
+ x = 300,
+ y = 400,
+ w = 80,
+ h = 80,
+ text = "stopLoading",
+ callback = function()
+ webview.stopLoading()
+ end
+ }
+ test(rootView, stopLoadingParams)
+
+ local getUrlParams = {
+ x = 0,
+ y = 500,
+ w = 80,
+ h = 80,
+ text = "getUrl",
+ callback = function()
+ Alert(webview.url())
+ end
+ }
+ test(rootView, getUrlParams)
+
+ local getTitleParams = {
+ x = 100,
+ y = 500,
+ w = 80,
+ h = 80,
+ text = "getTitle",
+ callback = function()
+ Alert(webview.title())
+ end
+ }
+ test(rootView, getTitleParams)
+
+ local canPullParams = {
+ x = 200,
+ y = 500,
+ w = 80,
+ h = 80,
+ text = "canPull",
+ callback = function()
+ if webview.pullRefreshEnable() == true then
+ webview.pullRefreshEnable(false)
+ else
+ webview.pullRefreshEnable(true)
+ end
+ end
+ }
+ test(rootView, canPullParams)
+end
+
+main()
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/UI_Window.lua b/Android/LuaViewDemo/assets/test/UI_Window.lua
new file mode 100644
index 00000000..32c4f9b7
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/UI_Window.lua
@@ -0,0 +1,59 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+scrW, scrH = System.screenSize()
+error = Button()
+error.text("xxxx")
+error.frame(0, 0, scrW, scrH - 50);
+error.backgroundColor(0xffff00)
+error.callback(function()
+ hideError();
+end);
+
+function showError()
+ window.addView(error);
+end
+
+function hideError()
+ error.removeFromSuper();
+end
+
+hideError();
+showError();
+
+
+
+window.callback({
+ onShow = function()
+ print("onShow")
+ end,
+ onHide = function()
+ print("onHide")
+ end,
+ onBack = function()
+ print("onBack")
+
+
+ Toast("onBack")
+ return true
+ end,
+ onWifiConnected = function()
+ print("onWifiConnected")
+ print(System.network())
+ end,
+ onMobileConnected = function()
+ print("onMobileConnected")
+ print(System.network())
+ end,
+ onConnectionClosed = function()
+ print("onConnectionClosed")
+ print(System.network())
+ end,
+ onLayout = function()
+ print("onLayout")
+ end
+})
+
diff --git a/Android/LuaViewDemo/assets/test/bundle/lv_kit.lua b/Android/LuaViewDemo/assets/test/bundle/lv_kit.lua
new file mode 100644
index 00000000..93f274c7
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/bundle/lv_kit.lua
@@ -0,0 +1,85 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+-- LuaView 相关的kit
+-- Created by IntelliJ IDEA.
+-- User: song
+-- Date: 15/9/8
+-- Time: 上午10:33
+--
+
+
+--1. Lua Table View by Elertan
+function printTable(t, exclusions)
+ if (type(t) == "table") then
+ local nests = 0
+ if not exclusions then exclusions = {} end
+ local recurse = function(t, recurse, exclusions)
+ indent = function()
+ local dent = ""
+ for i = 1, nests do
+ dent = dent .. " "
+ end
+ return dent
+ end
+ local excluded = function(key)
+ for k, v in pairs(exclusions) do
+ if v == key then
+ return true
+ end
+ end
+ return false
+ end
+ local isFirst = true
+ for k, v in pairs(t) do
+ local dent = indent()
+ if isFirst then
+ print(dent .. "|")
+ isFirst = false
+ end
+ dent = indent()
+ if type(v) == "table" and not excluded(k) then
+ print(dent .. "|- " .. tostring(k) .. ": " .. type(v))
+ nests = nests + 1
+ recurse(v, recurse, exclusions)
+ elseif excluded(k) then
+ print(dent .. "|- " .. tostring(k) .. ": " .. type(v))
+ elseif type(v) == "userdata" or type(v) == "function" then
+ print(dent .. "|- " .. tostring(k) .. ": " .. type(v))
+ elseif type(v) == "string" then
+ print(dent .. "|- " .. tostring(k) .. ": " .. "\"" .. tostring(v) .. "\"")
+ else
+ print(dent .. "|- " .. tostring(k) .. ": " .. tostring(v))
+ end
+ end
+ nests = nests - 1
+ end
+
+ nests = 0
+
+ if t then
+ print("### START TABLE ###")
+ for k, v in pairs(t) do
+ if type(v) == "table" then
+ print("|- " .. k .. ": " .. type(v))
+ nests = nests + 1
+ recurse(v, recurse, exclusions)
+ elseif type(v) == "userdata" or type(v) == "function" then
+ print("|- " .. tostring(k) .. ": " .. type(v))
+ elseif type(v) == "string" then
+ print("|- " .. tostring(k) .. ": " .. "\"" .. tostring(v) .. "\"")
+ else
+ print("|- " .. tostring(k) .. ": " .. tostring(v))
+ end
+ end
+ print("### END TABLE ###")
+ else
+ print("NIL TABLE")
+ end
+ else
+ print(t)
+ end
+end
diff --git a/Android/LuaViewDemo/assets/test/bundle/main.lua b/Android/LuaViewDemo/assets/test/bundle/main.lua
new file mode 100644
index 00000000..c0b5a931
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/bundle/main.lua
@@ -0,0 +1,153 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+--工具包引入
+require "lv_kit"
+
+w, h = System.screenSize()
+
+cellHeight = 100
+imageUrl1 = "http://gju2.alicdn.com/bao/uploaded/i1/10000073270926575/TB2fpg0cXXXXXb6XpXXXXXXXXXX_!!0-0-juitemmedia.jpg"
+imageUrl2 = "http://img4.duitang.com/uploads/item/201306/25/20130625045508_sairr.thumb.600_0.jpeg"
+
+
+local vp = PagerView({
+ PageCount = 4,
+ Pages = {
+ Title = function(pos)
+ return "Title"
+ end,
+ Init = function(page, pos)
+ local tableView = RefreshCollectionView {
+ Section = {
+ SectionCount = 2,
+ RowCount = function(section)
+ if(section == 1) then
+ return 1
+ else
+ return 10
+ end
+ end
+ },
+ Cell = {
+ Id = function(section, row)
+ if(pos % 2 == 0) then
+ if (section == 1) then
+ return "HScroll"
+ else
+ return "ImageAndImage"
+ end
+ else
+ if (section == 1) then
+ return "Pager"
+ else
+ return "ImageAndImage"
+ end
+ end
+ end,
+ HScroll = {
+ Size = function(section, row)
+ return w, 100
+ end,
+ Init = function(cell, section, row)
+ local scrollView = HScrollView()
+ for i = 0, 10, 1 do
+ local btn = Label()
+ btn.text("BTN" .. i)
+ btn.frame(i * 80, 0, 79, 100)
+ btn.backgroundColor(0xff00ff00)
+ btn.callback(function()
+ Toast(btn.text())
+ end)
+ scrollView.addView(btn)
+ end
+ scrollView.size(w, 100)
+ scrollView.backgroundColor(0xffcccccc)
+ cell.container= scrollView
+ end,
+ Layout = function(cell, section, row)
+ end
+ },
+ Pager = {
+ Size = function(section, row)
+ return w, 100
+ end,
+ Init = function(cell, section, row)
+ local vp = PagerView({
+ PageCount = 10,
+ Pages = {
+ Title = function(pos)
+ return "Title"
+ end,
+ Init = function(page, pos)
+ page.icon = Button()
+ end,
+ Layout = function(page, pos)
+ page.icon.text("测试按钮"..pos)
+ page.icon.frame(0, 0, w, 100)
+ page.icon.callback(function()
+ Toast(page.icon.text())
+ end)
+ end
+ }
+ })
+
+ vp.backgroundColor(0xaaaa0000)
+ vp.frame(0, 0, w, 100)
+
+ cell.container = vp
+ end,
+ Layout = function(cell, section, row)
+ end
+ },
+ ImageAndImage = {
+ Size = function(section, row)
+ return cellHeight
+ end,
+ Init = function(cell, section, row)
+ cell.icon = Image()
+ cell.icon2 = Image()
+ end,
+ Layout = function(cell, section, row)
+ local cellWdith, cellHeight = cell.window.size()
+ cell.icon.frame(0, 0, cellHeight, cellHeight)
+ cell.icon.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-1", section, row)
+ end)
+ cell.icon.callback(function()
+ print("cell_icon1")
+ end)
+
+
+ cell.icon2.frame(cellHeight + 10, 0, cellHeight, cellHeight)
+ cell.icon2.image(imageUrl1, function()
+ print("imageLoaded-ImageAndImage-2", section, row)
+ end)
+ cell.icon2.callback(function()
+ print("cell_icon2")
+ end)
+ end
+ }
+ }
+ }
+ tableView.frame(0, 0, w, h - 64)
+
+ page.view = tableView
+
+ end,
+ Layout = function(page, pos)
+ end
+ }
+})
+
+vp.backgroundColor(0xaaaa0000)
+vp.frame(0, 0, w, h)
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/assets/test/fonts/iconfont.ttf b/Android/LuaViewDemo/assets/test/fonts/iconfont.ttf
new file mode 100644
index 00000000..014f80db
Binary files /dev/null and b/Android/LuaViewDemo/assets/test/fonts/iconfont.ttf differ
diff --git a/Android/LuaViewDemo/assets/test/kit/lv_kit.lua b/Android/LuaViewDemo/assets/test/kit/lv_kit.lua
new file mode 100644
index 00000000..93f274c7
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/kit/lv_kit.lua
@@ -0,0 +1,85 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+-- LuaView 相关的kit
+-- Created by IntelliJ IDEA.
+-- User: song
+-- Date: 15/9/8
+-- Time: 上午10:33
+--
+
+
+--1. Lua Table View by Elertan
+function printTable(t, exclusions)
+ if (type(t) == "table") then
+ local nests = 0
+ if not exclusions then exclusions = {} end
+ local recurse = function(t, recurse, exclusions)
+ indent = function()
+ local dent = ""
+ for i = 1, nests do
+ dent = dent .. " "
+ end
+ return dent
+ end
+ local excluded = function(key)
+ for k, v in pairs(exclusions) do
+ if v == key then
+ return true
+ end
+ end
+ return false
+ end
+ local isFirst = true
+ for k, v in pairs(t) do
+ local dent = indent()
+ if isFirst then
+ print(dent .. "|")
+ isFirst = false
+ end
+ dent = indent()
+ if type(v) == "table" and not excluded(k) then
+ print(dent .. "|- " .. tostring(k) .. ": " .. type(v))
+ nests = nests + 1
+ recurse(v, recurse, exclusions)
+ elseif excluded(k) then
+ print(dent .. "|- " .. tostring(k) .. ": " .. type(v))
+ elseif type(v) == "userdata" or type(v) == "function" then
+ print(dent .. "|- " .. tostring(k) .. ": " .. type(v))
+ elseif type(v) == "string" then
+ print(dent .. "|- " .. tostring(k) .. ": " .. "\"" .. tostring(v) .. "\"")
+ else
+ print(dent .. "|- " .. tostring(k) .. ": " .. tostring(v))
+ end
+ end
+ nests = nests - 1
+ end
+
+ nests = 0
+
+ if t then
+ print("### START TABLE ###")
+ for k, v in pairs(t) do
+ if type(v) == "table" then
+ print("|- " .. k .. ": " .. type(v))
+ nests = nests + 1
+ recurse(v, recurse, exclusions)
+ elseif type(v) == "userdata" or type(v) == "function" then
+ print("|- " .. tostring(k) .. ": " .. type(v))
+ elseif type(v) == "string" then
+ print("|- " .. tostring(k) .. ": " .. "\"" .. tostring(v) .. "\"")
+ else
+ print("|- " .. tostring(k) .. ": " .. tostring(v))
+ end
+ end
+ print("### END TABLE ###")
+ else
+ print("NIL TABLE")
+ end
+ else
+ print(t)
+ end
+end
diff --git a/Android/LuaViewDemo/assets/test/lvp/UI_Window.luap b/Android/LuaViewDemo/assets/test/lvp/UI_Window.luap
new file mode 100644
index 00000000..760a7ce1
Binary files /dev/null and b/Android/LuaViewDemo/assets/test/lvp/UI_Window.luap differ
diff --git a/Android/LuaViewDemo/assets/test/music/test.mp3 b/Android/LuaViewDemo/assets/test/music/test.mp3
new file mode 100644
index 00000000..6ce1f6ee
Binary files /dev/null and b/Android/LuaViewDemo/assets/test/music/test.mp3 differ
diff --git a/Android/LuaViewDemo/assets/test/test.lua b/Android/LuaViewDemo/assets/test/test.lua
new file mode 100644
index 00000000..0bd0b4ea
--- /dev/null
+++ b/Android/LuaViewDemo/assets/test/test.lua
@@ -0,0 +1,51 @@
+-- Created by LuaView.
+-- Copyright (c) 2017, Alibaba Group. All rights reserved.
+--
+-- This source code is licensed under the MIT.
+-- For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+
+require ""
+str = {"中","华","人","民","共","和","国","万","岁"}
+
+
+txt = Label()
+txt.frame(0, 0, 200, 300)
+txt.backgroundColor(0xdcdcdc)
+
+index = 1
+
+t = ""
+
+timer = Timer()
+timer.callback(function()
+-- t = t .. string:char(str, index)
+
+ print(string:char(str, index))
+-- txt.text(string:char(str, 1, index))
+-- index = index + SubStringGetByteCount(str, index)
+
+-- t = t .. str[index]
+ txt.text(t)
+ index = index + 1
+
+end)
+
+--返回当前字符实际占用的字符数
+function SubStringGetByteCount(str, index)
+ local curByte = string:byte(str, index)
+ local byteCount = 1;
+ if curByte == nil then
+ byteCount = 0
+ elseif curByte > 0 and curByte <= 127 then
+ byteCount = 1
+ elseif curByte>=192 and curByte<223 then
+ byteCount = 2
+ elseif curByte>=224 and curByte<239 then
+ byteCount = 3
+ elseif curByte>=240 and curByte<=247 then
+ byteCount = 4
+ end
+ return byteCount;
+end
+
+timer.start(0.5, true)
\ No newline at end of file
diff --git a/Android/LuaViewDemo/build.gradle b/Android/LuaViewDemo/build.gradle
new file mode 100644
index 00000000..2e484d02
--- /dev/null
+++ b/Android/LuaViewDemo/build.gradle
@@ -0,0 +1,73 @@
+//运行配置
+apply plugin: 'android'
+
+description = """LuaView-Android-Demo: 用lua写Android、iOS"""
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+ jcenter()
+}
+
+configurations {
+ providedCompile
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+
+ //LuaViewSDK
+ compile project(':LuaViewSDK')
+
+ //glide for imageview
+ compile 'com.github.bumptech.glide:glide:3.7.0'
+}
+
+/*
+ 定义android插件
+*/
+android {
+ compileSdkVersion 23
+ buildToolsVersion '25.0.0'
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ resources.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ }
+
+ // Move the tests to tests/java, tests/res, etc...
+ instrumentTest.setRoot('tests')
+
+ // Move the build types to build-types/
+ // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
+ // This moves them out of them default location under src//... which would
+ // conflict with src/ being used by the main source set.
+ // Adding new build types or product flavors should be accompanied
+ // by a similar customization.
+ debug.setRoot('build-types/debug')
+ release.setRoot('build-types/release')
+ }
+ packagingOptions {
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE.txt'
+ }
+
+ buildTypes{
+ debug{
+ proguardFile("proguard.cfg")
+ }
+ }
+ lintOptions {
+ checkReleaseBuilds false
+ // Or, if you prefer, you can continue to check for errors in release builds,
+ // but continue the build even when errors are found:
+ abortOnError false
+ }
+}
+
diff --git a/Android/LuaViewDemo/proguard-rules.pro b/Android/LuaViewDemo/proguard-rules.pro
new file mode 100644
index 00000000..8b3bf7ef
--- /dev/null
+++ b/Android/LuaViewDemo/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/song/AndroidSDK/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/Android/LuaViewDemo/proguard.cfg b/Android/LuaViewDemo/proguard.cfg
new file mode 100644
index 00000000..4fd55b83
--- /dev/null
+++ b/Android/LuaViewDemo/proguard.cfg
@@ -0,0 +1,6 @@
+# proguard for Glide
+-keep public class * implements com.bumptech.glide.module.GlideModule
+-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
+ **[] $VALUES;
+ public *;
+}
diff --git a/Android/LuaViewDemo/res/drawable-hdpi/ic_launcher.png b/Android/LuaViewDemo/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..288b6655
Binary files /dev/null and b/Android/LuaViewDemo/res/drawable-hdpi/ic_launcher.png differ
diff --git a/Android/LuaViewDemo/res/drawable-mdpi/ic_launcher.png b/Android/LuaViewDemo/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..6ae570b4
Binary files /dev/null and b/Android/LuaViewDemo/res/drawable-mdpi/ic_launcher.png differ
diff --git a/Android/LuaViewDemo/res/drawable-xhdpi/ic_launcher.png b/Android/LuaViewDemo/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..d4fb7cd9
Binary files /dev/null and b/Android/LuaViewDemo/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/Android/LuaViewDemo/res/drawable-xxhdpi/ic_launcher.png b/Android/LuaViewDemo/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..85a60815
Binary files /dev/null and b/Android/LuaViewDemo/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/Android/LuaViewDemo/res/drawable/animate1.jpeg b/Android/LuaViewDemo/res/drawable/animate1.jpeg
new file mode 100644
index 00000000..62ee8183
Binary files /dev/null and b/Android/LuaViewDemo/res/drawable/animate1.jpeg differ
diff --git a/Android/LuaViewDemo/res/drawable/animate2.jpeg b/Android/LuaViewDemo/res/drawable/animate2.jpeg
new file mode 100644
index 00000000..4a2cf581
Binary files /dev/null and b/Android/LuaViewDemo/res/drawable/animate2.jpeg differ
diff --git a/Android/LuaViewDemo/res/layout/activity_main.xml b/Android/LuaViewDemo/res/layout/activity_main.xml
new file mode 100644
index 00000000..47bc8969
--- /dev/null
+++ b/Android/LuaViewDemo/res/layout/activity_main.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/Android/LuaViewDemo/res/layout/activity_main2.xml b/Android/LuaViewDemo/res/layout/activity_main2.xml
new file mode 100644
index 00000000..28d40a55
--- /dev/null
+++ b/Android/LuaViewDemo/res/layout/activity_main2.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/res/layout/demo_ac_fragment_container.xml b/Android/LuaViewDemo/res/layout/demo_ac_fragment_container.xml
new file mode 100644
index 00000000..0bbf4ce8
--- /dev/null
+++ b/Android/LuaViewDemo/res/layout/demo_ac_fragment_container.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/Android/LuaViewDemo/res/values-w820dp/dimens.xml b/Android/LuaViewDemo/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..63fc8164
--- /dev/null
+++ b/Android/LuaViewDemo/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/Android/LuaViewDemo/res/values/dimens.xml b/Android/LuaViewDemo/res/values/dimens.xml
new file mode 100644
index 00000000..47c82246
--- /dev/null
+++ b/Android/LuaViewDemo/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/Android/LuaViewDemo/res/values/strings.xml b/Android/LuaViewDemo/res/values/strings.xml
new file mode 100644
index 00000000..e6998682
--- /dev/null
+++ b/Android/LuaViewDemo/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+
+
+ LuaView
+ LuaView SDK Demo
+
+
diff --git a/Android/LuaViewDemo/res/values/styles.xml b/Android/LuaViewDemo/res/values/styles.xml
new file mode 100644
index 00000000..0309de5a
--- /dev/null
+++ b/Android/LuaViewDemo/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/Demo2Activity.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/Demo2Activity.java
new file mode 100644
index 00000000..48ddcec9
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/Demo2Activity.java
@@ -0,0 +1,80 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.activity;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+
+import com.taobao.android.luaview.demo.R;
+
+public class Demo2Activity extends Activity {
+
+ private ViewGroup mContainer = null;
+ private View child = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ test0();
+
+// test();
+ }
+
+ private void test0() {
+ setContentView(R.layout.activity_main2);
+
+ mContainer = (ViewGroup) this.findViewById(R.id.container);
+ child = this.findViewById(R.id.child);
+
+ child.setOnClickListener(new View.OnClickListener(){
+
+ @Override
+ public void onClick(View v) {
+ child.animate().translationY(-200).setDuration(2000).start();
+ }
+ });
+ }
+
+ private void test() {
+ mContainer = new RelativeLayout(this);
+
+ mContainer.setBackgroundColor(Color.RED);
+ mContainer.setAlpha(0.5f);
+
+ child = new RelativeLayout(this);
+
+ child.setBackgroundColor(Color.BLUE);
+ child.setAlpha(0.5f);
+
+
+ mContainer.addView(child, new ViewGroup.MarginLayoutParams(300, 300));
+
+ ((ViewGroup.MarginLayoutParams)child.getLayoutParams()).leftMargin = 0;
+ ((ViewGroup.MarginLayoutParams)child.getLayoutParams()).topMargin = 200;
+
+
+ child.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ child.animate().translationY(-200).setDuration(2000).start();
+ }
+ });
+
+ setContentView(mContainer, new ViewGroup.MarginLayoutParams(300, 300));
+
+ ((ViewGroup.MarginLayoutParams)mContainer.getLayoutParams()).leftMargin = 200;
+ ((ViewGroup.MarginLayoutParams)mContainer.getLayoutParams()).topMargin = 200;
+ }
+}
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/DemoActivity.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/DemoActivity.java
new file mode 100644
index 00000000..d2401831
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/DemoActivity.java
@@ -0,0 +1,90 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.activity;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+
+import com.taobao.luaview.global.Constants;
+import com.taobao.luaview.global.LuaViewConfig;
+import com.taobao.luaview.scriptbundle.LuaScriptManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class DemoActivity extends ListActivity {
+ //测试标准语法
+ public static boolean useStandardSyntax = true;
+
+ //非标准语法代码路径
+ private static final String FOLDER_NAME = "test";
+
+ //标准语法代码路径
+ private static final String FOLDER_STANDARD_NAME = "test-standard";
+
+ private String getFolderName() {
+ return (useStandardSyntax ? FOLDER_STANDARD_NAME : FOLDER_NAME);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ initContent();
+ initLuaView();
+ }
+
+ private void initContent() {
+ final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, getContentData());
+
+ getListView().setAdapter(adapter);
+ getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ final String fileName = adapter.getItem(position - getListView().getHeaderViewsCount());
+ final Intent intent = new Intent(DemoActivity.this, DemoLuaViewActivity.class);
+ intent.putExtra(Constants.PARAM_URI, getFolderName() + "/" + fileName);
+ startActivity(intent);
+ }
+ });
+ }
+
+ private List getContentData() {
+ String[] array = null;
+ List result = new ArrayList();
+ try {
+ array = getResources().getAssets().list(getFolderName());
+
+ if (array != null) {
+ for (String name : array) {
+ if (LuaScriptManager.isLuaScript(name)) {
+ result.add(name);
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * 初始化LuaView
+ */
+ private void initLuaView() {
+ LuaViewConfig.init(this);//初始化,只需要调用一次
+ LuaViewConfig.setDebug(true);//设置是否debug,默认release模式下不会开启
+ LuaViewConfig.setOpenDebugger(false);//是否开启调试器,默认模拟器环境会开启,真机不会开启。TODO Android 真机调试
+ LuaViewConfig.setAutoSetupClickEffects(true);//是否自动设置点击效果(如果有点击事件会自动设置)
+ }
+}
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/DemoLuaViewActivity.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/DemoLuaViewActivity.java
new file mode 100644
index 00000000..73d60788
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/DemoLuaViewActivity.java
@@ -0,0 +1,177 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.activity;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.taobao.luaview.demo.provider.GlideImageProvider;
+import com.taobao.luaview.demo.ui.CustomError;
+import com.taobao.luaview.demo.ui.CustomLoading;
+import com.taobao.luaview.global.Constants;
+import com.taobao.luaview.global.LuaScriptLoader;
+import com.taobao.luaview.global.LuaView;
+import com.taobao.luaview.scriptbundle.ScriptBundle;
+import com.taobao.luaview.util.AssetUtil;
+import com.taobao.luaview.util.JsonUtil;
+import com.taobao.luaview.util.LogUtil;
+import com.taobao.luaview.view.LVLoadingDialog;
+
+import org.luaj.vm2.LuaValue;
+
+/**
+ * 通过LuaView、注入bridge对象,实现Lua-Java通信
+ *
+ * @author song
+ * @date 15/11/11
+ * 主要功能描述
+ * 修改描述
+ * 下午4:50 song XXX
+ */
+public class DemoLuaViewActivity extends Activity {
+ private LuaView mLuaView;
+ private LVLoadingDialog mDialog;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ initActionBar();
+ showLoading();
+ createLuaViewAsync();
+ }
+
+ private void initActionBar() {
+ getActionBar().setDisplayShowHomeEnabled(false);
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+
+ private void showLoading() {
+ mDialog = new LVLoadingDialog(this);
+ mDialog.show();
+ }
+
+ private void hideLoading() {
+ if (mDialog != null) {
+ mDialog.cancel();
+ }
+ }
+
+ /**
+ * 异步创建LuaView(推荐方式)
+ */
+ private void createLuaViewAsync() {
+ LuaView.createAsync(this, new LuaView.CreatedCallback() {
+ @Override
+ public void onCreated(LuaView luaView) {
+ hideLoading();
+ mLuaView = luaView;
+ if (mLuaView != null) {
+ extendsLuaView(mLuaView);
+ loadScript(mLuaView);
+ setContentView(mLuaView);
+ }
+ }
+ });
+ }
+
+ /**
+ * 同步创建LuaView
+ */
+ private void createLuaView(){
+ mLuaView = LuaView.create(this);
+ extendsLuaView(mLuaView);
+ loadScript(mLuaView);
+ setContentView(mLuaView);
+ hideLoading();
+ }
+
+
+ /**
+ * 扩展LuaView
+ * 注册Panel(如果已经有UI组件,需要在Lua使用)
+ * 注册Bridge(有部分API或功能,需要在Lua使用)
+ */
+ private void extendsLuaView(final LuaView luaView) {
+ luaView.registerImageProvider(GlideImageProvider.class);
+ luaView.registerPanel(CustomError.class);
+ luaView.registerPanel(CustomLoading.class);
+ luaView.register("bridge", new LuaViewBridge(this));
+ luaView.setUseStandardSyntax(DemoActivity.useStandardSyntax);//是否使用标准语法
+ }
+
+ /**
+ * 加载数据
+ */
+ public void loadScript(final LuaView luaView) {
+ luaView.load(getLuaUri(), new LuaScriptLoader.ScriptExecuteCallback() {
+ @Override
+ public boolean onScriptPrepared(ScriptBundle bundle) {
+ return false;
+ }
+
+ @Override
+ public boolean onScriptCompiled(LuaValue value, LuaValue context, LuaValue view) {
+ return false;
+ }
+
+ @Override
+ public void onScriptExecuted(String uri, boolean executedSuccess) {
+ //测试调用 lua function
+ LogUtil.d("call-lua-function return:", luaView.callLuaFunction("global_fun_test1", 1, "a", 0.1));
+ LogUtil.d("call-lua-function return:", JsonUtil.toString(luaView.callLuaFunction("global_fun_test2", 2, "b", 0.2)));
+ LogUtil.d("call-window-function return:", luaView.callWindowFunction("window_fun1", 3, "c", 0.3));
+ LogUtil.d("call-window-function return:", luaView.callWindowFunction("window_fun2", 4, "d", 0.4));
+ }
+ });
+ }
+
+ /**
+ * load bytecode directly
+ *
+ * @param luaView
+ */
+ public void loadBytecodeScript(final LuaView luaView) {
+ luaView.loadPrototype(AssetUtil.open(this, "test/lvp/UI_Window.luap"), "UI_window", new LuaScriptLoader.ScriptExecuteCallback() {
+ @Override
+ public boolean onScriptPrepared(ScriptBundle bundle) {
+ return false;
+ }
+
+ @Override
+ public boolean onScriptCompiled(LuaValue value, LuaValue context, LuaValue view) {
+ return false;
+ }
+
+ @Override
+ public void onScriptExecuted(String uri, boolean executedSuccess) {
+ }
+ });
+ }
+
+ /**
+ * 获取文件名称
+ *
+ * @return
+ */
+ private String getLuaUri() {
+ if (getIntent() != null && getIntent().hasExtra(Constants.PARAM_URI)) {
+ return getIntent().getStringExtra(Constants.PARAM_URI);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onDestroy() {
+ LogUtil.d("LuaView-onDestroy");
+ super.onDestroy();
+ if (mLuaView != null) {
+ mLuaView.onDestroy();
+ }
+ }
+}
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/LuaViewBridge.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/LuaViewBridge.java
new file mode 100644
index 00000000..de30a498
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/activity/LuaViewBridge.java
@@ -0,0 +1,100 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.activity;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.taobao.luaview.util.LogUtil;
+
+import org.luaj.vm2.LuaTable;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * LuaView & Native 接口
+ *
+ * @author song
+ * @date 15/12/30
+ * 主要功能描述
+ * 修改描述
+ * 下午2:31 song XXX
+ */
+public class LuaViewBridge {
+ private Activity mActivity;
+
+ public LuaViewBridge(Activity activity) {
+ this.mActivity = activity;
+ }
+
+ public void openPage(String pageUri){
+ Intent intent = new Intent();
+ intent.setData(Uri.parse(pageUri));
+ mActivity.startActivity(intent);
+ }
+
+ public boolean isLogin(){
+ return true;
+ }
+
+ public Map testMap() {
+ Map map = new HashMap();
+ map.put("key1", "map1");
+ map.put("key2", "map2");
+ map.put("key3", "map3");
+ return map;
+ }
+
+ public List testList() {
+ return Arrays.asList(new String[]{"list1", "list2", "list3"});
+ }
+
+ public String testString() {
+ return "string";
+ }
+
+ public int testInt() {
+ return 0;
+ }
+
+ public Integer testInt2() {
+ return 1;
+ }
+
+ public long testLong() {
+ return 0L;
+ }
+
+ public Long testLong2() {
+ return 0L;
+ }
+
+ public double testDouble() {
+ return 0.0;
+ }
+
+ public Double testDouble2() {
+ return 0.0;
+ }
+
+ public boolean testBoolean() {
+ return true;
+ }
+
+ public Boolean testBoolean2() {
+ return false;
+ }
+
+ public void testParams(LuaTable value){
+ }
+}
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/fragment/DemoLuaViewFragment.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/fragment/DemoLuaViewFragment.java
new file mode 100644
index 00000000..855c47d0
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/fragment/DemoLuaViewFragment.java
@@ -0,0 +1,49 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.fragment;
+
+import android.os.Bundle;
+
+import com.taobao.luaview.demo.activity.LuaViewBridge;
+import com.taobao.luaview.demo.ui.CustomError;
+import com.taobao.luaview.demo.ui.CustomLoading;
+import com.taobao.luaview.fragment.LuaViewFragment;
+import com.taobao.luaview.global.LuaView;
+
+/**
+ * @author song
+ * @date 15/11/11
+ */
+public class DemoLuaViewFragment extends LuaViewFragment {
+
+ /**
+ * create a new lua view fragment
+ *
+ * @param bundle
+ * @return
+ */
+ public static DemoLuaViewFragment newInstance(Bundle bundle) {
+ DemoLuaViewFragment fragment = new DemoLuaViewFragment();
+ fragment.setArguments(bundle);
+ return fragment;
+ }
+
+ @Override
+ public void registerNameBeforeLoad(LuaView luaView) {
+ super.registerNameBeforeLoad(luaView);
+ luaView.registerPanel(CustomError.class);
+ luaView.registerPanel(CustomLoading.class);
+ luaView.register("viewController", new LuaViewBridge(getActivity()));
+ }
+
+ @Override
+ public void load(final LuaView luaView) {
+ luaView.load("testButton");
+ }
+}
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/provider/GlideConfiguration.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/provider/GlideConfiguration.java
new file mode 100644
index 00000000..32f2c8c2
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/provider/GlideConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.provider;
+
+import android.content.Context;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.GlideBuilder;
+import com.bumptech.glide.load.DecodeFormat;
+import com.bumptech.glide.module.GlideModule;
+
+/**
+ * configuration for glide
+ * @author song
+ */
+public class GlideConfiguration implements GlideModule {
+
+ @Override
+ public void applyOptions(Context context, GlideBuilder builder) {
+ // Apply options to the builder here.
+ builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
+ }
+
+ @Override
+ public void registerComponents(Context context, Glide glide) {
+ // register ModelLoaders here.
+ }
+}
\ No newline at end of file
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/provider/GlideImageProvider.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/provider/GlideImageProvider.java
new file mode 100644
index 00000000..050f2ca5
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/provider/GlideImageProvider.java
@@ -0,0 +1,123 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.provider;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;
+import com.bumptech.glide.load.resource.drawable.GlideDrawable;
+import com.bumptech.glide.request.RequestListener;
+import com.bumptech.glide.request.target.Target;
+import com.taobao.luaview.provider.ImageProvider;
+import com.taobao.luaview.view.imageview.BaseImageView;
+import com.taobao.luaview.view.imageview.DrawableLoadCallback;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * XXX
+ *
+ * @author song
+ * @date 16/4/11
+ * 主要功能描述
+ * 修改描述
+ * 下午5:42 song XXX
+ */
+public class GlideImageProvider implements ImageProvider {
+
+ @Override
+ public void pauseRequests(final ViewGroup view, Context context) {
+ Glide.with(context).pauseRequests();
+ }
+
+ @Override
+ public void resumeRequests(final ViewGroup view, Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ if (context instanceof Activity && (((Activity) context).isFinishing() || ((Activity) context).isDestroyed())) {
+ return;
+ }
+ } else {
+ if (context instanceof Activity && (((Activity) context).isFinishing())) {
+ return;
+ }
+ }
+ if (Glide.with(context).isPaused()) {
+ Glide.with(context).resumeRequests();
+ }
+ }
+
+ /**
+ * load url
+ *
+ * @param referImageView
+ * @param url
+ * @param callback
+ */
+ public void load(final Context context, final WeakReference referImageView, final String url, final WeakReference callback) {
+ if (referImageView != null) {
+ ImageView imageView = referImageView.get();
+ if (imageView != null) {
+ if (callback != null) {
+ Glide.with(context).load(url).listener(new RequestListener() {
+ @Override
+ public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
+ if (callback != null && callback.get() != null) {
+ callback.get().onLoadResult(null);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
+ if (callback != null && callback.get() != null) {
+ callback.get().onLoadResult(resource.getCurrent());
+ }
+ return false;
+ }
+ }).into(imageView);
+ } else {
+ Glide.with(context).load(url).into(imageView);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void preload(final Context context, String url, final DrawableLoadCallback callback) {
+ if (callback != null) {
+ Glide.with(context).load(url).listener(new RequestListener() {
+ @Override
+ public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
+ if (callback != null) {
+ callback.onLoadResult(null);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
+ if (callback != null) {
+ Drawable r = resource instanceof GlideBitmapDrawable ? new BitmapDrawable(context.getResources(), ((GlideBitmapDrawable) resource).getBitmap()) : resource;
+ callback.onLoadResult(r);
+ }
+ return false;
+ }
+ }).preload();
+ } else {
+ Glide.with(context).load(url).preload();
+ }
+ }
+}
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/ui/CustomError.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/ui/CustomError.java
new file mode 100644
index 00000000..f79d15a9
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/ui/CustomError.java
@@ -0,0 +1,51 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.ui;
+
+import android.view.View;
+import android.widget.Button;
+import android.widget.RelativeLayout;
+
+import com.taobao.luaview.util.LuaViewUtil;
+import com.taobao.luaview.view.LVCustomPanel;
+
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaTable;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Varargs;
+
+/**
+ * @author song
+ * @date 15/11/3
+ */
+public class CustomError extends LVCustomPanel {
+
+ public CustomError(Globals globals, LuaValue metaTable, Varargs varargs) {
+ super(globals, metaTable, varargs);
+ }
+
+ @Override
+ public void initPanel() {
+ Button button = new Button(getContext());
+ button.setText("Error");
+
+ LayoutParams relativeLayout = LuaViewUtil.createRelativeLayoutParamsWW();
+ relativeLayout.addRule(RelativeLayout.CENTER_IN_PARENT);
+ addView(button, relativeLayout);
+
+ button.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ LuaTable table = new LuaTable();
+ table.insert(1, LuaValue.valueOf(1.4));
+ callLuaCallback("Message", "Error", 100, new Object(), table);
+ }
+ });
+ }
+}
diff --git a/Android/LuaViewDemo/src/com/taobao/luaview/demo/ui/CustomLoading.java b/Android/LuaViewDemo/src/com/taobao/luaview/demo/ui/CustomLoading.java
new file mode 100644
index 00000000..dba2c242
--- /dev/null
+++ b/Android/LuaViewDemo/src/com/taobao/luaview/demo/ui/CustomLoading.java
@@ -0,0 +1,42 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.demo.ui;
+
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+
+import com.taobao.luaview.util.LuaViewUtil;
+import com.taobao.luaview.view.LVCustomPanel;
+import com.taobao.luaview.view.LVLoadingView;
+
+import org.luaj.vm2.Globals;
+import org.luaj.vm2.LuaValue;
+import org.luaj.vm2.Varargs;
+
+/**
+ * @author song
+ * @date 15/11/3
+ */
+public class CustomLoading extends LVCustomPanel {
+
+ public CustomLoading(Globals globals, LuaValue metaTable, Varargs varargs) {
+ super(globals, metaTable, varargs);
+ }
+
+ @Override
+ public void initPanel() {
+ final View lvLoadingView = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmallInverse);
+ LayoutParams relativeLayout = LuaViewUtil.createRelativeLayoutParamsWW();
+ relativeLayout.addRule(RelativeLayout.CENTER_IN_PARENT);
+ lvLoadingView.setVisibility(View.VISIBLE);
+ addView(lvLoadingView, relativeLayout);
+ }
+}
diff --git a/Android/LuaViewSDK/.gitignore b/Android/LuaViewSDK/.gitignore
new file mode 100644
index 00000000..b3fdf275
--- /dev/null
+++ b/Android/LuaViewSDK/.gitignore
@@ -0,0 +1,2 @@
+build
+target
\ No newline at end of file
diff --git a/Android/LuaViewSDK/AndroidManifest.xml b/Android/LuaViewSDK/AndroidManifest.xml
new file mode 100644
index 00000000..03e30d44
--- /dev/null
+++ b/Android/LuaViewSDK/AndroidManifest.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewSDK/LuaViewSDK.iml b/Android/LuaViewSDK/LuaViewSDK.iml
new file mode 100644
index 00000000..2b234176
--- /dev/null
+++ b/Android/LuaViewSDK/LuaViewSDK.iml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generateDebugSources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/assets/debug.lua b/Android/LuaViewSDK/assets/debug.lua
new file mode 100644
index 00000000..d64fc771
--- /dev/null
+++ b/Android/LuaViewSDK/assets/debug.lua
@@ -0,0 +1,406 @@
+_DEBUG_FILE = "@debug.lua"
+
+debug.bps = {
+ max = 0,
+ trace = false,
+ last_cmd = "",
+ next = false,
+ cur_func = nil,
+ trace_count = 0,
+ var_tbl = nil,
+}
+
+function debug_log( log_str )
+ print( "[调试器] " .. log_str );
+end
+
+function debug_print_var_0( name, value, level )
+ local ret = "";
+ local prefix = string:rep( " ", level )
+ local str = string:format( "%s%s = %s", prefix, name, tostring(value) )
+
+ if type( value ) == "table" then
+ if debug.var_tbl[value] then
+ --已在临时表中的,只打印表地址
+ -- print( str )
+ ret = ret .. tostring(str) .. '\n';
+ return ret;
+ end
+
+ --加到临时表中,以免表出现循环引用时,打印也产生死循环
+ debug.var_tbl[value] = true
+ --打印表中所有数据
+ --print( string:format( "%s%s = {", prefix, name ) )
+ ret = ret .. string:format( "%s%s = {", prefix, name ) .. '\n';
+ for k, v in pairs( value ) do
+ if type( k ) == "string" then
+ else
+ k = tostring(k);
+ end
+ --不打印 "_"开头的内部变量
+ --if string:sub( k, 1, 1 ) ~= "_" then
+ ret = ret .. debug_print_var_0( k, v, level + 1 )
+ --end
+ end
+ -- print( prefix .. "}" )
+ ret = ret .. prefix .. "}" .. '\n';
+ elseif type( value ) == "string" then
+ -- print( str )
+ ret = ret .. tostring(str) .. '\n';
+ else
+ -- print( str )
+ ret = ret .. tostring(str) .. '\n';
+ end
+ return ret;
+end
+
+function debug_print_var( name, value, level )
+ local s = debug_print_var_0( name, value, level );
+ if( s ) then
+ s = string:sub(s, 1, #s - 1);
+ debug_log( s );
+ else
+ debug_log( s );
+ end
+end
+
+function debug_print_expr( var )
+ if ( var==nil ) then
+ debug_log("debug_print_expr var==nil");
+ return;
+ end
+ --清空临时变量表
+ debug.var_tbl = {}
+
+ local index = 1
+ --找局部变量
+ while true do
+ local name, value = debug:getlocal( 4, index )
+ if not name then
+ break
+ end
+ index = index + 1
+
+ if name == var then
+ debug_print_var( var, value, 0 )
+ return
+ end
+ end
+
+ -- try upvalues
+ local func = debug:getinfo(4,"f").func
+ local index = 1
+ while true do
+ local name, value = debug:getupvalue(func, index)
+ if not name then
+ break
+ end
+ if name == var then
+ debug_print_var( var, value, 0 )
+ return
+ end
+ index = index + 1
+ end
+
+
+ --找全局变量
+ if _G[var] ~= nil then
+ debug_print_var( var, _G[var], 0 )
+ return
+ end
+
+ debug_log( var .. " is invalid" )
+end
+
+
+function debug_run_expr( s )
+ loadJson(s)
+end
+
+function add_breakpoint( expr )
+ local si = string:find( expr, ":" )
+ if nil == si then
+ debug_log( "add breakpoint error, expr (" .. expr .. ") invalid" )
+ return
+ end
+
+ local line = string:sub( expr, si + 1 )
+ local line = tonumber( line )
+ local source = string:sub( expr, 1, si - 1 )
+
+ --先查找有不有相同断点
+ if ( ( debug.bps[line] ~= nil ) and ( debug.bps[line][source] ~= nil ) ) then
+ debug_log( string:format( "breakpoint %s:%d existed", source, line ) )
+ return
+ end
+
+ local tbl = {}
+ tbl.source = source
+ tbl.line = line
+ tbl.active = true
+ tbl.number = debug.bps.max + 1
+
+ if debug.bps[line] == nil then
+ debug.bps[line] = {}
+ end
+
+ debug.bps[line][source] = tbl
+ debug.bps.max = debug.bps.max + 1
+ debug_log( string:format( "加断点(%s:%d)", source, line ) )
+end
+
+function remove_breakpoint( expr )
+ local si = string:find( expr, ":" )
+ if nil == si then
+ debug_log( "remove breakpoint error, expr (" .. expr .. ") invalid" )
+ return
+ end
+
+ local line = string:sub( expr, si + 1 )
+ local line = tonumber( line )
+ local source = string:sub( expr, 1, si - 1 )
+
+ --先查找有不有相同断点
+ if( ( debug.bps[line] ~= nil ) and ( debug.bps[line][source] ~= nil ) )then
+ debug.bps[line][source] = nil;
+ debug_log( string:format( "删点断(%s:%d)", source, line ) )
+ return
+ else
+ debug_log( string:format( "not found breakpoint %s:%d existed", source, line ) )
+ return
+ end
+end
+
+function debug_show_bp()
+ for k, v in pairs( debug.bps ) do
+ if type( v ) == "table" then
+ for k1, v1 in pairs( v ) do
+ local str = string:format( "bp num:%d %s:%d active:",
+ v1.number,
+ v1.source,
+ v1.line )
+ if v1.active then
+ str = str .. "enable"
+ else
+ str = str .. "disable"
+ end
+ debug_log( str )
+ end
+ end
+ end
+end
+
+function debug_del_bp( expr )
+ local number = tonumber( expr )
+ for k, v in pairs( debug.bps ) do
+ if type( v ) == "table" then
+ for k1, v1 in pairs( v ) do
+ if v1.number == number then
+ debug.bps[k][k1] = nil
+ debug_log( "remove bp:" .. number .. " ok" )
+ end
+ end
+ end
+ end
+end
+
+function debug_enable_bp( expr )
+ local number = tonumber( expr )
+ for k, v in pairs( debug.bps ) do
+ if type( v ) == "table" then
+ for k1, v1 in pairs( v ) do
+ if v1.number == number then
+ v1.active = true
+ debug_log( "enable bp:" .. number )
+ end
+ end
+ end
+ end
+end
+
+function debug_disable_bp( expr )
+ local number = tonumber( expr )
+ for k, v in pairs( debug.bps ) do
+ if type( v ) == "table" then
+ for k1, v1 in pairs( v ) do
+ if v1.number == number then
+ v1.active = false
+ debug_log( "disable bp:" .. number )
+ end
+ end
+ end
+ end
+end
+
+function debug_help()
+ print( "h help info" )
+ print( "c continue" )
+ print( "s trace" )
+ print( "n next" )
+ print( "p var print variable" )
+ print( "run expression run expression code" )
+ print( "b src:line add breakpoint" )
+ print( "rb src:line remove breakpoint" )
+ print( "bl list breakpoint" )
+ print( "bt print traceback" )
+end
+
+function debug_runing_execute( cmd )
+ if( cmd==nil ) then
+ return;
+ end
+ local c = cmd
+ local expr = ""
+ local si = string:find( cmd, " " )
+ if si ~= nil then
+ c = string:sub( cmd, 1, si - 1 )
+ expr = string:sub( cmd, string:find( cmd, " %w" ) + 1 )
+ end
+
+ if c == "b" then
+ add_breakpoint( expr )
+ elseif c == "rb" then
+ remove_breakpoint( expr )
+ elseif c == "p" then
+ debug_print_expr( expr )
+ end
+end
+
+function debug_execute_cmd( env )
+ --print( "(ldb) " )
+ local cmd = debug:readCmd()
+ if ( cmd ==nil ) then
+ debug:sleep(0.01);
+ return false;
+ end
+ --取上一次的命令,方便调试
+ -- if cmd ~= "" then
+ -- debug.bps.last_cmd = cmd
+ -- else
+ -- cmd = debug.bps.last_cmd
+ -- end
+
+ local c = cmd
+ local expr = ""
+ local si = string:find( cmd, " " )
+ if si ~= nil then
+ c = string:sub( cmd, 1, si - 1 )
+ -- local index = string:find( cmd, " %w" );
+ -- if ( index ) then
+ -- expr = string:sub( cmd, index + 1 );
+ -- end
+ expr = string:sub(cmd, si + 1 );
+ end
+ if c=="close" then
+ debug_close();
+ return true;
+ elseif c=="none" then
+ return false;
+ elseif c == "c" then
+ debug.bps.trace = false
+ return true
+ elseif c == "s" then
+ debug.bps.trace = true
+ return true
+ elseif c == "n" then
+ debug.bps.trace = false
+ debug.bps.next = true
+ debug.bps.cur_func = env.func
+ debug.bps.trace_count = debug:traceback_count()
+ return true
+ elseif c == "p" then
+ debug_print_expr( expr )
+ elseif c == "run" then
+ debug_run_expr( expr )
+ elseif c == "b" then
+ add_breakpoint( expr )
+ elseif c == "rb" then
+ remove_breakpoint( expr )
+ elseif c == "bl" then
+ debug_show_bp()
+ elseif c == "d" then
+ debug_del_bp( expr )
+ elseif c == "be" then
+ debug_enable_bp( expr )
+ elseif c == "bd" then
+ debug_disable_bp( expr )
+ elseif c == "bt" then
+ print( debug:traceback("", 3) )
+ elseif c == "h" then
+ debug_help()
+ else
+ debug_log( "invalid cmd:" .. cmd )
+ end
+ return false
+end
+
+function debug_trace( event, line )
+
+ local env = debug:getinfo( 2 )
+ if not env then
+ print("getinfo failed ", event, line)
+ return
+ end
+
+ if env.source == _DEBUG_FILE then
+ return
+ end
+
+ --判断是否在next调试
+ if debug.bps.next then
+ local trace_count = debug:traceback_count()
+ --函数返回了,调用栈数量就会比现在小
+ if trace_count < debug.bps.trace_count then
+ debug.bps.next = false
+ debug.bps.trace = true
+ elseif trace_count == debug.bps.trace_count then
+ if debug.bps.cur_func == env.func then
+ debug.bps.next = false
+ debug.bps.trace = true
+ end
+ end
+ end
+
+ --判断是否有断点
+ if( ( not debug.bps.trace ) and ( debug.bps[line] ~= nil ) ) then
+ local tbl = debug.bps[line][env.source]
+ if( ( tbl ~= nil ) and tbl.active )then
+ --如果在next时,碰到断点了,就清除单步运行状态
+ debug.bps.next = false
+ debug.bps.trace = true
+ -- debug_log( "碰到断点 " .. env.source .. " - " .. line )
+ end
+ end
+
+ if debug.bps.trace then
+ local src = debug:get_file_line( env.source, line )
+ local funname = env.name or "unknow"
+ --debug_log( string:format( "%s:%d(%s) %s", env.source, line, funname, src ) )
+ debug:runningLine( env.source, line );
+ debug.bps.cur_file = env.source;
+ debug.bps.cur_line = line
+ while not debug_execute_cmd( env ) do
+ end
+ return;
+ end
+
+ -- local cmd = debug:readCmd()
+ -- debug_runing_execute( cmd );
+end
+
+function begin_debug()
+ debug.bps.trace = true
+ debug:sethook( debug_trace, "l" )
+end
+
+--关闭debugger
+function debug_close()
+ debug.bps.trace = false
+ debug.bps.next = false
+ debug:sethook()
+end
+
+debug:printToServer(true);
+
+
+begin_debug(); -- last line
diff --git a/Android/LuaViewSDK/build.gradle b/Android/LuaViewSDK/build.gradle
new file mode 100644
index 00000000..cd5e2b6b
--- /dev/null
+++ b/Android/LuaViewSDK/build.gradle
@@ -0,0 +1,66 @@
+//打包配置
+apply plugin: 'com.android.library'
+
+description = """LuaView-Android: 用lua写Android、iOS"""
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+ jcenter()
+}
+
+configurations {
+ providedCompile
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:support-v4:23.0.1'
+ //recycler view
+ compile 'com.android.support:recyclerview-v7:23.0.1'
+// compile 'com.android.support:appcompat-v7:23.4.0'
+}
+
+/*
+ 定义android插件
+*/
+android {
+ compileSdkVersion 23
+ buildToolsVersion '25.0.0'
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src', 'src-csslayout']
+ resources.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ }
+
+ // Move the tests to tests/java, tests/res, etc...
+ instrumentTest.setRoot('tests')
+
+ // Move the build types to build-types/
+ // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
+ // This moves them out of them default location under src//... which would
+ // conflict with src/ being used by the main source set.
+ // Adding new build types or product flavors should be accompanied
+ // by a similar customization.
+ debug.setRoot('build-types/debug')
+ release.setRoot('build-types/release')
+ }
+ packagingOptions {
+ exclude 'META-INF/LICENSE.txt'
+ }
+ buildTypes {
+ debug {
+ debuggable true
+ }
+ }
+ lintOptions {
+ abortOnError false
+ }
+}
+
diff --git a/Android/LuaViewSDK/github_sync.sh b/Android/LuaViewSDK/github_sync.sh
new file mode 100644
index 00000000..017c0fc9
--- /dev/null
+++ b/Android/LuaViewSDK/github_sync.sh
@@ -0,0 +1,39 @@
+if [ ! -n "$1" ]; then
+ echo "必须指定需要的同步的分支, sh github_sync.sh branch_name"
+ exit 0;
+fi
+
+GIT_MERGE="git merge $1"
+
+echo "save current branch changes:"
+
+git stash
+
+GIT_CURRENT_BRANCH=$(git symbolic-ref -q HEAD)
+GIT_CURRENT_BRANCH=${GIT_CURRENT_BRANCH##refs/heads/}
+GIT_CURRENT_BRANCH=${GIT_CURRENT_BRANCH:-HEAD}
+
+
+git pull
+git checkout develop
+git pull
+$GIT_MERGE
+
+echo "\npush to develop"
+git push
+echo "\npush to github on branch develop"
+git push https://github.com/alibaba/LuaViewSDK develop:develop
+
+echo "\n"
+git checkout master
+git pull
+git merge develop
+
+echo "\npush to master"
+git push
+echo "\npush to github on branch master"
+git push https://github.com/alibaba/LuaViewSDK master:master
+
+echo "\n"
+git checkout $GIT_CURRENT_BRANCH
+git stash apply
diff --git a/Android/LuaViewSDK/package/keystore/test/debug.keystore b/Android/LuaViewSDK/package/keystore/test/debug.keystore
new file mode 100644
index 00000000..1399bfd5
Binary files /dev/null and b/Android/LuaViewSDK/package/keystore/test/debug.keystore differ
diff --git a/Android/LuaViewSDK/package/keystore/test/debugkeystore readme.txt b/Android/LuaViewSDK/package/keystore/test/debugkeystore readme.txt
new file mode 100644
index 00000000..b138878c
--- /dev/null
+++ b/Android/LuaViewSDK/package/keystore/test/debugkeystore readme.txt
@@ -0,0 +1,2 @@
+alias:androiddebugkey
+pwd:android
\ No newline at end of file
diff --git a/Android/LuaViewSDK/pom.xml b/Android/LuaViewSDK/pom.xml
new file mode 100644
index 00000000..7efd6784
--- /dev/null
+++ b/Android/LuaViewSDK/pom.xml
@@ -0,0 +1,131 @@
+
+ 4.0.0
+
+
+
+ com.taobao.ju.android
+ luaviewsdk
+ 1.0.0-SNAPSHOT
+ ${packaging.type}
+
+ LuaView-Android SDK
+
+
+ LuaView Android SDK, 2015.11.23 add by song
+
+
+
+ true
+ 57
+ aar
+ UTF-8
+
+
+
+ src
+
+
+
+
+ com.taobao.maven.plugins.android
+ android-maven-plugin
+
+
+ 1.3.6.7
+ true
+ true
+
+ ${pakageidsegment}
+ true
+ ${project.basedir}/src
+ ${project.basedir}/AndroidManifest.xml
+ ${project.basedir}/res
+ ${project.basedir}/assets
+
+
+
+
+
+
+
+
+ releases
+ http://mvnrepo.alibaba-inc.com/mvn/releases
+
+
+ snapshots
+ http://mvnrepo.alibaba-inc.com/mvn/snapshots
+
+
+
+
+
+
+
+ com.google.android
+ android
+ r23
+ provided
+
+
+
+
+ com.android.support
+ support-v4
+ 23.0.1
+ aar
+ provided
+
+
+
+
+
+
+
+ com.android.support
+ recyclerview-v7
+ 23.4.0
+ aar
+ provided
+
+
+
+
+
+
+
+
+ awb
+
+ awb
+ provided
+ false
+
+
+
+
+ aar
+
+ true
+
+
+ aar
+ provided
+ false
+
+
+
+
+
diff --git a/Android/LuaViewSDK/proguard-rules.pro b/Android/LuaViewSDK/proguard-rules.pro
new file mode 100644
index 00000000..8b3bf7ef
--- /dev/null
+++ b/Android/LuaViewSDK/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/song/AndroidSDK/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/Android/LuaViewSDK/proguard.cfg b/Android/LuaViewSDK/proguard.cfg
new file mode 100644
index 00000000..e69de29b
diff --git a/Android/LuaViewSDK/res/color/lv_vpi__dark_theme.xml b/Android/LuaViewSDK/res/color/lv_vpi__dark_theme.xml
new file mode 100644
index 00000000..2a1cb137
--- /dev/null
+++ b/Android/LuaViewSDK/res/color/lv_vpi__dark_theme.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewSDK/res/color/lv_vpi__light_theme.xml b/Android/LuaViewSDK/res/color/lv_vpi__light_theme.xml
new file mode 100644
index 00000000..ffe0390d
--- /dev/null
+++ b/Android/LuaViewSDK/res/color/lv_vpi__light_theme.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewSDK/res/drawable-v21/lv_click_foreground.xml b/Android/LuaViewSDK/res/drawable-v21/lv_click_foreground.xml
new file mode 100644
index 00000000..6865917a
--- /dev/null
+++ b/Android/LuaViewSDK/res/drawable-v21/lv_click_foreground.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/drawable/lv_bg_dialog_progress_default.xml b/Android/LuaViewSDK/res/drawable/lv_bg_dialog_progress_default.xml
new file mode 100644
index 00000000..5cd5e755
--- /dev/null
+++ b/Android/LuaViewSDK/res/drawable/lv_bg_dialog_progress_default.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/drawable/lv_click_foreground.xml b/Android/LuaViewSDK/res/drawable/lv_click_foreground.xml
new file mode 100644
index 00000000..21323871
--- /dev/null
+++ b/Android/LuaViewSDK/res/drawable/lv_click_foreground.xml
@@ -0,0 +1,8 @@
+
+
+ -
+
+
+
+
+
diff --git a/Android/LuaViewSDK/res/drawable/lv_vpi__tab_indicator.xml b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_indicator.xml
new file mode 100644
index 00000000..9def9ba8
--- /dev/null
+++ b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_indicator.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_focused_holo.9.png b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_focused_holo.9.png
new file mode 100644
index 00000000..673e3bf1
Binary files /dev/null and b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_focused_holo.9.png differ
diff --git a/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_holo.9.png b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_holo.9.png
new file mode 100644
index 00000000..d57df98b
Binary files /dev/null and b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_holo.9.png differ
diff --git a/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_pressed_holo.9.png b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_pressed_holo.9.png
new file mode 100644
index 00000000..6278eef4
Binary files /dev/null and b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_selected_pressed_holo.9.png differ
diff --git a/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_focused_holo.9.png b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_focused_holo.9.png
new file mode 100644
index 00000000..294991d7
Binary files /dev/null and b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_focused_holo.9.png differ
diff --git a/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_holo.9.png b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_holo.9.png
new file mode 100644
index 00000000..19532ab1
Binary files /dev/null and b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_holo.9.png differ
diff --git a/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_pressed_holo.9.png b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_pressed_holo.9.png
new file mode 100644
index 00000000..aadc6f87
Binary files /dev/null and b/Android/LuaViewSDK/res/drawable/lv_vpi__tab_unselected_pressed_holo.9.png differ
diff --git a/Android/LuaViewSDK/res/layout/lv_dialog_progress_default.xml b/Android/LuaViewSDK/res/layout/lv_dialog_progress_default.xml
new file mode 100644
index 00000000..2736c0ff
--- /dev/null
+++ b/Android/LuaViewSDK/res/layout/lv_dialog_progress_default.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/layout/lv_recyclerview_vertical.xml b/Android/LuaViewSDK/res/layout/lv_recyclerview_vertical.xml
new file mode 100644
index 00000000..18562e74
--- /dev/null
+++ b/Android/LuaViewSDK/res/layout/lv_recyclerview_vertical.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/values/attrs_auto_fit_text.xml b/Android/LuaViewSDK/res/values/attrs_auto_fit_text.xml
new file mode 100644
index 00000000..f36dd180
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/attrs_auto_fit_text.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/values/colors.xml b/Android/LuaViewSDK/res/values/colors.xml
new file mode 100644
index 00000000..54c6a849
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+
+ #99000000
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/values/dimens.xml b/Android/LuaViewSDK/res/values/dimens.xml
new file mode 100644
index 00000000..be1dc8ba
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 5dp
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/values/ids.xml b/Android/LuaViewSDK/res/values/ids.xml
new file mode 100644
index 00000000..5260221c
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/ids.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/values/lv_vpi__attrs.xml b/Android/LuaViewSDK/res/values/lv_vpi__attrs.xml
new file mode 100644
index 00000000..464221ef
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/lv_vpi__attrs.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewSDK/res/values/lv_vpi__colors.xml b/Android/LuaViewSDK/res/values/lv_vpi__colors.xml
new file mode 100644
index 00000000..0b006c25
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/lv_vpi__colors.xml
@@ -0,0 +1,26 @@
+
+
+
+
+ #ff000000
+ #fff3f3f3
+ @color/lv_vpi__background_holo_light
+ @color/lv_vpi__background_holo_dark
+ #ff4c4c4c
+ #ffb2b2b2
+ @color/lv_vpi__bright_foreground_holo_light
+ @color/lv_vpi__bright_foreground_holo_dark
+
diff --git a/Android/LuaViewSDK/res/values/lv_vpi__defaults.xml b/Android/LuaViewSDK/res/values/lv_vpi__defaults.xml
new file mode 100644
index 00000000..d07c44a9
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/lv_vpi__defaults.xml
@@ -0,0 +1,53 @@
+
+
+
+
+ true
+ #FFFFFFFF
+ #00000000
+ 0
+ 3dp
+ false
+ #FFDDDDDD
+ 1dp
+
+ 12dp
+ 4dp
+ 1dp
+ #FF33B5E5
+ #FFBBBBBB
+ true
+
+ 4dp
+ #FF33B5E5
+ 2dp
+ 2
+ 4dp
+ 20dp
+ 7dp
+ 0
+ #FFFFFFFF
+ true
+ #BBFFFFFF
+ 15dp
+ 5dp
+ 7dp
+
+ true
+ 300
+ 400
+ #FF33B5E5
+
\ No newline at end of file
diff --git a/Android/LuaViewSDK/res/values/lv_vpi__styles.xml b/Android/LuaViewSDK/res/values/lv_vpi__styles.xml
new file mode 100644
index 00000000..f2fcbf56
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/lv_vpi__styles.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewSDK/res/values/strings.xml b/Android/LuaViewSDK/res/values/strings.xml
new file mode 100644
index 00000000..07157276
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+
+
+ LuaView
+
+
+
diff --git a/Android/LuaViewSDK/res/values/styles.xml b/Android/LuaViewSDK/res/values/styles.xml
new file mode 100644
index 00000000..0309de5a
--- /dev/null
+++ b/Android/LuaViewSDK/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSAlign.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSAlign.java
new file mode 100644
index 00000000..f177270f
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSAlign.java
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public enum CSSAlign {
+ AUTO,
+ FLEX_START,
+ CENTER,
+ FLEX_END,
+ STRETCH,
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSConstants.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSConstants.java
new file mode 100644
index 00000000..ec0b3f7c
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSConstants.java
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public class CSSConstants {
+
+ public static final float UNDEFINED = Float.NaN;
+
+ public static boolean isUndefined(float value) {
+ return Float.compare(value, UNDEFINED) == 0;
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSDirection.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSDirection.java
new file mode 100644
index 00000000..26e93bd6
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSDirection.java
@@ -0,0 +1,15 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public enum CSSDirection {
+ INHERIT,
+ LTR,
+ RTL,
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSFlexDirection.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSFlexDirection.java
new file mode 100644
index 00000000..b5040e25
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSFlexDirection.java
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public enum CSSFlexDirection {
+ COLUMN,
+ COLUMN_REVERSE,
+ ROW,
+ ROW_REVERSE
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSJustify.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSJustify.java
new file mode 100644
index 00000000..371b38cb
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSJustify.java
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public enum CSSJustify {
+ FLEX_START,
+ CENTER,
+ FLEX_END,
+ SPACE_BETWEEN,
+ SPACE_AROUND,
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSLayout.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSLayout.java
new file mode 100644
index 00000000..26ec4d56
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSLayout.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+import java.util.Arrays;
+
+/**
+ * Where the output of {@link LayoutEngine#layoutNode(CSSNode, float)} will go in the CSSNode.
+ */
+public class CSSLayout {
+ public static final int POSITION_LEFT = 0;
+ public static final int POSITION_TOP = 1;
+ public static final int POSITION_RIGHT = 2;
+ public static final int POSITION_BOTTOM = 3;
+
+ public static final int DIMENSION_WIDTH = 0;
+ public static final int DIMENSION_HEIGHT = 1;
+
+ public float[] position = new float[4];
+ public float[] dimensions = new float[2];
+ public CSSDirection direction = CSSDirection.LTR;
+
+ /**
+ * This should always get called before calling {@link LayoutEngine#layoutNode(CSSNode, float)}
+ */
+ public void resetResult() {
+ Arrays.fill(position, 0);
+ Arrays.fill(dimensions, CSSConstants.UNDEFINED);
+ direction = CSSDirection.LTR;
+ }
+
+ public void copy(CSSLayout layout) {
+ position[POSITION_LEFT] = layout.position[POSITION_LEFT];
+ position[POSITION_TOP] = layout.position[POSITION_TOP];
+ position[POSITION_RIGHT] = layout.position[POSITION_RIGHT];
+ position[POSITION_BOTTOM] = layout.position[POSITION_BOTTOM];
+ dimensions[DIMENSION_WIDTH] = layout.dimensions[DIMENSION_WIDTH];
+ dimensions[DIMENSION_HEIGHT] = layout.dimensions[DIMENSION_HEIGHT];
+ direction = layout.direction;
+ }
+
+ @Override
+ public String toString() {
+ return "layout: {" +
+ "left: " + position[POSITION_LEFT] + ", " +
+ "top: " + position[POSITION_TOP] + ", " +
+ "width: " + dimensions[DIMENSION_WIDTH] + ", " +
+ "height: " + dimensions[DIMENSION_HEIGHT] + ", " +
+ "direction: " + direction +
+ "}";
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSLayoutContext.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSLayoutContext.java
new file mode 100644
index 00000000..8c93e0eb
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSLayoutContext.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+/**
+ * A context for holding values local to a given instance of layout computation.
+ *
+ * This is necessary for making layout thread-safe. A separate instance should
+ * be used when {@link CSSNode#calculateLayout} is called concurrently on
+ * different node hierarchies.
+ */
+public class CSSLayoutContext {
+ /*package*/ final MeasureOutput measureOutput = new MeasureOutput();
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSNode.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSNode.java
new file mode 100644
index 00000000..95d4f67d
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSNode.java
@@ -0,0 +1,601 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+import com.taobao.luaview.annotations.Nullable;
+import com.taobao.luaview.util.Assertions;
+
+import java.util.ArrayList;
+
+import static com.facebook.csslayout.CSSLayout.DIMENSION_HEIGHT;
+import static com.facebook.csslayout.CSSLayout.DIMENSION_WIDTH;
+import static com.facebook.csslayout.CSSLayout.POSITION_BOTTOM;
+import static com.facebook.csslayout.CSSLayout.POSITION_LEFT;
+import static com.facebook.csslayout.CSSLayout.POSITION_RIGHT;
+import static com.facebook.csslayout.CSSLayout.POSITION_TOP;
+
+/**
+ * A CSS Node. It has a style object you can manipulate at {@link #style}. After calling
+ * {@link #calculateLayout()}, {@link #layout} will be filled with the results of the layout.
+ */
+public class CSSNode {
+
+ private static enum LayoutState {
+ /**
+ * Some property of this node or its children has changes and the current values in
+ * {@link #layout} are not valid.
+ */
+ DIRTY,
+
+ /**
+ * This node has a new layout relative to the last time {@link #markLayoutSeen()} was called.
+ */
+ HAS_NEW_LAYOUT,
+
+ /**
+ * {@link #layout} is valid for the node's properties and this layout has been marked as
+ * having been seen.
+ */
+ UP_TO_DATE,
+ }
+
+ public static interface MeasureFunction {
+
+ /**
+ * Should measure the given node and put the result in the given MeasureOutput.
+ *
+ * NB: measure is NOT guaranteed to be threadsafe/re-entrant safe!
+ */
+ public void measure(CSSNode node, float width, float height, MeasureOutput measureOutput);
+ }
+
+ // VisibleForTesting
+ /*package*/ final CSSStyle style = new CSSStyle();
+ /*package*/ final CSSLayout layout = new CSSLayout();
+ /*package*/ final CachedCSSLayout lastLayout = new CachedCSSLayout();
+
+ public int lineIndex = 0;
+
+ /*package*/ CSSNode nextAbsoluteChild;
+ /*package*/ CSSNode nextFlexChild;
+
+ protected
+ @Nullable
+ ArrayList mChildren;
+ private
+ @Nullable
+ CSSNode mParent;
+ private
+ @Nullable
+ MeasureFunction mMeasureFunction = null;
+ private boolean mSizeToFit;
+ private LayoutState mLayoutState = LayoutState.DIRTY;
+
+ public int getChildCount() {
+ return mChildren == null ? 0 : mChildren.size();
+ }
+
+ public CSSLayout getLayout() {
+ return layout;
+ }
+
+ public void resetChildren() {
+ mChildren.clear();
+ }
+
+ public boolean getSizeToFit() {
+ return mSizeToFit;
+ }
+
+ public void setSizeToFit(boolean sizeToFit) {
+ mSizeToFit = sizeToFit;
+ }
+
+ public CSSNode getChildAt(int i) {
+ Assertions.assertNotNull(mChildren);
+ return mChildren.get(i);
+ }
+
+ public void addChildAt(CSSNode child, int i) {
+ if (child.mParent != null) {
+ throw new IllegalStateException("Child already has a parent, it must be removed first.");
+ }
+ if (mChildren == null) {
+ // 4 is kinda arbitrary, but the default of 10 seems really high for an average View.
+ mChildren = new ArrayList(4);
+ }
+
+ mChildren.add(i, child);
+ child.mParent = this;
+ dirty();
+ }
+
+ public void setAlignContent(CSSAlign alignContent) {
+ if (style.alignContent != alignContent) {
+ style.alignContent = alignContent;
+ dirty();
+ }
+ }
+
+ public CSSAlign getAlignContent() {
+ return style.alignContent;
+ }
+
+ public float getStyleMinWidth() {
+ return style.minWidth;
+ }
+
+ public void setStyleMinWidth(float width) {
+ if (!valuesEqual(style.minWidth, width)) {
+ style.minWidth = width;
+ dirty();
+ }
+ }
+
+ public float getStyleMinHeight() {
+ return style.minHeight;
+ }
+
+ public void setStyleMinHeight(float height) {
+ if (!valuesEqual(style.minHeight, height)) {
+ style.minHeight = height;
+ dirty();
+ }
+ }
+
+ public float getStyleMaxWidth() {
+ return style.maxWidth;
+ }
+
+ public void setStyleMaxWidth(float width) {
+ if (!valuesEqual(style.maxWidth, width)) {
+ style.maxWidth = width;
+ dirty();
+ }
+ }
+
+ public float getStyleMaxHeight() {
+ return style.maxHeight;
+ }
+
+ public void setStyleMaxHeight(float height) {
+ if (!valuesEqual(style.maxHeight, height)) {
+ style.maxHeight = height;
+ dirty();
+ }
+ }
+
+
+ public void addChild(CSSNode child) {
+ if (child.mParent != null) {
+ throw new IllegalStateException("Child already has a parent, it must be removed first.");
+ }
+ if (mChildren == null) {
+ // 4 is kinda arbitrary, but the default of 10 seems really high for an average View.
+ mChildren = new ArrayList(4);
+ }
+
+ mChildren.add(child);
+ child.mParent = this;
+ dirty();
+ }
+
+ public CSSNode removeChildAt(int i) {
+ Assertions.assertNotNull(mChildren);
+ CSSNode removed = mChildren.remove(i);
+ removed.mParent = null;
+ dirty();
+ return removed;
+ }
+
+ public
+ @Nullable
+ CSSNode getParent() {
+ return mParent;
+ }
+
+ /**
+ * @return the index of the given child, or -1 if the child doesn't exist in this node.
+ */
+ public int indexOf(CSSNode child) {
+ Assertions.assertNotNull(mChildren);
+ return mChildren.indexOf(child);
+ }
+
+ public void setMeasureFunction(MeasureFunction measureFunction) {
+ if (mMeasureFunction != measureFunction) {
+ mMeasureFunction = measureFunction;
+ dirty();
+ }
+ }
+
+ public boolean isMeasureDefined() {
+ return mMeasureFunction != null;
+ }
+
+ /*package*/ MeasureOutput measure(MeasureOutput measureOutput, float width, float height) {
+ if (!isMeasureDefined()) {
+ throw new RuntimeException("Measure function isn't defined!");
+ }
+ measureOutput.height = CSSConstants.UNDEFINED;
+ measureOutput.width = CSSConstants.UNDEFINED;
+ Assertions.assertNotNull(mMeasureFunction).measure(this, width, height, measureOutput);
+ return measureOutput;
+ }
+
+ /**
+ * Performs the actual layout and saves the results in {@link #layout}
+ */
+ public void calculateLayout(CSSLayoutContext layoutContext) {
+ layout.resetResult();
+ LayoutEngine.layoutNode(layoutContext, this, CSSConstants.UNDEFINED, CSSConstants.UNDEFINED, null);
+ }
+
+ /**
+ * See {@link LayoutState#DIRTY}.
+ */
+ protected boolean isDirty() {
+ return mLayoutState == LayoutState.DIRTY;
+ }
+
+ /**
+ * See {@link LayoutState#HAS_NEW_LAYOUT}.
+ */
+ public boolean hasNewLayout() {
+ return mLayoutState == LayoutState.HAS_NEW_LAYOUT;
+ }
+
+ protected void dirty() {
+ if (mLayoutState == LayoutState.DIRTY) {
+ return;
+ } else if (mLayoutState == LayoutState.HAS_NEW_LAYOUT) {
+ throw new IllegalStateException("Previous layout was ignored! markLayoutSeen() never called");
+ }
+
+ mLayoutState = LayoutState.DIRTY;
+
+ if (mParent != null) {
+ mParent.dirty();
+ }
+ }
+
+ /*package*/ void markHasNewLayout() {
+ mLayoutState = LayoutState.HAS_NEW_LAYOUT;
+ }
+
+ /**
+ * Tells the node that the current values in {@link #layout} have been seen. Subsequent calls
+ * to {@link #hasNewLayout()} will return false until this node is laid out with new parameters.
+ * You must call this each time the layout is generated if the node has a new layout.
+ */
+ public void markLayoutSeen() {
+ if (!hasNewLayout()) {
+ throw new IllegalStateException("Expected node to have a new layout to be seen!");
+ }
+
+ mLayoutState = LayoutState.UP_TO_DATE;
+ }
+
+ private void toStringWithIndentation(StringBuilder result, int level) {
+ // Spaces and tabs are dropped by IntelliJ logcat integration, so rely on __ instead.
+ StringBuilder indentation = new StringBuilder();
+ for (int i = 0; i < level; ++i) {
+ indentation.append("__");
+ }
+
+ result.append(indentation.toString());
+ result.append(layout.toString());
+
+ if (getChildCount() == 0) {
+ return;
+ }
+
+ result.append(", children: [\n");
+ for (int i = 0; i < getChildCount(); i++) {
+ getChildAt(i).toStringWithIndentation(result, level + 1);
+ result.append("\n");
+ }
+ result.append(indentation + "]");
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ this.toStringWithIndentation(sb, 0);
+ return sb.toString();
+ }
+
+ protected boolean valuesEqual(float f1, float f2) {
+ return FloatUtil.floatsEqual(f1, f2);
+ }
+
+ /**
+ * Get this node's direction, as defined in the style.
+ */
+ public CSSDirection getStyleDirection() {
+ return style.direction;
+ }
+
+ public void setDirection(CSSDirection direction) {
+ if (style.direction != direction) {
+ style.direction = direction;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's flex direction, as defined by style.
+ */
+ public CSSFlexDirection getFlexDirection() {
+ return style.flexDirection;
+ }
+
+ public void setFlexDirection(CSSFlexDirection flexDirection) {
+ if (style.flexDirection != flexDirection) {
+ style.flexDirection = flexDirection;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's justify content, as defined by style.
+ */
+ public CSSJustify getJustifyContent() {
+ return style.justifyContent;
+ }
+
+ public void setJustifyContent(CSSJustify justifyContent) {
+ if (style.justifyContent != justifyContent) {
+ style.justifyContent = justifyContent;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's align items, as defined by style.
+ */
+ public CSSAlign getAlignItems() {
+ return style.alignItems;
+ }
+
+ public void setAlignItems(CSSAlign alignItems) {
+ if (style.alignItems != alignItems) {
+ style.alignItems = alignItems;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's align items, as defined by style.
+ */
+ public CSSAlign getAlignSelf() {
+ return style.alignSelf;
+ }
+
+ public void setAlignSelf(CSSAlign alignSelf) {
+ if (style.alignSelf != alignSelf) {
+ style.alignSelf = alignSelf;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's position type, as defined by style.
+ */
+ public CSSPositionType getPositionType() {
+ return style.positionType;
+ }
+
+ public void setPositionType(CSSPositionType positionType) {
+ if (style.positionType != positionType) {
+ style.positionType = positionType;
+ dirty();
+ }
+ }
+
+ public void setWrap(CSSWrap flexWrap) {
+ if (style.flexWrap != flexWrap) {
+ style.flexWrap = flexWrap;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's flex, as defined by style.
+ */
+ public float getFlex() {
+ return style.flex;
+ }
+
+ public void setFlex(float flex) {
+ if (!valuesEqual(style.flex, flex)) {
+ style.flex = flex;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's margin, as defined by style + default margin.
+ */
+ public Spacing getMargin() {
+ return style.margin;
+ }
+
+ public void setMargin(int spacingType, float margin) {
+ if (style.margin.set(spacingType, margin)) {
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's padding, as defined by style + default padding.
+ */
+ public Spacing getPadding() {
+ return style.padding;
+ }
+
+ public void setPadding(int spacingType, float padding) {
+ if (style.padding.set(spacingType, padding)) {
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's border, as defined by style.
+ */
+ public Spacing getBorder() {
+ return style.border;
+ }
+
+ public void setBorder(int spacingType, float border) {
+ if (style.border.set(spacingType, border)) {
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's position top, as defined by style.
+ */
+ public float getPositionTop() {
+ return style.position[POSITION_TOP];
+ }
+
+ public void setPositionTop(float positionTop) {
+ if (!valuesEqual(style.position[POSITION_TOP], positionTop)) {
+ style.position[POSITION_TOP] = positionTop;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's position bottom, as defined by style.
+ */
+ public float getPositionBottom() {
+ return style.position[POSITION_BOTTOM];
+ }
+
+ public void setPositionBottom(float positionBottom) {
+ if (!valuesEqual(style.position[POSITION_BOTTOM], positionBottom)) {
+ style.position[POSITION_BOTTOM] = positionBottom;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's position left, as defined by style.
+ */
+ public float getPositionLeft() {
+ return style.position[POSITION_LEFT];
+ }
+
+ public void setPositionLeft(float positionLeft) {
+ if (!valuesEqual(style.position[POSITION_LEFT], positionLeft)) {
+ style.position[POSITION_LEFT] = positionLeft;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's position right, as defined by style.
+ */
+ public float getPositionRight() {
+ return style.position[POSITION_RIGHT];
+ }
+
+ public void setPositionRight(float positionRight) {
+ if (!valuesEqual(style.position[POSITION_RIGHT], positionRight)) {
+ style.position[POSITION_RIGHT] = positionRight;
+ dirty();
+ }
+ }
+
+ /**
+ * Get this node's width, as defined in the style.
+ */
+ public float getStyleWidth() {
+ return style.dimensions[DIMENSION_WIDTH];
+ }
+
+ public void setStyleWidth(float width) {
+ if (!valuesEqual(style.dimensions[DIMENSION_WIDTH], width)) {
+ style.dimensions[DIMENSION_WIDTH] = width;
+ dirty();
+ }
+ }
+
+ public void setNoDirtyStyleWidth(float width) {
+ if (!valuesEqual(style.dimensions[DIMENSION_WIDTH], width)) {
+ style.dimensions[DIMENSION_WIDTH] = width;
+ }
+ }
+
+ public void setNoDirtyStyleHeight(float height) {
+ if (!valuesEqual(style.dimensions[DIMENSION_HEIGHT], height)) {
+ style.dimensions[DIMENSION_HEIGHT] = height;
+ }
+ }
+
+ /**
+ * Get this node's height, as defined in the style.
+ */
+ public float getStyleHeight() {
+ return style.dimensions[DIMENSION_HEIGHT];
+ }
+
+ public void setStyleHeight(float height) {
+ if (!valuesEqual(style.dimensions[DIMENSION_HEIGHT], height)) {
+ style.dimensions[DIMENSION_HEIGHT] = height;
+ dirty();
+ }
+ }
+
+ public float getLayoutX() {
+ return layout.position[POSITION_LEFT];
+ }
+
+ public float getLayoutY() {
+ return layout.position[POSITION_TOP];
+ }
+
+ public float getLayoutWidth() {
+ return layout.dimensions[DIMENSION_WIDTH];
+ }
+
+ public float getLayoutHeight() {
+ return layout.dimensions[DIMENSION_HEIGHT];
+ }
+
+ public CSSDirection getLayoutDirection() {
+ return layout.direction;
+ }
+
+ /**
+ * Set a default padding (left/top/right/bottom) for this node.
+ */
+ public void setDefaultPadding(int spacingType, float padding) {
+ if (style.padding.setDefault(spacingType, padding)) {
+ dirty();
+ }
+ }
+
+ /**
+ * Resets this instance to its default state. This method is meant to be used when
+ * recycling {@link CSSNode} instances.
+ */
+ public void reset() {
+ if (mParent != null || (mChildren != null && mChildren.size() > 0)) {
+ throw new IllegalStateException("You should not reset an attached CSSNode");
+ }
+
+ style.reset();
+ layout.resetResult();
+ lineIndex = 0;
+ mLayoutState = LayoutState.DIRTY;
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSPositionType.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSPositionType.java
new file mode 100644
index 00000000..6dca2dc3
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSPositionType.java
@@ -0,0 +1,14 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public enum CSSPositionType {
+ RELATIVE,
+ ABSOLUTE,
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSStyle.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSStyle.java
new file mode 100644
index 00000000..f4d325dc
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSStyle.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+import java.util.Arrays;
+
+/**
+ * The CSS style definition for a {@link CSSNode}.
+ */
+public class CSSStyle {
+
+ public CSSDirection direction;
+ public CSSFlexDirection flexDirection;
+ public CSSJustify justifyContent;
+ public CSSAlign alignContent;
+ public CSSAlign alignItems;
+ public CSSAlign alignSelf;
+ public CSSPositionType positionType;
+ public CSSWrap flexWrap;
+ public float flex;
+
+ public Spacing margin = new Spacing();
+ public Spacing padding = new Spacing();
+ public Spacing border = new Spacing();
+
+ public float[] position = new float[4];
+ public float[] dimensions = new float[2];
+
+ public float minWidth = CSSConstants.UNDEFINED;
+ public float minHeight = CSSConstants.UNDEFINED;
+
+ public float maxWidth = CSSConstants.UNDEFINED;
+ public float maxHeight = CSSConstants.UNDEFINED;
+
+ CSSStyle() {
+ reset();
+ }
+
+ void reset() {
+ direction = CSSDirection.INHERIT;
+ flexDirection = CSSFlexDirection.COLUMN;
+ justifyContent = CSSJustify.FLEX_START;
+ alignContent = CSSAlign.FLEX_START;
+ alignItems = CSSAlign.STRETCH;
+ alignSelf = CSSAlign.AUTO;
+ positionType = CSSPositionType.RELATIVE;
+ flexWrap = CSSWrap.NOWRAP;
+ flex = 0f;
+
+ margin.reset();;
+ padding.reset();
+ border.reset();
+
+ Arrays.fill(position, CSSConstants.UNDEFINED);
+ Arrays.fill(dimensions, CSSConstants.UNDEFINED);
+
+ minWidth = CSSConstants.UNDEFINED;
+ minHeight = CSSConstants.UNDEFINED;
+
+ maxWidth = CSSConstants.UNDEFINED;
+ maxHeight = CSSConstants.UNDEFINED;
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CSSWrap.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSWrap.java
new file mode 100644
index 00000000..581481a4
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CSSWrap.java
@@ -0,0 +1,14 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public enum CSSWrap {
+ NOWRAP,
+ WRAP,
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/CachedCSSLayout.java b/Android/LuaViewSDK/src/com/facebook/csslayout/CachedCSSLayout.java
new file mode 100644
index 00000000..e5393ef6
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/CachedCSSLayout.java
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+/**
+ * CSSLayout with additional information about the conditions under which it was generated.
+ * {@link #requestedWidth} and {@link #requestedHeight} are the width and height the parent set on
+ * this node before calling layout visited us.
+ */
+public class CachedCSSLayout extends CSSLayout {
+
+ public float requestedWidth = CSSConstants.UNDEFINED;
+ public float requestedHeight = CSSConstants.UNDEFINED;
+ public float parentMaxWidth = CSSConstants.UNDEFINED;
+ public float parentMaxHeight = CSSConstants.UNDEFINED;
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/FloatUtil.java b/Android/LuaViewSDK/src/com/facebook/csslayout/FloatUtil.java
new file mode 100644
index 00000000..37dd007b
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/FloatUtil.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+public class FloatUtil {
+
+ private static final float EPSILON = .00001f;
+
+ public static boolean floatsEqual(float f1, float f2) {
+ if (Float.isNaN(f1) || Float.isNaN(f2)) {
+ return Float.isNaN(f1) && Float.isNaN(f2);
+ }
+ return Math.abs(f2 - f1) < EPSILON;
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/LayoutEngine.java b/Android/LuaViewSDK/src/com/facebook/csslayout/LayoutEngine.java
new file mode 100644
index 00000000..f4743291
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/LayoutEngine.java
@@ -0,0 +1,948 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+import static com.facebook.csslayout.CSSLayout.DIMENSION_HEIGHT;
+import static com.facebook.csslayout.CSSLayout.DIMENSION_WIDTH;
+import static com.facebook.csslayout.CSSLayout.POSITION_BOTTOM;
+import static com.facebook.csslayout.CSSLayout.POSITION_LEFT;
+import static com.facebook.csslayout.CSSLayout.POSITION_RIGHT;
+import static com.facebook.csslayout.CSSLayout.POSITION_TOP;
+
+/**
+ * Calculates layouts based on CSS style. See {@link #layoutNode(CSSNode, float, float)}.
+ */
+public class LayoutEngine {
+
+ private static final int CSS_FLEX_DIRECTION_COLUMN =
+ CSSFlexDirection.COLUMN.ordinal();
+ private static final int CSS_FLEX_DIRECTION_COLUMN_REVERSE =
+ CSSFlexDirection.COLUMN_REVERSE.ordinal();
+ private static final int CSS_FLEX_DIRECTION_ROW =
+ CSSFlexDirection.ROW.ordinal();
+ private static final int CSS_FLEX_DIRECTION_ROW_REVERSE =
+ CSSFlexDirection.ROW_REVERSE.ordinal();
+
+ private static final int CSS_POSITION_RELATIVE = CSSPositionType.RELATIVE.ordinal();
+ private static final int CSS_POSITION_ABSOLUTE = CSSPositionType.ABSOLUTE.ordinal();
+
+ private static final int[] leading = {
+ POSITION_TOP,
+ POSITION_BOTTOM,
+ POSITION_LEFT,
+ POSITION_RIGHT,
+ };
+
+ private static final int[] trailing = {
+ POSITION_BOTTOM,
+ POSITION_TOP,
+ POSITION_RIGHT,
+ POSITION_LEFT,
+ };
+
+ private static final int[] pos = {
+ POSITION_TOP,
+ POSITION_BOTTOM,
+ POSITION_LEFT,
+ POSITION_RIGHT,
+ };
+
+ private static final int[] dim = {
+ DIMENSION_HEIGHT,
+ DIMENSION_HEIGHT,
+ DIMENSION_WIDTH,
+ DIMENSION_WIDTH,
+ };
+
+ private static final int[] leadingSpacing = {
+ Spacing.TOP,
+ Spacing.BOTTOM,
+ Spacing.START,
+ Spacing.START
+ };
+
+ private static final int[] trailingSpacing = {
+ Spacing.BOTTOM,
+ Spacing.TOP,
+ Spacing.END,
+ Spacing.END
+ };
+
+ private static float boundAxis(CSSNode node, int axis, float value) {
+ float min = CSSConstants.UNDEFINED;
+ float max = CSSConstants.UNDEFINED;
+
+ if (axis == CSS_FLEX_DIRECTION_COLUMN ||
+ axis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
+ min = node.style.minHeight;
+ max = node.style.maxHeight;
+ } else if (axis == CSS_FLEX_DIRECTION_ROW ||
+ axis == CSS_FLEX_DIRECTION_ROW_REVERSE) {
+ min = node.style.minWidth;
+ max = node.style.maxWidth;
+ }
+
+ float boundValue = value;
+
+ if (!Float.isNaN(max) && max >= 0.0 && boundValue > max) {
+ boundValue = max;
+ }
+ if (!Float.isNaN(min) && min >= 0.0 && boundValue < min) {
+ boundValue = min;
+ }
+
+ return boundValue;
+ }
+
+ private static void setDimensionFromStyle(CSSNode node, int axis) {
+ // The parent already computed us a width or height. We just skip it
+ if (!Float.isNaN(node.layout.dimensions[dim[axis]])) {
+ return;
+ }
+ // We only run if there's a width or height defined
+ if (Float.isNaN(node.style.dimensions[dim[axis]]) ||
+ node.style.dimensions[dim[axis]] <= 0.0) {
+ return;
+ }
+
+ // The dimensions can never be smaller than the padding and border
+ float maxLayoutDimension = Math.max(
+ boundAxis(node, axis, node.style.dimensions[dim[axis]]),
+ node.style.padding.getWithFallback(leadingSpacing[axis], leading[axis]) +
+ node.style.padding.getWithFallback(trailingSpacing[axis], trailing[axis]) +
+ node.style.border.getWithFallback(leadingSpacing[axis], leading[axis]) +
+ node.style.border.getWithFallback(trailingSpacing[axis], trailing[axis]));
+ node.layout.dimensions[dim[axis]] = maxLayoutDimension;
+ }
+
+ private static float getRelativePosition(CSSNode node, int axis) {
+ float lead = node.style.position[leading[axis]];
+ if (!Float.isNaN(lead)) {
+ return lead;
+ }
+
+ float trailingPos = node.style.position[trailing[axis]];
+ return Float.isNaN(trailingPos) ? 0 : -trailingPos;
+ }
+
+ private static int resolveAxis(
+ int axis,
+ CSSDirection direction) {
+ if (direction == CSSDirection.RTL) {
+ if (axis == CSS_FLEX_DIRECTION_ROW) {
+ return CSS_FLEX_DIRECTION_ROW_REVERSE;
+ } else if (axis == CSS_FLEX_DIRECTION_ROW_REVERSE) {
+ return CSS_FLEX_DIRECTION_ROW;
+ }
+ }
+
+ return axis;
+ }
+
+ private static CSSDirection resolveDirection(CSSNode node, CSSDirection parentDirection) {
+ CSSDirection direction = node.style.direction;
+ if (direction == CSSDirection.INHERIT) {
+ direction = (parentDirection == null ? CSSDirection.LTR : parentDirection);
+ }
+
+ return direction;
+ }
+
+ private static int getFlexDirection(CSSNode node) {
+ return node.style.flexDirection.ordinal();
+ }
+
+ private static int getCrossFlexDirection(
+ int axis,
+ CSSDirection direction) {
+ if (axis == CSS_FLEX_DIRECTION_COLUMN ||
+ axis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
+ return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
+ } else {
+ return CSS_FLEX_DIRECTION_COLUMN;
+ }
+ }
+
+ private static CSSAlign getAlignItem(CSSNode node, CSSNode child) {
+ if (child.style.alignSelf != CSSAlign.AUTO) {
+ return child.style.alignSelf;
+ }
+ return node.style.alignItems;
+ }
+
+ private static boolean isMeasureDefined(CSSNode node) {
+ return node.isMeasureDefined();
+ }
+
+ static boolean needsRelayout(CSSNode node, float parentMaxWidth, float parentMaxHeight) {
+ return node.isDirty() ||
+ !FloatUtil.floatsEqual(
+ node.lastLayout.requestedHeight,
+ node.layout.dimensions[DIMENSION_HEIGHT]) ||
+ !FloatUtil.floatsEqual(
+ node.lastLayout.requestedWidth,
+ node.layout.dimensions[DIMENSION_WIDTH]) ||
+ !FloatUtil.floatsEqual(node.lastLayout.parentMaxWidth, parentMaxWidth) ||
+ !FloatUtil.floatsEqual(node.lastLayout.parentMaxHeight, parentMaxHeight);
+ }
+
+ /*package*/ static void layoutNode(
+ CSSLayoutContext layoutContext,
+ CSSNode node,
+ float parentMaxWidth,
+ float parentMaxHeight,
+ CSSDirection parentDirection) {
+ if (needsRelayout(node, parentMaxWidth, parentMaxHeight)) {
+ node.lastLayout.requestedWidth = node.layout.dimensions[DIMENSION_WIDTH];
+ node.lastLayout.requestedHeight = node.layout.dimensions[DIMENSION_HEIGHT];
+ node.lastLayout.parentMaxWidth = parentMaxWidth;
+ node.lastLayout.parentMaxHeight = parentMaxHeight;
+
+ layoutNodeImpl(layoutContext, node, parentMaxWidth, parentMaxHeight, parentDirection);
+ node.lastLayout.copy(node.layout);
+ } else {
+ node.layout.copy(node.lastLayout);
+ }
+
+ node.markHasNewLayout();
+ }
+
+ private static void layoutNodeImpl(
+ CSSLayoutContext layoutContext,
+ CSSNode node,
+ float parentMaxWidth,
+ float parentMaxHeight,
+ CSSDirection parentDirection) {
+ for (int i = 0, childCount = node.getChildCount(); i < childCount; i++) {
+ node.getChildAt(i).layout.resetResult();
+ }
+
+ /** START_GENERATED **/
+
+ CSSDirection direction = resolveDirection(node, parentDirection);
+ int mainAxis = resolveAxis(getFlexDirection(node), direction);
+ int crossAxis = getCrossFlexDirection(mainAxis, direction);
+ int resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
+
+ // Handle width and height style attributes
+ setDimensionFromStyle(node, mainAxis);
+ setDimensionFromStyle(node, crossAxis);
+
+ // Set the resolved resolution in the node's layout
+ node.layout.direction = direction;
+
+ // The position is set by the parent, but we need to complete it with a
+ // delta composed of the margin and left/top/right/bottom
+ node.layout.position[leading[mainAxis]] += node.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) +
+ getRelativePosition(node, mainAxis);
+ node.layout.position[trailing[mainAxis]] += node.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) +
+ getRelativePosition(node, mainAxis);
+ node.layout.position[leading[crossAxis]] += node.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) +
+ getRelativePosition(node, crossAxis);
+ node.layout.position[trailing[crossAxis]] += node.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) +
+ getRelativePosition(node, crossAxis);
+
+ // Inline immutable values from the target node to avoid excessive method
+ // invocations during the layout calculation.
+ int childCount = node.getChildCount();
+ float paddingAndBorderAxisResolvedRow = ((node.style.padding.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.border.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis])) + (node.style.padding.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis]) + node.style.border.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis])));
+ float paddingAndBorderAxisColumn = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])));
+
+ if (isMeasureDefined(node)) {
+ boolean isResolvedRowDimDefined = (!Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0);
+
+ float width = CSSConstants.UNDEFINED;
+ if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) {
+ width = node.style.dimensions[DIMENSION_WIDTH];
+ } else if (isResolvedRowDimDefined) {
+ width = node.layout.dimensions[dim[resolvedRowAxis]];
+ } else {
+ width = parentMaxWidth -
+ (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis]));
+ }
+ width -= paddingAndBorderAxisResolvedRow;
+
+ float height = CSSConstants.UNDEFINED;
+ if ((!Float.isNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
+ height = node.style.dimensions[DIMENSION_HEIGHT];
+ } else if ((!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
+ height = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]];
+ } else {
+ height = parentMaxHeight -
+ (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis]));
+ }
+ height -= ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])));
+
+ // We only need to give a dimension for the text if we haven't got any
+ // for it computed yet. It can either be from the style attribute or because
+ // the element is flexible.
+ boolean isRowUndefined = !(!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0) && !isResolvedRowDimDefined;
+ boolean isColumnUndefined = !(!Float.isNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0) &&
+ Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]);
+
+ // Let's not measure the text if we already know both dimensions
+ if (isRowUndefined || isColumnUndefined) {
+ MeasureOutput measureDim = node.measure(
+
+ layoutContext.measureOutput,
+ width,
+ height
+ );
+ if (isRowUndefined) {
+ node.layout.dimensions[DIMENSION_WIDTH] = measureDim.width +
+ paddingAndBorderAxisResolvedRow;
+ }
+ if (isColumnUndefined) {
+ node.layout.dimensions[DIMENSION_HEIGHT] = measureDim.height +
+ paddingAndBorderAxisColumn;
+ }
+ }
+ if (childCount == 0) {
+ return;
+ }
+ }
+
+ boolean isNodeFlexWrap = (node.style.flexWrap == CSSWrap.WRAP);
+
+ CSSJustify justifyContent = node.style.justifyContent;
+
+ float leadingPaddingAndBorderMain = (node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]));
+ float leadingPaddingAndBorderCross = (node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]));
+ float paddingAndBorderAxisMain = ((node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis])));
+ float paddingAndBorderAxisCross = ((node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis])) + (node.style.padding.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) + node.style.border.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
+
+ boolean isMainDimDefined = (!Float.isNaN(node.layout.dimensions[dim[mainAxis]]) && node.layout.dimensions[dim[mainAxis]] >= 0.0);
+ boolean isCrossDimDefined = (!Float.isNaN(node.layout.dimensions[dim[crossAxis]]) && node.layout.dimensions[dim[crossAxis]] >= 0.0);
+ boolean isMainRowDirection = (mainAxis == CSS_FLEX_DIRECTION_ROW || mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE);
+
+ int i;
+ int ii;
+ CSSNode child;
+ int axis;
+
+ CSSNode firstAbsoluteChild = null;
+ CSSNode currentAbsoluteChild = null;
+
+ float definedMainDim = CSSConstants.UNDEFINED;
+ if (isMainDimDefined) {
+ definedMainDim = node.layout.dimensions[dim[mainAxis]] - paddingAndBorderAxisMain;
+ }
+
+ // We want to execute the next two loops one per line with flex-wrap
+ int startLine = 0;
+ int endLine = 0;
+ // int nextOffset = 0;
+ int alreadyComputedNextLayout = 0;
+ // We aggregate the total dimensions of the container in those two variables
+ float linesCrossDim = 0;
+ float linesMainDim = 0;
+ int linesCount = 0;
+ while (endLine < childCount) {
+ // Layout non flexible children and count children by type
+
+ // mainContentDim is accumulation of the dimensions and margin of all the
+ // non flexible children. This will be used in order to either set the
+ // dimensions of the node if none already exist, or to compute the
+ // remaining space left for the flexible children.
+ float mainContentDim = 0;
+
+ // There are three kind of children, non flexible, flexible and absolute.
+ // We need to know how many there are in order to distribute the space.
+ int flexibleChildrenCount = 0;
+ float totalFlexible = 0;
+ int nonFlexibleChildrenCount = 0;
+
+ // Use the line loop to position children in the main axis for as long
+ // as they are using a simple stacking behaviour. Children that are
+ // immediately stacked in the initial loop will not be touched again
+ // in .
+ boolean isSimpleStackMain =
+ (isMainDimDefined && justifyContent == CSSJustify.FLEX_START) ||
+ (!isMainDimDefined && justifyContent != CSSJustify.CENTER);
+ int firstComplexMain = (isSimpleStackMain ? childCount : startLine);
+
+ // Use the initial line loop to position children in the cross axis for
+ // as long as they are relatively positioned with alignment STRETCH or
+ // FLEX_START. Children that are immediately stacked in the initial loop
+ // will not be touched again in .
+ boolean isSimpleStackCross = true;
+ int firstComplexCross = childCount;
+
+ CSSNode firstFlexChild = null;
+ CSSNode currentFlexChild = null;
+
+ float mainDim = leadingPaddingAndBorderMain;
+ float crossDim = 0;
+
+ float maxWidth;
+ float maxHeight;
+ for (i = startLine; i < childCount; ++i) {
+ child = node.getChildAt(i);
+ child.lineIndex = linesCount;
+
+ child.nextAbsoluteChild = null;
+ child.nextFlexChild = null;
+
+ CSSAlign alignItem = getAlignItem(node, child);
+
+ // Pre-fill cross axis dimensions when the child is using stretch before
+ // we call the recursive layout pass
+ if (alignItem == CSSAlign.STRETCH &&
+ child.style.positionType == CSSPositionType.RELATIVE &&
+ isCrossDimDefined &&
+ !(!Float.isNaN(child.style.dimensions[dim[crossAxis]]) && child.style.dimensions[dim[crossAxis]] >= 0.0)) {
+ child.layout.dimensions[dim[crossAxis]] = Math.max(
+ boundAxis(child, crossAxis, node.layout.dimensions[dim[crossAxis]] -
+ paddingAndBorderAxisCross - (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))),
+ // You never want to go smaller than padding
+ ((child.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis])) + (child.style.padding.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) + child.style.border.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])))
+ );
+ } else if (child.style.positionType == CSSPositionType.ABSOLUTE) {
+ // Store a private linked list of absolutely positioned children
+ // so that we can efficiently traverse them later.
+ if (firstAbsoluteChild == null) {
+ firstAbsoluteChild = child;
+ }
+ if (currentAbsoluteChild != null) {
+ currentAbsoluteChild.nextAbsoluteChild = child;
+ }
+ currentAbsoluteChild = child;
+
+ // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
+ // left and right or top and bottom).
+ for (ii = 0; ii < 2; ii++) {
+ axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
+ if ((!Float.isNaN(node.layout.dimensions[dim[axis]]) && node.layout.dimensions[dim[axis]] >= 0.0) &&
+ !(!Float.isNaN(child.style.dimensions[dim[axis]]) && child.style.dimensions[dim[axis]] >= 0.0) &&
+ !Float.isNaN(child.style.position[leading[axis]]) &&
+ !Float.isNaN(child.style.position[trailing[axis]])) {
+ child.layout.dimensions[dim[axis]] = Math.max(
+ boundAxis(child, axis, node.layout.dimensions[dim[axis]] -
+ ((node.style.padding.getWithFallback(leadingSpacing[axis], leading[axis]) + node.style.border.getWithFallback(leadingSpacing[axis], leading[axis])) + (node.style.padding.getWithFallback(trailingSpacing[axis], trailing[axis]) + node.style.border.getWithFallback(trailingSpacing[axis], trailing[axis]))) -
+ (child.style.margin.getWithFallback(leadingSpacing[axis], leading[axis]) + child.style.margin.getWithFallback(trailingSpacing[axis], trailing[axis])) -
+ (Float.isNaN(child.style.position[leading[axis]]) ? 0 : child.style.position[leading[axis]]) -
+ (Float.isNaN(child.style.position[trailing[axis]]) ? 0 : child.style.position[trailing[axis]])),
+ // You never want to go smaller than padding
+ ((child.style.padding.getWithFallback(leadingSpacing[axis], leading[axis]) + child.style.border.getWithFallback(leadingSpacing[axis], leading[axis])) + (child.style.padding.getWithFallback(trailingSpacing[axis], trailing[axis]) + child.style.border.getWithFallback(trailingSpacing[axis], trailing[axis])))
+ );
+ }
+ }
+ }
+
+ float nextContentDim = 0;
+
+ // It only makes sense to consider a child flexible if we have a computed
+ // dimension for the node.
+ if (isMainDimDefined && (child.style.positionType == CSSPositionType.RELATIVE && child.style.flex > 0)) {
+ flexibleChildrenCount++;
+ totalFlexible += child.style.flex;
+
+ // Store a private linked list of flexible children so that we can
+ // efficiently traverse them later.
+ if (firstFlexChild == null) {
+ firstFlexChild = child;
+ }
+ if (currentFlexChild != null) {
+ currentFlexChild.nextFlexChild = child;
+ }
+ currentFlexChild = child;
+
+ // Even if we don't know its exact size yet, we already know the padding,
+ // border and margin. We'll use this partial information, which represents
+ // the smallest possible size for the child, to compute the remaining
+ // available space.
+ nextContentDim = ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))) +
+ (child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
+
+ } else {
+ maxWidth = CSSConstants.UNDEFINED;
+ maxHeight = CSSConstants.UNDEFINED;
+
+ if (!isMainRowDirection) {
+ if ((!Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0)) {
+ maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] -
+ paddingAndBorderAxisResolvedRow;
+ } else {
+ maxWidth = parentMaxWidth -
+ (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis])) -
+ paddingAndBorderAxisResolvedRow;
+ }
+ } else {
+ if ((!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
+ maxHeight = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] -
+ paddingAndBorderAxisColumn;
+ } else {
+ maxHeight = parentMaxHeight -
+ (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])) -
+ paddingAndBorderAxisColumn;
+ }
+ }
+
+ // This is the main recursive call. We layout non flexible children.
+ if (alreadyComputedNextLayout == 0) {
+ layoutNode(layoutContext, child, maxWidth, maxHeight, direction);
+ }
+
+ // Absolute positioned elements do not take part of the layout, so we
+ // don't use them to compute mainContentDim
+ if (child.style.positionType == CSSPositionType.RELATIVE) {
+ nonFlexibleChildrenCount++;
+ // At this point we know the final size and margin of the element.
+ nextContentDim = (child.layout.dimensions[dim[mainAxis]] + child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
+ }
+ }
+
+ // The element we are about to add would make us go to the next line
+ if (isNodeFlexWrap &&
+ isMainDimDefined &&
+ mainContentDim + nextContentDim > definedMainDim &&
+ // If there's only one element, then it's bigger than the content
+ // and needs its own line
+ i != startLine) {
+ nonFlexibleChildrenCount--;
+ alreadyComputedNextLayout = 1;
+ break;
+ }
+
+ // Disable simple stacking in the main axis for the current line as
+ // we found a non-trivial child. The remaining children will be laid out
+ // in .
+ if (isSimpleStackMain &&
+ (child.style.positionType != CSSPositionType.RELATIVE || (child.style.positionType == CSSPositionType.RELATIVE && child.style.flex > 0))) {
+ isSimpleStackMain = false;
+ firstComplexMain = i;
+ }
+
+ // Disable simple stacking in the cross axis for the current line as
+ // we found a non-trivial child. The remaining children will be laid out
+ // in .
+ if (isSimpleStackCross &&
+ (child.style.positionType != CSSPositionType.RELATIVE ||
+ (alignItem != CSSAlign.STRETCH && alignItem != CSSAlign.FLEX_START) ||
+ !(!Float.isNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0))) {
+ isSimpleStackCross = false;
+ firstComplexCross = i;
+ }
+
+ if (isSimpleStackMain) {
+ child.layout.position[pos[mainAxis]] += mainDim;
+ if (isMainDimDefined) {
+ child.layout.position[trailing[mainAxis]] = node.layout.dimensions[dim[mainAxis]] - child.layout.dimensions[dim[mainAxis]] - child.layout.position[pos[mainAxis]];
+ }
+
+ mainDim += (child.layout.dimensions[dim[mainAxis]] + child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
+ crossDim = Math.max(crossDim, boundAxis(child, crossAxis, (child.layout.dimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))));
+ }
+
+ if (isSimpleStackCross) {
+ child.layout.position[pos[crossAxis]] += linesCrossDim + leadingPaddingAndBorderCross;
+ if (isCrossDimDefined) {
+ child.layout.position[trailing[crossAxis]] = node.layout.dimensions[dim[crossAxis]] - child.layout.dimensions[dim[crossAxis]] - child.layout.position[pos[crossAxis]];
+ }
+ }
+
+ alreadyComputedNextLayout = 0;
+ mainContentDim += nextContentDim;
+ endLine = i + 1;
+ }
+
+ // Layout flexible children and allocate empty space
+
+ // In order to position the elements in the main axis, we have two
+ // controls. The space between the beginning and the first element
+ // and the space between each two elements.
+ float leadingMainDim = 0;
+ float betweenMainDim = 0;
+
+ // The remaining available space that needs to be allocated
+ float remainingMainDim = 0;
+ if (isMainDimDefined) {
+ remainingMainDim = definedMainDim - mainContentDim;
+ } else {
+ remainingMainDim = Math.max(mainContentDim, 0) - mainContentDim;
+ }
+
+ // If there are flexible children in the mix, they are going to fill the
+ // remaining space
+ if (flexibleChildrenCount != 0) {
+ float flexibleMainDim = remainingMainDim / totalFlexible;
+ float baseMainDim;
+ float boundMainDim;
+
+ // If the flex share of remaining space doesn't meet min/max bounds,
+ // remove this child from flex calculations.
+ currentFlexChild = firstFlexChild;
+ while (currentFlexChild != null) {
+ baseMainDim = flexibleMainDim * currentFlexChild.style.flex +
+ ((currentFlexChild.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + currentFlexChild.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (currentFlexChild.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + currentFlexChild.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis])));
+ boundMainDim = boundAxis(currentFlexChild, mainAxis, baseMainDim);
+
+ if (baseMainDim != boundMainDim) {
+ remainingMainDim -= boundMainDim;
+ totalFlexible -= currentFlexChild.style.flex;
+ }
+
+ currentFlexChild = currentFlexChild.nextFlexChild;
+ }
+ flexibleMainDim = remainingMainDim / totalFlexible;
+
+ // The non flexible children can overflow the container, in this case
+ // we should just assume that there is no space available.
+ if (flexibleMainDim < 0) {
+ flexibleMainDim = 0;
+ }
+
+ currentFlexChild = firstFlexChild;
+ while (currentFlexChild != null) {
+ // At this point we know the final size of the element in the main
+ // dimension
+ currentFlexChild.layout.dimensions[dim[mainAxis]] = boundAxis(currentFlexChild, mainAxis,
+ flexibleMainDim * currentFlexChild.style.flex +
+ ((currentFlexChild.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + currentFlexChild.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (currentFlexChild.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + currentFlexChild.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis])))
+ );
+
+ maxWidth = CSSConstants.UNDEFINED;
+ if ((!Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0)) {
+ maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] -
+ paddingAndBorderAxisResolvedRow;
+ } else if (!isMainRowDirection) {
+ maxWidth = parentMaxWidth -
+ (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis])) -
+ paddingAndBorderAxisResolvedRow;
+ }
+ maxHeight = CSSConstants.UNDEFINED;
+ if ((!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
+ maxHeight = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] -
+ paddingAndBorderAxisColumn;
+ } else if (isMainRowDirection) {
+ maxHeight = parentMaxHeight -
+ (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])) -
+ paddingAndBorderAxisColumn;
+ }
+
+ // And we recursively call the layout algorithm for this child
+ layoutNode(layoutContext, currentFlexChild, maxWidth, maxHeight, direction);
+
+ child = currentFlexChild;
+ currentFlexChild = currentFlexChild.nextFlexChild;
+ child.nextFlexChild = null;
+ }
+
+ // We use justifyContent to figure out how to allocate the remaining
+ // space available
+ } else if (justifyContent != CSSJustify.FLEX_START) {
+ if (justifyContent == CSSJustify.CENTER) {
+ leadingMainDim = remainingMainDim / 2;
+ } else if (justifyContent == CSSJustify.FLEX_END) {
+ leadingMainDim = remainingMainDim;
+ } else if (justifyContent == CSSJustify.SPACE_BETWEEN) {
+ remainingMainDim = Math.max(remainingMainDim, 0);
+ if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 != 0) {
+ betweenMainDim = remainingMainDim /
+ (flexibleChildrenCount + nonFlexibleChildrenCount - 1);
+ } else {
+ betweenMainDim = 0;
+ }
+ } else if (justifyContent == CSSJustify.SPACE_AROUND) {
+ // Space on the edges is half of the space between elements
+ betweenMainDim = remainingMainDim /
+ (flexibleChildrenCount + nonFlexibleChildrenCount);
+ leadingMainDim = betweenMainDim / 2;
+ }
+ }
+
+ // Position elements in the main axis and compute dimensions
+
+ // At this point, all the children have their dimensions set. We need to
+ // find their position. In order to do that, we accumulate data in
+ // variables that are also useful to compute the total dimensions of the
+ // container!
+ mainDim += leadingMainDim;
+
+ for (i = firstComplexMain; i < endLine; ++i) {
+ child = node.getChildAt(i);
+
+ if (child.style.positionType == CSSPositionType.ABSOLUTE &&
+ !Float.isNaN(child.style.position[leading[mainAxis]])) {
+ // In case the child is position absolute and has left/top being
+ // defined, we override the position to whatever the user said
+ // (and margin/border).
+ child.layout.position[pos[mainAxis]] = (Float.isNaN(child.style.position[leading[mainAxis]]) ? 0 : child.style.position[leading[mainAxis]]) +
+ node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) +
+ child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]);
+ } else {
+ // If the child is position absolute (without top/left) or relative,
+ // we put it at the current accumulated offset.
+ child.layout.position[pos[mainAxis]] += mainDim;
+
+ // Define the trailing position accordingly.
+ if (isMainDimDefined) {
+ child.layout.position[trailing[mainAxis]] = node.layout.dimensions[dim[mainAxis]] - child.layout.dimensions[dim[mainAxis]] - child.layout.position[pos[mainAxis]];
+ }
+
+ // Now that we placed the element, we need to update the variables
+ // We only need to do that for relative elements. Absolute elements
+ // do not take part in that phase.
+ if (child.style.positionType == CSSPositionType.RELATIVE) {
+ // The main dimension is the sum of all the elements dimension plus
+ // the spacing.
+ mainDim += betweenMainDim + (child.layout.dimensions[dim[mainAxis]] + child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
+ // The cross dimension is the max of the elements dimension since there
+ // can only be one element in that cross dimension.
+ crossDim = Math.max(crossDim, boundAxis(child, crossAxis, (child.layout.dimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))));
+ }
+ }
+ }
+
+ float containerCrossAxis = node.layout.dimensions[dim[crossAxis]];
+ if (!isCrossDimDefined) {
+ containerCrossAxis = Math.max(
+ // For the cross dim, we add both sides at the end because the value
+ // is aggregate via a max function. Intermediate negative values
+ // can mess this computation otherwise
+ boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross),
+ paddingAndBorderAxisCross
+ );
+ }
+
+ // Position elements in the cross axis
+ for (i = firstComplexCross; i < endLine; ++i) {
+ child = node.getChildAt(i);
+
+ if (child.style.positionType == CSSPositionType.ABSOLUTE &&
+ !Float.isNaN(child.style.position[leading[crossAxis]])) {
+ // In case the child is absolutely positionned and has a
+ // top/left/bottom/right being set, we override all the previously
+ // computed positions to set it correctly.
+ child.layout.position[pos[crossAxis]] = (Float.isNaN(child.style.position[leading[crossAxis]]) ? 0 : child.style.position[leading[crossAxis]]) +
+ node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) +
+ child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]);
+
+ } else {
+ float leadingCrossDim = leadingPaddingAndBorderCross;
+
+ // For a relative children, we're either using alignItems (parent) or
+ // alignSelf (child) in order to determine the position in the cross axis
+ if (child.style.positionType == CSSPositionType.RELATIVE) {
+ /*eslint-disable */
+ // This variable is intentionally re-defined as the code is transpiled to a block scope language
+ CSSAlign alignItem = getAlignItem(node, child);
+ /*eslint-enable */
+ if (alignItem == CSSAlign.STRETCH) {
+ // You can only stretch if the dimension has not already been set
+ // previously.
+ if (!(!Float.isNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0)) {
+ child.layout.dimensions[dim[crossAxis]] = Math.max(
+ boundAxis(child, crossAxis, containerCrossAxis -
+ paddingAndBorderAxisCross - (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))),
+ // You never want to go smaller than padding
+ ((child.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis])) + (child.style.padding.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) + child.style.border.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])))
+ );
+ }
+ } else if (alignItem != CSSAlign.FLEX_START) {
+ // The remaining space between the parent dimensions+padding and child
+ // dimensions+margin.
+ float remainingCrossDim = containerCrossAxis -
+ paddingAndBorderAxisCross - (child.layout.dimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]));
+
+ if (alignItem == CSSAlign.CENTER) {
+ leadingCrossDim += remainingCrossDim / 2;
+ } else { // CSSAlign.FLEX_END
+ leadingCrossDim += remainingCrossDim;
+ }
+ }
+ }
+
+ // And we apply the position
+ child.layout.position[pos[crossAxis]] += linesCrossDim + leadingCrossDim;
+
+ // Define the trailing position accordingly.
+ if (isCrossDimDefined) {
+ child.layout.position[trailing[crossAxis]] = node.layout.dimensions[dim[crossAxis]] - child.layout.dimensions[dim[crossAxis]] - child.layout.position[pos[crossAxis]];
+ }
+ }
+ }
+
+ linesCrossDim += crossDim;
+ linesMainDim = Math.max(linesMainDim, mainDim);
+ linesCount += 1;
+ startLine = endLine;
+ }
+
+ //
+ //
+ // Note(prenaux): More than one line, we need to layout the crossAxis
+ // according to alignContent.
+ //
+ // Note that we could probably remove and handle the one line case
+ // here too, but for the moment this is safer since it won't interfere with
+ // previously working code.
+ //
+ // See specs:
+ // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm
+ // section 9.4
+ //
+ if (linesCount > 1 && isCrossDimDefined) {
+ float nodeCrossAxisInnerSize = node.layout.dimensions[dim[crossAxis]] -
+ paddingAndBorderAxisCross;
+ float remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;
+
+ float crossDimLead = 0;
+ float currentLead = leadingPaddingAndBorderCross;
+
+ CSSAlign alignContent = node.style.alignContent;
+ if (alignContent == CSSAlign.FLEX_END) {
+ currentLead += remainingAlignContentDim;
+ } else if (alignContent == CSSAlign.CENTER) {
+ currentLead += remainingAlignContentDim / 2;
+ } else if (alignContent == CSSAlign.STRETCH) {
+ if (nodeCrossAxisInnerSize > linesCrossDim) {
+ crossDimLead = (remainingAlignContentDim / linesCount);
+ }
+ }
+
+ int endIndex = 0;
+ for (i = 0; i < linesCount; ++i) {
+ int startIndex = endIndex;
+
+ // compute the line's height and find the endIndex
+ float lineHeight = 0;
+ for (ii = startIndex; ii < childCount; ++ii) {
+ child = node.getChildAt(ii);
+ if (child.style.positionType != CSSPositionType.RELATIVE) {
+ continue;
+ }
+ if (child.lineIndex != i) {
+ break;
+ }
+ if ((!Float.isNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0)) {
+ lineHeight = Math.max(
+ lineHeight,
+ child.layout.dimensions[dim[crossAxis]] + (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))
+ );
+ }
+ }
+ endIndex = ii;
+ lineHeight += crossDimLead;
+
+ for (ii = startIndex; ii < endIndex; ++ii) {
+ child = node.getChildAt(ii);
+ if (child.style.positionType != CSSPositionType.RELATIVE) {
+ continue;
+ }
+
+ CSSAlign alignContentAlignItem = getAlignItem(node, child);
+ if (alignContentAlignItem == CSSAlign.FLEX_START) {
+ child.layout.position[pos[crossAxis]] = currentLead + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]);
+ } else if (alignContentAlignItem == CSSAlign.FLEX_END) {
+ child.layout.position[pos[crossAxis]] = currentLead + lineHeight - child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) - child.layout.dimensions[dim[crossAxis]];
+ } else if (alignContentAlignItem == CSSAlign.CENTER) {
+ float childHeight = child.layout.dimensions[dim[crossAxis]];
+ child.layout.position[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;
+ } else if (alignContentAlignItem == CSSAlign.STRETCH) {
+ child.layout.position[pos[crossAxis]] = currentLead + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]);
+ // TODO(prenaux): Correctly set the height of items with undefined
+ // (auto) crossAxis dimension.
+ }
+ }
+
+ currentLead += lineHeight;
+ }
+ }
+
+ boolean needsMainTrailingPos = false;
+ boolean needsCrossTrailingPos = false;
+
+ // If the user didn't specify a width or height, and it has not been set
+ // by the container, then we set it via the children.
+ if (!isMainDimDefined) {
+ node.layout.dimensions[dim[mainAxis]] = Math.max(
+ // We're missing the last padding at this point to get the final
+ // dimension
+ boundAxis(node, mainAxis, linesMainDim + (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))),
+ // We can never assign a width smaller than the padding and borders
+ paddingAndBorderAxisMain
+ );
+
+ if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
+ mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
+ needsMainTrailingPos = true;
+ }
+ }
+
+ if (!isCrossDimDefined) {
+ node.layout.dimensions[dim[crossAxis]] = Math.max(
+ // For the cross dim, we add both sides at the end because the value
+ // is aggregate via a max function. Intermediate negative values
+ // can mess this computation otherwise
+ boundAxis(node, crossAxis, linesCrossDim + paddingAndBorderAxisCross),
+ paddingAndBorderAxisCross
+ );
+
+ if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
+ crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
+ needsCrossTrailingPos = true;
+ }
+ }
+
+ // Set trailing position if necessary
+ if (needsMainTrailingPos || needsCrossTrailingPos) {
+ for (i = 0; i < childCount; ++i) {
+ child = node.getChildAt(i);
+
+ if (needsMainTrailingPos) {
+ child.layout.position[trailing[mainAxis]] = node.layout.dimensions[dim[mainAxis]] - child.layout.dimensions[dim[mainAxis]] - child.layout.position[pos[mainAxis]];
+ }
+
+ if (needsCrossTrailingPos) {
+ child.layout.position[trailing[crossAxis]] = node.layout.dimensions[dim[crossAxis]] - child.layout.dimensions[dim[crossAxis]] - child.layout.position[pos[crossAxis]];
+ }
+ }
+ }
+
+ // Calculate dimensions for absolutely positioned elements
+ currentAbsoluteChild = firstAbsoluteChild;
+ while (currentAbsoluteChild != null) {
+ // Pre-fill dimensions when using absolute position and both offsets for
+ // the axis are defined (either both left and right or top and bottom).
+ for (ii = 0; ii < 2; ii++) {
+ axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
+
+ if ((!Float.isNaN(node.layout.dimensions[dim[axis]]) && node.layout.dimensions[dim[axis]] >= 0.0) &&
+ !(!Float.isNaN(currentAbsoluteChild.style.dimensions[dim[axis]]) && currentAbsoluteChild.style.dimensions[dim[axis]] >= 0.0) &&
+ !Float.isNaN(currentAbsoluteChild.style.position[leading[axis]]) &&
+ !Float.isNaN(currentAbsoluteChild.style.position[trailing[axis]])) {
+ currentAbsoluteChild.layout.dimensions[dim[axis]] = Math.max(
+ boundAxis(currentAbsoluteChild, axis, node.layout.dimensions[dim[axis]] -
+ (node.style.border.getWithFallback(leadingSpacing[axis], leading[axis]) + node.style.border.getWithFallback(trailingSpacing[axis], trailing[axis])) -
+ (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[axis], leading[axis]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[axis], trailing[axis])) -
+ (Float.isNaN(currentAbsoluteChild.style.position[leading[axis]]) ? 0 : currentAbsoluteChild.style.position[leading[axis]]) -
+ (Float.isNaN(currentAbsoluteChild.style.position[trailing[axis]]) ? 0 : currentAbsoluteChild.style.position[trailing[axis]])
+ ),
+ // You never want to go smaller than padding
+ ((currentAbsoluteChild.style.padding.getWithFallback(leadingSpacing[axis], leading[axis]) + currentAbsoluteChild.style.border.getWithFallback(leadingSpacing[axis], leading[axis])) + (currentAbsoluteChild.style.padding.getWithFallback(trailingSpacing[axis], trailing[axis]) + currentAbsoluteChild.style.border.getWithFallback(trailingSpacing[axis], trailing[axis])))
+ );
+ }
+
+ if (!Float.isNaN(currentAbsoluteChild.style.position[trailing[axis]]) &&
+ !!Float.isNaN(currentAbsoluteChild.style.position[leading[axis]])) {
+ currentAbsoluteChild.layout.position[leading[axis]] =
+ node.layout.dimensions[dim[axis]] -
+ currentAbsoluteChild.layout.dimensions[dim[axis]] -
+ (Float.isNaN(currentAbsoluteChild.style.position[trailing[axis]]) ? 0 : currentAbsoluteChild.style.position[trailing[axis]]);
+ }
+ }
+
+ child = currentAbsoluteChild;
+ currentAbsoluteChild = currentAbsoluteChild.nextAbsoluteChild;
+ child.nextAbsoluteChild = null;
+ }
+ }
+ /** END_GENERATED **/
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/MeasureOutput.java b/Android/LuaViewSDK/src/com/facebook/csslayout/MeasureOutput.java
new file mode 100644
index 00000000..3efa1f2e
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/MeasureOutput.java
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+/**
+ * POJO to hold the output of the measure function.
+ */
+public class MeasureOutput {
+
+ public float width;
+ public float height;
+}
diff --git a/Android/LuaViewSDK/src/com/facebook/csslayout/Spacing.java b/Android/LuaViewSDK/src/com/facebook/csslayout/Spacing.java
new file mode 100644
index 00000000..3a68b0fb
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/facebook/csslayout/Spacing.java
@@ -0,0 +1,220 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+package com.facebook.csslayout;
+
+import com.taobao.luaview.annotations.Nullable;
+
+import java.util.Arrays;
+
+/**
+ * Class representing CSS spacing (padding, margin, and borders). This is mostly necessary to
+ * properly implement interactions and updates for properties like margin, marginLeft, and
+ * marginHorizontal.
+ */
+public class Spacing {
+
+ /**
+ * Spacing type that represents the left direction. E.g. {@code marginLeft}.
+ */
+ public static final int LEFT = 0;
+ /**
+ * Spacing type that represents the top direction. E.g. {@code marginTop}.
+ */
+ public static final int TOP = 1;
+ /**
+ * Spacing type that represents the right direction. E.g. {@code marginRight}.
+ */
+ public static final int RIGHT = 2;
+ /**
+ * Spacing type that represents the bottom direction. E.g. {@code marginBottom}.
+ */
+ public static final int BOTTOM = 3;
+ /**
+ * Spacing type that represents vertical direction (top and bottom). E.g. {@code marginVertical}.
+ */
+ public static final int VERTICAL = 4;
+ /**
+ * Spacing type that represents horizontal direction (left and right). E.g.
+ * {@code marginHorizontal}.
+ */
+ public static final int HORIZONTAL = 5;
+ /**
+ * Spacing type that represents start direction e.g. left in left-to-right, right in right-to-left.
+ */
+ public static final int START = 6;
+ /**
+ * Spacing type that represents end direction e.g. right in left-to-right, left in right-to-left.
+ */
+ public static final int END = 7;
+ /**
+ * Spacing type that represents all directions (left, top, right, bottom). E.g. {@code margin}.
+ */
+ public static final int ALL = 8;
+
+ private static final int[] sFlagsMap = {
+ 1, /*LEFT*/
+ 2, /*TOP*/
+ 4, /*RIGHT*/
+ 8, /*BOTTOM*/
+ 16, /*VERTICAL*/
+ 32, /*HORIZONTAL*/
+ 64, /*START*/
+ 128, /*END*/
+ 256, /*ALL*/
+ };
+
+ private final float[] mSpacing = newFullSpacingArray();
+ @Nullable private float[] mDefaultSpacing = null;
+ private int mValueFlags = 0;
+ private boolean mHasAliasesSet;
+
+ /**
+ * Set a spacing value.
+ *
+ * @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
+ * {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
+ * @param value the value for this direction
+ * @return {@code true} if the spacing has changed, or {@code false} if the same value was already
+ * set
+ */
+ public boolean set(int spacingType, float value) {
+ if (!FloatUtil.floatsEqual(mSpacing[spacingType], value)) {
+ mSpacing[spacingType] = value;
+
+ if (CSSConstants.isUndefined(value)) {
+ mValueFlags &= ~sFlagsMap[spacingType];
+ } else {
+ mValueFlags |= sFlagsMap[spacingType];
+ }
+
+ mHasAliasesSet =
+ (mValueFlags & sFlagsMap[ALL]) != 0 ||
+ (mValueFlags & sFlagsMap[VERTICAL]) != 0 ||
+ (mValueFlags & sFlagsMap[HORIZONTAL]) != 0;
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set a default spacing value. This is used as a fallback when no spacing has been set for a
+ * particular direction.
+ *
+ * @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
+ * @param value the default value for this direction
+ * @return
+ */
+ public boolean setDefault(int spacingType, float value) {
+ if (mDefaultSpacing == null) {
+ mDefaultSpacing = newSpacingResultArray();
+ }
+ if (!FloatUtil.floatsEqual(mDefaultSpacing[spacingType], value)) {
+ mDefaultSpacing[spacingType] = value;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the spacing for a direction. This takes into account any default values that have been set.
+ *
+ * @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
+ */
+ public float get(int spacingType) {
+ float defaultValue = (mDefaultSpacing != null)
+ ? mDefaultSpacing[spacingType]
+ : (spacingType == START || spacingType == END ? CSSConstants.UNDEFINED : 0);
+
+ if (mValueFlags == 0) {
+ return defaultValue;
+ }
+
+ if ((mValueFlags & sFlagsMap[spacingType]) != 0) {
+ return mSpacing[spacingType];
+ }
+
+ if (mHasAliasesSet) {
+ int secondType = spacingType == TOP || spacingType == BOTTOM ? VERTICAL : HORIZONTAL;
+ if ((mValueFlags & sFlagsMap[secondType]) != 0) {
+ return mSpacing[secondType];
+ } else if ((mValueFlags & sFlagsMap[ALL]) != 0) {
+ return mSpacing[ALL];
+ }
+ }
+
+ return defaultValue;
+ }
+
+ /**
+ * Get the raw value (that was set using {@link #set(int, float)}), without taking into account
+ * any default values.
+ *
+ * @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
+ * {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
+ */
+ public float getRaw(int spacingType) {
+ return mSpacing[spacingType];
+ }
+
+ /**
+ * Resets the spacing instance to its default state. This method is meant to be used when
+ * recycling {@link Spacing} instances.
+ */
+ void reset() {
+ Arrays.fill(mSpacing, CSSConstants.UNDEFINED);
+ mDefaultSpacing = null;
+ mHasAliasesSet = false;
+ mValueFlags = 0;
+ }
+
+ /**
+ * Try to get start value and fallback to given type if not defined. This is used privately
+ * by the layout engine as a more efficient way to fetch direction-aware values by
+ * avoid extra method invocations.
+ */
+ float getWithFallback(int spacingType, int fallbackType) {
+ return
+ (mValueFlags & sFlagsMap[spacingType]) != 0
+ ? mSpacing[spacingType]
+ : get(fallbackType);
+ }
+
+ private static float[] newFullSpacingArray() {
+ return new float[] {
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ };
+ }
+
+ private static float[] newSpacingResultArray() {
+ return newSpacingResultArray(0);
+ }
+
+ private static float[] newSpacingResultArray(float defaultValue) {
+ return new float[] {
+ defaultValue,
+ defaultValue,
+ defaultValue,
+ defaultValue,
+ defaultValue,
+ defaultValue,
+ CSSConstants.UNDEFINED,
+ CSSConstants.UNDEFINED,
+ defaultValue,
+ };
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/activity/LuaViewActivity.java b/Android/LuaViewSDK/src/com/taobao/luaview/activity/LuaViewActivity.java
new file mode 100644
index 00000000..4902dd58
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/activity/LuaViewActivity.java
@@ -0,0 +1,70 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.activity;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.taobao.luaview.global.Constants;
+import com.taobao.luaview.global.LuaView;
+
+/**
+ * LuaView Activity
+ *
+ * @author song
+ * @date 15/9/22
+ */
+public class LuaViewActivity extends Activity {
+ private LuaView mLuaView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLuaView = LuaView.create(this);
+ setContentView(mLuaView);
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ if (mLuaView != null) {
+ registerNameBeforeLoad(mLuaView);
+ load(mLuaView);
+ }
+ }
+
+ /**
+ * 注册接口,注册各种脚本,panel
+ */
+ public void registerNameBeforeLoad(final LuaView luaView) {
+ }
+
+ /**
+ * 加载数据
+ */
+ public void load(final LuaView luaView) {
+ luaView.load(getLuaUri());
+ }
+
+ /**
+ * 获取文件名称
+ *
+ * @return
+ */
+ private String getLuaUri() {
+ if (getIntent() != null && getIntent().hasExtra(Constants.PARAM_URI)) {
+ return getIntent().getStringExtra(Constants.PARAM_URI);
+ }
+ return null;
+ }
+
+ public LuaView getLuaView() {
+ return mLuaView;
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/activity/LuaViewFragmentActivity.java b/Android/LuaViewSDK/src/com/taobao/luaview/activity/LuaViewFragmentActivity.java
new file mode 100644
index 00000000..9748c3e6
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/activity/LuaViewFragmentActivity.java
@@ -0,0 +1,72 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.activity;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.taobao.luaview.global.Constants;
+import com.taobao.luaview.global.LuaView;
+
+/**
+ * LuaView Activity
+ *
+ * @author song
+ * @date 15/9/22
+ */
+public class LuaViewFragmentActivity extends FragmentActivity {
+ private LuaView mLuaView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLuaView = LuaView.create(this);
+ setContentView(mLuaView);
+ getSupportFragmentManager().beginTransaction().commit();
+ }
+
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ if (mLuaView != null) {
+ registerNameBeforeLoad(mLuaView);
+ load(mLuaView);
+ }
+ }
+
+ /**
+ * 注册接口,注册各种脚本,panel
+ */
+ public void registerNameBeforeLoad(final LuaView luaView) {
+ }
+
+ /**
+ * 加载数据
+ */
+ public void load(final LuaView luaView) {
+ luaView.load(getLuaUri());
+ }
+
+ /**
+ * 获取文件名称
+ *
+ * @return
+ */
+ private String getLuaUri() {
+ if (getIntent() != null && getIntent().hasExtra(Constants.PARAM_URI)) {
+ return getIntent().getStringExtra(Constants.PARAM_URI);
+ }
+ return null;
+ }
+
+ public LuaView getLuaView() {
+ return mLuaView;
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/annotations/Nonnull.java b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/Nonnull.java
new file mode 100644
index 00000000..6b79ae5c
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/Nonnull.java
@@ -0,0 +1,29 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Documented
+@TypeQualifier
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Nonnull {
+ When when() default When.ALWAYS;
+
+ public static class Checker implements TypeQualifierValidator {
+ public Checker() {
+ }
+
+ public When forConstantValue(Nonnull qualifierqualifierArgument, Object value) {
+ return value == null?When.NEVER:When.ALWAYS;
+ }
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/annotations/Nullable.java b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/Nullable.java
new file mode 100644
index 00000000..72b786a8
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/Nullable.java
@@ -0,0 +1,22 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Documented
+@Nonnull(
+ when = When.UNKNOWN
+)
+@Retention(RetentionPolicy.RUNTIME)
+@TypeQualifierNickname
+public @interface Nullable {
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifier.java b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifier.java
new file mode 100644
index 00000000..c3c71d74
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifier.java
@@ -0,0 +1,22 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Documented
+@Target({ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TypeQualifier {
+ Class> applicableTo() default Object.class;
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifierNickname.java b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifierNickname.java
new file mode 100644
index 00000000..9a3bfcb8
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifierNickname.java
@@ -0,0 +1,18 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Documented
+@Target({ElementType.ANNOTATION_TYPE})
+public @interface TypeQualifierNickname {
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifierValidator.java b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifierValidator.java
new file mode 100644
index 00000000..46640f28
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/TypeQualifierValidator.java
@@ -0,0 +1,16 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.annotations;
+
+import java.lang.annotation.Annotation;
+
+public interface TypeQualifierValidator {
+ @Nonnull
+ When forConstantValue(@Nonnull A var1, Object var2);
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/annotations/When.java b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/When.java
new file mode 100644
index 00000000..db8b0673
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/annotations/When.java
@@ -0,0 +1,19 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.annotations;
+
+public enum When {
+ ALWAYS,
+ UNKNOWN,
+ MAYBE,
+ NEVER;
+
+ private When() {
+ }
+}
diff --git a/Android/LuaViewSDK/src/com/taobao/luaview/cache/AppCache.java b/Android/LuaViewSDK/src/com/taobao/luaview/cache/AppCache.java
new file mode 100644
index 00000000..999c2933
--- /dev/null
+++ b/Android/LuaViewSDK/src/com/taobao/luaview/cache/AppCache.java
@@ -0,0 +1,252 @@
+/*
+ * Created by LuaView.
+ * Copyright (c) 2017, Alibaba Group. All rights reserved.
+ *
+ * This source code is licensed under the MIT.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+package com.taobao.luaview.cache;
+
+import android.app.Application;
+import android.support.v4.util.LruCache;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * App级别的引用cache,不会在退出的时候清空
+ *
+ * @author song
+ * @date 16/1/27
+ */
+public class AppCache {
+ public static final int DEFAULT_LRU_CACHE_PROTOTYPE_SIZE = (int) (1.5 * 1024 * 1024);//1.5M
+ public static final int DEFAULT_LRU_CACHE_SIZE = 5;//5个
+ public static final String CACHE_METHODS = "cache_methods";//方法名称缓存
+ public static final String CACHE_PUBLIC_KEY = "cache_public_key";//公钥
+ public static final String CACHE_METATABLES = "cache_metatables";//metatable缓存
+ public static final String CACHE_SCRIPTS = "cache_scripts";//脚本文件缓存,占用空间2%
+ public static final String CACHE_PROTOTYPE = "cache_prototype";//lua中间码缓存,占用空间3%
+
+ //全局静态cache
+ private static Map mCachePool;
+
+ //simple cache
+ private Map