momotech / mln Goto Github PK
View Code? Open in Web Editor NEW高性能、小巧、易上手的移动跨平台开发框架. A framework for building Mobile cross-platform apps with Lua
License: MIT License
高性能、小巧、易上手的移动跨平台开发框架. A framework for building Mobile cross-platform apps with Lua
License: MIT License
目前一个window
的上述方法只支持设置一次,多次设置的话只会执行最后一次设置的回调方法。多次回调这个使用场景还是比较多的,比如cell
中的svg
需要在viewDisappear
或者onDestory
页面销毁时去停止svg
。
view1 = View():width(100):height(100)
--view1:setGravity(MBit:bor(Gravity.RIGHT,Gravity.BOTTOM))
view1:bgColor(Color(121, 121, 0, 1.0))
window:addView(view1)
rotate = 30
view1:rotation(rotate)
view1:anchorPoint(0.1, 0.1)
view2 = Label():width(100):height(50):text("rotate+30"):bgColor(Color(120, 120, 120, 1)):marginTop(200)
window:addView(view2)
view2:onClick(function()
rotate = rotate + 30
view1:rotation(rotate, true)
end)
view3 = Label():width(200):height(50):text("anchorPoint(1, 1)"):bgColor(Color(120, 120, 120, 1)):marginTop(200):marginLeft(110)
window:addView(view3)
view3:onClick(function()
view1:anchorPoint(1, 1)
end)
view4 = Label():width(200):height(50):text("width(200):height(200)"):bgColor(Color(120, 120, 120, 1)):marginTop(260):marginLeft(110)
window:addView(view4)
view4:onClick(function()
view1:width(200):height(200)
end)
MLN项目目前还有些明显的bug和两端不一致,陌陌程序员正在修复,预计三周左右完成。
demo:
dataSource = { 'http://img0.imgtn.bdimg.com/it/u=3119758101,904377357&fm=26&gp=0.jpg',
'http://img3.imgtn.bdimg.com/it/u=153999598,1046213513&fm=26&gp=0.jpg',
'http://img0.imgtn.bdimg.com/it/u=3183925070,1159334990&fm=26&gp=0.jpg',
'http://img4.imgtn.bdimg.com/it/u=1645068771,1181810785&fm=26&gp=0.jpg' }
taps = { "5.0分", " 4条评论", "超赞房东", "可以做饭", "免费停车", "有洗衣机" }
local isAnimed = false
-- 邀请好友
local invite = Label()
:width(100)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(100)
:marginLeft(20)
:text("邀请好友")
:fontSize(18)
:cornerRadius(20)
:borderWidth(1)
:textAlign(TextAlign.CENTER)
window:addView(invite)
-- 横线
local line = View()
:width(MeasurementType.MATCH_PARENT)
:height(1)
:bgColor(Color(0, 0, 0, 0.3))
:marginTop(150)
window:addView(line)
local count = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(170)
:marginLeft(20)
:text("1个可定房源")
:fontSize(18)
window:addView(count)
-- 房源cell
local cellView = LinearLayout(LinearType.VERTICAL)
:width(MeasurementType.MATCH_PARENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(200)
:marginLeft(25)
:marginRight(25)
:marginBottom(10)
--:padding(5,25,10,25)
--:bgColor(Color(255,0,0,0.3))
window:addView(cellView)
-- ViewPagerAdapter
local adapter = ViewPagerAdapter()
adapter:getCount(function(section)
return #dataSource
end)
adapter:initCell(function(cell, row)
local contentView = cell.contentView
contentView:bgColor(Color(255, 255, 255, 1))
cell.imageView = ImageView()
cell.imageView:contentMode(ContentMode.SCALE_TO_FILL)
cell.imageView:width(MeasurementType.MATCH_PARENT):height(MeasurementType.MATCH_PARENT)
contentView:addView(cell.imageView)
end)
adapter:fillCellData(function(cell, row)
local item = dataSource[row]
cell.imageView:image(item)
end)
-- ViewPager
local viewPager = ViewPager()
:width(MeasurementType.MATCH_PARENT)
:height(150):bgColor(Color(255,0,0,0.3))
cellView:addView(viewPager)
viewPager:adapter(adapter)
viewPager:showIndicator(true)
-- 房源信息文本
local descView = LinearLayout(LinearType.VERTICAL):width(MeasurementType.MATCH_PARENT):height(MeasurementType.WRAP_CONTENT)
cellView:addView(descView)
local info1 = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(8)
:text("整套公寓 1张床")
:fontSize(10)
descView:addView(info1)
local info2 = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(8)
:lines(0)
:text("南京南站地铁口商圈毗邻景区市中心新街口影院无印风大床套房")
:fontSize(15)
descView:addView(info2)
local info3 = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(8)
:text("¥ 258/晚")
:fontSize(10)
descView:addView(info3)
local info4 = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(8)
:text("超赞房东")
:fontSize(10)
descView:addView(info4)
--房源详情标签
tapView = WaterfallView(false, false):width(MeasurementType.MATCH_PARENT):height(100):marginTop(5)
tapLayout = WaterfallLayoutFix():itemSpacing(1):lineSpacing(1):spanCount(5)
tapAdapter = WaterfallAdapter()
tapAdapter:initCell(function(cell)
cell.tapLabel = Label():text("可以做饭"):textColor(Color(100, 150, 100, 1)):fontSize(10):padding(3, 6, 3, 6):bgColor(Color(100, 150, 100, 0.2)):cornerRadius(5)
cell.contentView:addView(cell.tapLabel)
end)
tapAdapter:fillCellData(function(cell, _, row)
cell.tapLabel:text(taps[row])
end)
tapAdapter:rowCount(function()
return #taps;
end)
tapView:layout(tapLayout)
tapView:adapter(tapAdapter)
descView:addView(tapView)
tapView:gone(true)
-- 缩放动画
local animator = Animator()
animator:setDuration(1)
animator:setOnAnimationUpdateCallback(function(percentage)
cellView:marginLeft(25 - 25 * percentage):marginRight(25 - 25 * percentage):marginTop(200 - 200 * percentage)
end)
--viewpager alpha 1 - 0.3 - 1
vpAnim = AlphaAnimation(1, 0.3)
vpAnim:setDuration(0.5):setRepeat(RepeatType.REVERSE, 1)
-- label alpha 1 - 0 - 1
descAnim = AlphaAnimation(1, 0)
descAnim:setDuration(0.5):setRepeat(RepeatType.REVERSE, 1)
descAnim:setRepeatCallback(function()
print("descAnim-setRepeatCallback")
info1:textColor((Color(80, 80, 200, 1)))
info2:setTextFontStyle(FontStyle.BOLD)
info3:gone(true)
info4:gone(true)
tapView:gone(false)
descView:padding(20, 20, 20, 20)
end)
cellView:onClick(function()
if not isAnimed then
invite:hidden(true)
line:hidden(true)
count:hidden(true)
viewPager:startAnimation(vpAnim)
descView:startAnimation(descAnim)
animator:start()
isAnimed = true
end
end)
Android、iOS强持有的对象需要文档标注,如:addView
两秒播放70张左右安卓端会出现闪烁,iOS 端正常
GameFeedApi:getGameFeedListData(self.currentIndex, sCount, function(success, response, error)
self:processResult(success, response, error)
end, self.targetFeedID)
如第三个变量为非匿名函数那么回调的 success, response, error 将发生错误
view子视图超出父视图时安卓clipToBounds默认true,iOS NO,两端表现不一致。出于性能考虑暂时没有修复,正在寻找解决方案。
demo:
switch = Switch()
switch:width(100):height(80):marginLeft(100):marginTop(100)
switch:bgColor(Color(223, 213, 12, 1))
switch:on(true)
switch:setThumbColor(Color(255,0,0,1)) --设置圆点颜色
switch:setNormalColor(Color(0,0,255,1)) --设置未选中主题色
switch:setSelectedColor(Color(255,255,0,1)) --设置选中主题色
switch:setSwitchChangedCallback(function(isOn)
print("switch changed -----", isOn)
print("switch ----- ", switch:on())
end)
window:addView(switch)
demo:
function setupViewPager()
dataSource = {"1", "2", "3", "4", "5"}
viewPager = ViewPager()
viewPager:width(window:width()):height(window:height() - 50):marginTop(50)
adapter = ViewPagerAdapter()
adapter:getCount(function() --设置cell数量回调
return #dataSource
end)
adapter:initCell(function (cell) --设置初始化cell的回调
cell.label = Label():width(200):height(200)
cell.label:marginTop(200):marginLeft(80)
cell.label:fontSize(40)
cell.label:textAlign(TextAlign.CENTER)
cell.contentView:cornerRadius(10):clipToBounds(true) --圆角
cell.contentView:bgColor(Color(100, 100, 100, 0.5))
cell.contentView:addView(cell.label)
end)
adapter:fillCellData(function (cell, position) --设置初始化cell数据的回调
local data = dataSource[position]
cell.label:text(data)
end)
viewPager:setPageClickListener(function (position) --设置点击指定页的回调
--Toast("Click position: "..tostring(position),1)
end)
viewPager:autoScroll(false) --是否自动滚动
viewPager:showIndicator(true)
viewPager:adapter(adapter)
window:addView(viewPager)
end
-- 创建viewPager
setupViewPager()
-----------以下为创建tab segment--------------
local array = Array()
array:add('附近动态')
array:add('附近的人')
array:add('附近直播')
array:add('item4')
array:add('item5')
array:add('item6')
array:add('item7')
array:add('item8')
array:add('item9')
array:add('item10')
array:add('item11')
array:add('item12')
array:add('item13')
array:add('item14')
print(array)
-- android的array暂不支持lua table
tabSegment = TabSegmentView(Rect(0, 80, window:width(), 50), array)
tabSegment:relatedToViewPager(viewPager)
tabSegment:bgColor(Color():hex(0xffff00):alpha(1))
tabSegment:selectScale(1.6)
tabSegment:normalFontSize(15)
tabSegment:setTapBadgeNumAtIndex(30, 3)
window:addView(tabSegment)
tabSegment:setTabSelectedListener(function(index)
print(">>> 选中 tab index =", index)
end)
local label4 = Label()
label4:marginTop(200):width(200):height(50)
label4:fontSize(16)
label4:text("点击选中第2个 tab")
label4:bgColor(Color():hex(0xffaa00):alpha(1))
label4:onClick(function()
print('>>>> currentIndex:', tabSegment:currentIndex())
-- 动画效果选中index 2
tabSegment:setCurrentIndexAnimated(2)
-- index 4上设置badge num为20
tabSegment:setTapBadgeNumAtIndex(20, 4)
-- index 1上展示红点
tabSegment:setRedDotHiddenAtIndex(1, true)
-- 隐藏index 3上的badge num
tabSegment:setTapBadgeNumAtIndex(0, 3)
end)
window:addView(label4)
MLN对这个问题增加了安全区域概念(Safe Area), 开启Safe Area后,开发人只需要关注页面具体内容,不需要为各种设备的不同页面模式去适配顶部开始距离和底部留白的高度,MLN层会自动适配不同方位上的安全区域。
希望提供创建window模版功能
1、包含声明周期相关函数
2、充分注释
3、最佳实践
iOS 端设置锚点会导致 View 的位置也会移动,Android 端不会。
希望在修改完锚点之后,能重新设置一遍 frame,保持 layer 不移动。
demo:
local view = View()
:width(100)
:height(100)
:marginLeft(100)
:marginTop(100)
:bgColor(Color(255,0,0,1))
view:anchorPoint(1,1)
window:addView(view)
a_setIncludeFontPadding 设置Android的Label是否有内边距。
Android默认有,IOS没有。
这块可以像IOS靠拢,默认a_setIncludeFontPadding(false)。
另外看看小米8的机型问题
想问一下 这套框架 对于Flutter RN等, 有哪些核心竞争力. 去让大家觉得有必要去使用它.
function foo()
local localView = View()
self.contentView:addView(localView)
end
localView超出作用域,iOS会释放localView android addView后会持有,两端实现不一致。
近期会尝试修改
我自己看了一下代码,感觉和RN Weex 原理类似?渲染还是交给原生做?
IDEA版本:2019.3; EmmyLua版本:1.3.0.135-neggaqnw-IDEA182
保持现状
--扫描二维码获取ip地址不对,刘旭已修复✅
CollectionViewGridLayoutFix
-> CollectionViewLayout
WaterfallLayoutFix
-> WaterfallLayout
function
,没有进一步提示这个函数的参数---已在内部merge/out分支上修复
---已在内部merge/out分支上修复
---暂不修复
viewPager
调用reloadData
后会导致setScrollEnable(false)
方法失效
demo:
local label = Label()
label:width(100):height(50):marginTop(200)
label:text("alert"):fontSize(16):textAlign(TextAlign.CENTER)
label:addCornerMask(10, Color(255,255,255,1), RectCorner.ALL_CORNERS)
label:bgColor(Color(125,125,125,1))
window:addView(label)
clipToBounds方法只能在父视图被addView后使用才会生效,在addView前使用无效,不应该有此限制条件。
例如,下述demo中,fatherView1:clipToBounds(false)
只能写在fatherView:addView(fatherView1)
之后,希望写在fatherView:addView(fatherView1)
之前也能生效。
--- 父视图的父视图
local fatherView = View()
:width(MeasurementType.MATCH_PARENT)
:height(50)
:marginTop(80)
:bgColor(Color(0,0,0,0.3))
window:addView(fatherView)
--- 父视图
local fatherView1 = View()
:width(200)
:height(80)
:marginLeft(50)
:bgColor(Color(255,0,0,1))
--fatherView1:clipToBounds(false)
fatherView:addView(fatherView1)
fatherView1:clipToBounds(false)
--- 子视图
local subView1 = View()
:width(250)
:height(100)
:bgColor(Color(0,0,255,0.3))
fatherView1:addView(subView1)
Animator测试结果:
1.ios:设置setRepeat(RepeatType.REVERSE, 3)
,ios重复了2次回到最终状态,android重复3次回到初始状态; --- 已解决,现在两端一致
2.ios:设置setRepeat(RepeatType.FROM_START, 3)
,ios重复了4次,并且RepeatCallback多回调了1次; --- 已解决
3.ios:设置setDelay
无效; --- 已解决
4.setEndCallback方法,两端都报错,废弃了?; --- 没有这个方法
5.android:animator:clone()使用后报错 --- 已解决
6.旋转动画,stop后,两端显示不一致,ios停留在旋转的位置,android则回到初始位置; --- ios端已修复 ,两端一致;
demo:
local view = View()
view:width(100):height(100):marginTop(100):marginLeft(100)
view:bgColor(Color(212,14,23,1))
window:addView(view)
local ani = Animator():setDuration(3):setDelay(3):setRepeat(RepeatType.REVERSE, 3)
ani:setOnAnimationUpdateCallback(function(percentage)
view:height(100 + 30 * (percentage)):width(100 + 30 * (percentage))
end)
local linear = LinearLayout(LinearType.HORIZONTAL)
:width(MeasurementType.MATCH_PARENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(300)
window:addView(linear)
local start = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:fontSize(20)
:marginLeft(30)
:bgColor(Color(0,0,0,0.3))
:text("开始")
linear:addView(start)
local cancel = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:fontSize(20)
:marginLeft(30)
:bgColor(Color(0,0,0,0.3))
:text("取消")
linear:addView(cancel)
local stop = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:fontSize(20)
:marginLeft(30)
:bgColor(Color(0,0,0,0.3))
:text("结束")
linear:addView(stop)
local running = Label()
:width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:fontSize(20)
:marginLeft(30)
:bgColor(Color(0,0,0,0.3))
:text("isRunning")
linear:addView(running)
start:onClick(function ()
ani:start()
end)
cancel:onClick(function ()
ani:cancel()
end)
stop:onClick(function ()
ani:stop()
end)
running:onClick(function ()
Toast(tostring(ani:isRunning()), 1)
end)
ani:setStartCallback(function ()
print("StartCallback")
end)
ani:setStopCallback(function ()
print("StopCallback")
end)
ani:setRepeatCallback(function ()
print("RepeatCallback")
end)
ani:setCancelCallback(function ()
print("CancelCallback")
end)
local linearSet = LinearLayout(LinearType.HORIZONTAL)
:width(MeasurementType.MATCH_PARENT)
:height(MeasurementType.WRAP_CONTENT)
:marginTop(350)
window:addView(linearSet)
local setRepeat = Label():width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:marginLeft(10)
:bgColor(Color(0,0,0,0.3))
:fontSize(20):text("repeat")
linearSet:addView(setRepeat)
setRepeat:onClick(function ()
ani:setRepeat(RepeatType.FROM_START, 2)
end)
local setDelay = Label():width(MeasurementType.WRAP_CONTENT)
:height(MeasurementType.WRAP_CONTENT)
:marginLeft(50)
:bgColor(Color(0,0,0,0.3))
:fontSize(20):text("delay")
linearSet:addView(setDelay)
setDelay:onClick(function ()
ani:setDelay(5)
end)
--- 旋转视图
local rotateView = View()
rotateView:marginTop(400):width(100):height(100)
rotateView:bgColor(Color(14,212,23,1))
window:addView(rotateView)
ani2 = ani:clone()
ani2:setOnAnimationUpdateCallback(function(percentage)
rotateView:rotation(360 * percentage, true)
end)
rotateView:onClick(function()
ani2:start()
end)
window:onClick(function ()
ani2:stop()
end)
ani2:setStartCallback(function ()
print("StartCallback")
end)
ani2:setStopCallback(function ()
print("StopCallback")
end)
ani2:setRepeatCallback(function ()
print("RepeatCallback")
end)
ani2:setCancelCallback(function ()
print("CancelCallback")
end)
测试机型:iphone7, 软件版本:13.1.2
demo:
timer = Timer()
timer:repeatCount(1)
timer:interval(3.0)
startView = Label()
startView:text('开始')
startView:textAlign(TextAlign.CENTER)
startView:setGravity(Gravity.CENTER_HORIZONTAL)
startView:bgColor(Color(222, 20, 232, 1))
startView:width(80):height(30):marginTop(100)
startView:onClick(function()
print('timer ---- start')
Loading:show()
timer:start(function()
Loading:hide()
timer:stop()
print('timer ----- stop')
end)
end)
window:addView(startView)
(前提:ImageView未设置图片)请求图片为nil时,android端不执行setImageWithCallback,ios端则正常执行
demo:
local imgView = ImageView()
:marginTop(100)
:width(200)
:height(170)
:setGravity(Gravity.CENTER_HORIZONTAL)
:bgColor(Color(121,121,121,1.0))
window:addView(imgView)
local url = "http://pic23.nipic.com/20120914/8561775_161249013399_2.jpg"
local placeholderImgURL ="http://img.momocdn.com/album/89/36/8936A76E-A95A-D826-78F2-F443EA95962F20181114_250x250.webp"
local newImageUrl = "http://file06.16sucai.com/2016/0406/b1a3df64d1c4df3cfd105377b69dd9f9.jpg"
--imgView:image(newImageUrl)
--imgView:image("placeholder")
local test1 = Label():marginTop(310):bgColor(Color(255,0,255,1.0)):padding(5,5,5,5)
test1:text("点击设置网络图片")
test1:onClick(function()
local avatarURL = nil
imgView:setImageWithCallback(avatarURL, "placeholder", function(success, errmsg, imgURL)
print('callback url = ',imgURL)
print('error:',tostring(errmsg))
print('success:', tostring(success))
-- **我们现在是通过url判等来 模拟 回调2次的问题**
if imgURL == avatarURL then
print('callback ===== ')
if not success then
print('success为false时另加载图片')
imgView:image(url)
end
end
end)
end)
window:addView(test1)
如题:
mln文件访问支持相对路径,前缀:file://
对于两端私有的目录,可以也统一。
如:Android的Asserts目录,iOS的mainBundle目录。可以统一使用前缀:assert://
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.