M8Test Help

状态

单状态

状态是声明式UI中最重要的概念。当状态值发生改变时,UI会根据需要自动更新,无需像命令式UI那样通过代码手动更新UI。你只需改变状态值,例如按钮点击时:

  • 声明式UI中只需改变状态值,如 state.setValue(state.getValue() + 1) (每点击一次自增1)。当状态改变时,所有通过 trackSingleState 添加该状态的Composable都会自动更新,无需手动操作。

  • 命令式UI中需要直接修改控件属性,如 textView.setText(textView.getText().toInt() + 1) 。若存在多个关联组件,还需逐一修改,例如 textView2.setText(textView2.getText().toInt() + 1)

import com.m8test.script.GlobalVariables.* fun side1Run() { // 这是一个非常简单的例子,当点击按钮时会将计数器(状态)的值加1,状态改变后,使用到该状态的文本会自动更新 // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView.create { // 插槽(Slot)是一种内容分发机制。它允许你在封装一个通用组件时,在组件内部预留一些“坑位”或“插槽”,然后让使用该组件的父组件来决定这些“坑位”里到底填充什么内容。 // 创建一个Column,Column是一种垂直布局,可以让其中的组件垂直排列 Column { // 设置 Column 中 content 插槽的内容 setContent { // 1. 创建一个可变状态,用于保存计数器的值 val count = mutableStateOf(0) // 添加一个文件组件到 Column (垂直布局)中 Text { // 2. 在组件的某个属性中使用该状态的值 setText(count.getValue().toString()) // 3. 将状态添加到组件中,这样text组件就会监听该状态的改变,这个是必须的步骤,如果没有此步骤,那么 count 的值改变时,composable(text组件)不会重组(界面更新) trackSingleState(count) } // 添加一个文本按钮到 Column (垂直布局)中 TextButton { // 设置文本按钮的content插槽内容 setContent { // 在插槽中添加一个文本 Text { setText("点击我") } } // 设置按钮点击事件 setOnClick { // 4. 当按钮被点击时,更新状态的值,这时使用到count的所有组件都会重组(界面更新), 必须要 trackSingleState count.setValue(count.getValue() + 1) } } } } } // 启动一个Activity用于显示脚本界面 _activity.start() } // 下面的语句中的 '//-m8test-remove' 在实际编译时会被删除,也就是将会改成 'side1Run();', 但是不能省略,否则 side1Run 方法不会被执行 //-m8test-remove side1Run();
// 这是一个非常简单的例子,当点击按钮时会将计数器(状态)的值加1,状态改变后,使用到该状态的文本会自动更新 // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create { slot -> // 插槽(Slot)是一种内容分发机制。它允许你在封装一个通用组件时,在组件内部预留一些“坑位”或“插槽”,然后让使用该组件的父组件来决定这些“坑位”里到底填充什么内容。 // 创建一个Column,Column是一种垂直布局,可以让其中的组件垂直排列 slot.Column { column -> // 设置 Column 中 content 插槽的内容 column.setContent { columnSlot -> // 1. 创建一个可变状态,用于保存计数器的值 def count = columnSlot.mutableStateOf(0) // 添加一个文件组件到 Column (垂直布局)中 columnSlot.Text { text -> // 2. 在组件的某个属性中使用该状态的值 text.setText(count.getValue().toString()) // 3. 将状态添加到组件中,这样text组件就会监听该状态的改变,这个是必须的步骤,如果没有此步骤,那么 count 的值改变时,composable(text组件)不会重组(界面更新) text.trackSingleState(count) } // 添加一个文本按钮到 Column (垂直布局)中 columnSlot.TextButton { button -> // 设置文本按钮的content插槽内容 button.setContent { buttonSlot -> // 在插槽中添加一个文本 buttonSlot.Text { text -> text.setText("点击我") } } // 设置按钮点击事件 button.setOnClick { // 4. 当按钮被点击时,更新状态的值,这时使用到count的所有组件都会重组(界面更新), 必须要 trackSingleState count.setValue(count.getValue() + 1) } } } } } // 启动一个Activity用于显示脚本界面 $activity.start()
// 这是一个非常简单的例子,当点击按钮时会将计数器(状态)的值加1,状态改变后,使用到该状态的文本会自动更新 // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create(slot => { // 插槽(Slot)是一种内容分发机制。它允许你在封装一个通用组件时,在组件内部预留一些“坑位”或“插槽”,然后让使用该组件的父组件来决定这些“坑位”里到底填充什么内容。 // 创建一个Column,Column是一种垂直布局,可以让其中的组件垂直排列 slot.Column(column => { // 设置 Column 中 content 插槽的内容 column.setContent(columnSlot => { // 1. 创建一个可变状态,用于保存计数器的值 const count = columnSlot.mutableStateOf(0); // 添加一个文件组件到 Column (垂直布局)中 columnSlot.Text(text => { // 2. 在组件的某个属性中使用该状态的值 text.setText(count.getValue().toString()); // 3. 将状态添加到组件中,这样text组件就会监听该状态的改变,这个是必须的步骤,如果没有此步骤,那么 count 的值改变时,composable(text组件)不会重组(界面更新) text.trackSingleState(count); }); // 添加一个文本按钮到 Column (垂直布局)中 columnSlot.TextButton(button => { // 设置文本按钮的content插槽内容 button.setContent(buttonSlot => { // 在插槽中添加一个文本 buttonSlot.Text(text => { text.setText("点击我"); }); }); // 设置按钮点击事件 button.setOnClick(() => { // 4. 当按钮被点击时,更新状态的值,这时使用到count的所有组件都会重组(界面更新), 必须要 trackSingleState count.setValue(count.getValue() + 1); }); }); }); }); }); // 启动一个Activity用于显示脚本界面 $activity.start();
-- 这是一个非常简单的例子,当点击按钮时会将计数器(状态)的值加1,状态改变后,使用到该状态的文本会自动更新 -- 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView:create(function(slot) -- 插槽(Slot)是一种内容分发机制。它允许你在封装一个通用组件时,在组件内部预留一些“坑位”或“插槽”,然后让使用该组件的父组件来决定这些“坑位”里到底填充什么内容。 -- 创建一个Column,Column是一种垂直布局,可以让其中的组件垂直排列 slot:Column(function(column) -- 设置 Column 中 content 插槽的内容 column:setContent(function(columnSlot) -- 1. 创建一个可变状态,用于保存计数器的值 local count = columnSlot:mutableStateOf(0) -- 添加一个文件组件到 Column (垂直布局)中 columnSlot:Text(function(text) -- 2. 在组件的某个属性中使用该状态的值 text:setText(tostring(count:getValue())) -- 3. 将状态添加到组件中,这样text组件就会监听该状态的改变,这个是必须的步骤,如果没有此步骤,那么 count 的值改变时,composable(text组件)不会重组(界面更新) text:trackSingleState(count) end) -- 添加一个文本按钮到 Column (垂直布局)中 columnSlot:TextButton(function(button) -- 设置文本按钮的content插槽内容 button:setContent(function(buttonSlot) -- 在插槽中添加一个文本 buttonSlot:Text(function(text) text:setText("点击我") end) end) -- 设置按钮点击事件 button:setOnClick(function() -- 4. 当按钮被点击时,更新状态的值,这时使用到count的所有组件都会重组(界面更新), 必须要 trackSingleState count:setValue(count:getValue() + 1) end) end) end) end) end) -- 启动一个Activity用于显示脚本界面 _activity:start()
<?php /** @var m8test_java\com\m8test\script\core\api\ui\compose\ComposeView $composeView */ global $composeView; /** @var m8test_java\com\m8test\script\core\api\ui\Activity $activity */ global $activity; // 这是一个非常简单的例子,当点击按钮时会将计数器(状态)的值加1,状态改变后,使用到该状态的文本会自动更新 // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView->create(function ($slot) { // 插槽(Slot)是一种内容分发机制。它允许你在封装一个通用组件时,在组件内部预留一些“坑位”或“插槽”,然后让使用该组件的父组件来决定这些“坑位”里到底填充什么内容。 // 创建一个Column,Column是一种垂直布局,可以让其中的组件垂直排列 $slot->Column(function ($column) { // 设置 Column 中 content 插槽的内容 $column->setContent(function ($columnSlot) { // 1. 创建一个可变状态,用于保存计数器的值 $count = $columnSlot->mutableStateOf(0); // 添加一个文件组件到 Column (垂直布局)中 $columnSlot->Text(function ($text) use ($count) { // 2. 在组件的某个属性中使用该状态的值 (将数字转换为字符串) $text->setText((string)$count->getValue()); // 3. 将状态添加到组件中,这样text组件就会监听该状态的改变,这个是必须的步骤,如果没有此步骤,那么 count 的值改变时,composable(text组件)不会重组(界面更新) $text->trackSingleState($count); }); // 添加一个文本按钮到 Column (垂直布局)中 $columnSlot->TextButton(function ($button) use ($count) { // 设置文本按钮的content插槽内容 $button->setContent(function ($buttonSlot) { // 在插槽中添加一个文本 $buttonSlot->Text(function ($text) { $text->setText(javaString("点击我")); }); }); // 设置按钮点击事件 $button->setOnClick(function () use ($count) { // 4. 当按钮被点击时,更新状态的值,这时使用到count的所有组件都会重组(界面更新), 必须要 trackSingleState $count->setValue($count->getValue() + 1); }); }); }); }); }); // 启动一个Activity用于显示脚本界面 $activity->start();
# 导入所需的全局变量,每一行导入一个 from m8test_java.com.m8test.script.GlobalVariables import _activity from m8test_java.com.m8test.script.GlobalVariables import _composeView # 这是一个非常简单的例子,当点击按钮时会将计数器(状态)的值加1,状态改变后,使用到该状态的文本会自动更新 # 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView.create(lambda slot: # 插槽(Slot)是一种内容分发机制。它允许你在封装一个通用组件时,在组件内部预留一些“坑位”或“插槽”,然后让使用该组件的父组件来决定这些“坑位”里到底填充什么内容。 # 创建一个Column,Column是一种垂直布局,可以让其中的组件垂直排列 slot.Column(lambda column: # 设置 Column 中 content 插槽的内容 column.setContent(lambda columnSlot: ( # 1. 创建一个可变状态,用于保存计数器的值 # 使用海象运算符 `:=` 在表达式内部进行赋值 (count := columnSlot.mutableStateOf(0)), # 添加一个文件组件到 Column (垂直布局)中 # 因为 lambda 中需要执行多个操作,所以我们把它们放到一个元组里 columnSlot.Text(lambda text: ( # 2. 在组件的某个属性中使用该状态的值 # Groovy 的 .toString() 相当于 Python 的 str() text.setText(str(count.getValue())), # 3. 将状态添加到组件中,这样text组件就会监听该状态的改变,这个是必须的步骤,如果没有此步骤,那么 count 的值改变时,composable(text组件)不会重组(界面更新) text.trackSingleState(count) )), # 添加一个文本按钮到 Column (垂直布局)中 columnSlot.TextButton(lambda button: ( # 设置文本按钮的content插槽内容 button.setContent(lambda buttonSlot: # 在插槽中添加一个文本 buttonSlot.Text(lambda text: text.setText("点击我") ) ), # 设置按钮点击事件 button.setOnClick(lambda: # 4. 当按钮被点击时,更新状态的值,这时使用到count的所有组件都会重组(界面更新), 必须要 trackSingleState count.setValue(count.getValue() + 1) ) )) )) ) ) # 启动一个Activity用于显示脚本界面 _activity.start()
# encoding: utf-8 # 这是一个非常简单的例子,当点击按钮时会将计数器(状态)的值加1,状态改变后,使用到该状态的文本会自动更新 # 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create do |slot| # 插槽(Slot)是一种内容分发机制。它允许你在封装一个通用组件时,在组件内部预留一些“坑位”或“插槽”,然后让使用该组件的父组件来决定这些“坑位”里到底填充什么内容。 # 创建一个Column,Column是一种垂直布局,可以让其中的组件垂直排列 slot.Column do |column| # 设置 Column 中 content 插槽的内容 column.setContent do |columnSlot| # 1. 创建一个可变状态,用于保存计数器的值 count = columnSlot.mutableStateOf(0) # 添加一个文件组件到 Column (垂直布局)中 columnSlot.Text do |text| # 2. 在组件的某个属性中使用该状态的值 text.setText(count.getValue().to_s) # 3. 将状态添加到组件中,这样text组件就会监听该状态的改变,这个是必须的步骤,如果没有此步骤,那么 count 的值改变时,composable(text组件)不会重组(界面更新) text.trackSingleState(count) end # 添加一个文本按钮到 Column (垂直布局)中 columnSlot.TextButton do |button| # 设置文本按钮的content插槽内容 button.setContent do |buttonSlot| # 在插槽中添加一个文本 buttonSlot.Text do |text| text.setText("点击我") end end # 设置按钮点击事件 button.setOnClick do # 4. 当按钮被点击时,更新状态的值,这时使用到count的所有组件都会重组(界面更新), 必须要 trackSingleState count.setValue(count.getValue() + 1) end end end end end # 启动一个Activity用于显示脚本界面 $activity.start()

对于状态列表,可通过 LazyRowLazyColumn 实现。当列表中的元素发生改变时, LazyRowLazyColumn 会自动更新。

import com.m8test.script.GlobalVariables.* fun side1Run() { // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView.create { // 1. 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 val state = mutableStateListOf(_iterables.listOf("初始数据")) LazyColumn { setModifier { fillMaxWidth(1f) } // 2. 跟踪状态列表,当列表增删改时 LazyColumn 会重组 trackSingleState(state) // 设置懒列表内容 setContent { // 设置列表固定头 stickyHeader(null, null) { index -> // 添加一个 Button 到列表固定头 Button { // 设置按钮内容 setContent { // 添加文本到按钮中 Text { // 设置按钮中文本显示的内容 setText("添加项目") } } // 4. 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 setOnClick { state.add("+++++") } } } // 3. 将状态列表中的数据显示到 LazyColumn 中 itemsIndexed(state, null, null) { index, item -> // 状态列表中每个元素显示一个简单的 Text 组件 Text { setModifier { height { d -> d.fromInt(200) } } // 设置 Text 组件显示的内容 setText(item) } } } } } // 启动一个Activity用于显示脚本界面 _activity.start() } //-m8test-remove side1Run();
// 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create { slot -> // 1. 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 def state = slot.mutableStateListOf($iterables.listOf("初始数据")) slot.LazyColumn { lc -> lc.setModifier { it.fillMaxWidth(1f) } // 2. 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state) // 设置懒列表内容 lc.setContent { lls -> // 设置列表固定头 lls.stickyHeader(null, null) { llss, index -> // 添加一个 Button 到列表固定头 llss.Button { button -> // 设置按钮内容 button.setContent { bs -> // 添加文本到按钮中 bs.Text { text -> // 设置按钮中文本显示的内容 text.setText("添加项目") } } // 4. 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick { state.add("+++++") } } } // 3. 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, null, null) { llss, index, item -> // 状态列表中每个元素显示一个简单的 Text 组件 llss.Text { text -> text.setModifier { it.height { d -> d.fromInt(200) } } // 设置 Text 组件显示的内容 text.setText(item) } } } } } // 启动一个Activity用于显示脚本界面 $activity.start()
// 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create(slot => { // 1. 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 const state = slot.mutableStateListOf($iterables.listOf("初始数据")); slot.LazyColumn(lc => { lc.setModifier(it => it.fillMaxWidth(1.0)); // 2. 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state); // 设置懒列表内容 lc.setContent(lls => { // 设置列表固定头 lls.stickyHeader(null, null, (llss, index) => { // 添加一个 Button 到列表固定头 llss.Button(button => { // 设置按钮内容 button.setContent(bs => { // 添加文本到按钮中 bs.Text(text => { // 设置按钮中文本显示的内容 text.setText("添加项目"); }); }); // 4. 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick(() => state.add("+++++")); }); }); // 3. 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, null, null, (llss, index, item) => { // 状态列表中每个元素显示一个简单的 Text 组件 llss.Text(text => { text.setModifier(it => { it.height(d => d.fromInt(200)); }); // 设置 Text 组件显示的内容 text.setText(item); }); }); }); }); }); // 启动一个Activity用于显示脚本界面 $activity.start();
-- 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView:create(function(slot) -- 1. 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 local state = slot:mutableStateListOf(_iterables:listOf("初始数据")) slot:LazyColumn(function(lc) lc:setModifier(function(it) it:fillMaxWidth(1) end) -- 2. 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc:trackSingleState(state) -- 设置懒列表内容 lc:setContent(function(lls) -- 设置列表固定头 lls:stickyHeader(nil, nil, function(llss, index) -- 添加一个 Button 到列表固定头 llss:Button(function(button) -- 设置按钮内容 button:setContent(function(bs) -- 添加文本到按钮中 bs:Text(function(text) -- 设置按钮中文本显示的内容 text:setText("添加项目") end) end) -- 4. 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button:setOnClick(function() state:add("+++++") end) end) end) -- 3. 将状态列表中的数据显示到 LazyColumn 中 lls:itemsIndexed(state, nil, nil, function(llss, index, item) -- 状态列表中每个元素显示一个简单的 Text 组件 llss:Text(function(text) text:setModifier(function(it) it:height(function(d) return d:fromInt(200) end) end) -- 设置 Text 组件显示的内容 text:setText(item) end) end) end) end) end) -- 启动一个Activity用于显示脚本界面 _activity:start()
<?php /** @var m8test_java\com\m8test\script\core\api\ui\compose\ComposeView $composeView */ global $composeView; /** @var m8test_java\com\m8test\script\core\api\ui\Activity $activity */ global $activity; /** @var m8test_java\com\m8test\script\core\api\collections\Iterables $iterables */ global $iterables; // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView->create(function ($slot) { global $iterables; // 1. 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 $state = $slot->mutableStateListOf($iterables->listOf(javaString("初始数据"))); $slot->LazyColumn(function ($lc) use ($state) { $lc->setModifier(function ($it) { $it->fillMaxWidth(1.0); }); // 2. 跟踪状态列表,当列表增删改时 LazyColumn 会重组 $lc->trackSingleState($state); // 设置懒列表内容 $lc->setContent(function ($lls) use ($state) { // 设置列表固定头 $lls->stickyHeader(null, null, function ($llss, $index) use ($state) { // 添加一个 Button 到列表固定头 $llss->Button(function ($button) use ($state) { // 设置按钮内容 $button->setContent(function ($bs) { // 添加文本到按钮中 $bs->Text(function ($text) { // 设置按钮中文本显示的内容 $text->setText(javaString("添加项目")); }); }); // 4. 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 $button->setOnClick(function () use ($state) { $state->add(javaString("+++++")); }); }); }); // 3. 将状态列表中的数据显示到 LazyColumn 中 $lls->itemsIndexed($state, null, null, function ($llss, $index, $item) { // 状态列表中每个元素显示一个简单的 Text 组件 $llss->Text(function ($text) use ($item) { $text->setModifier(function ($it) { $it->height(function ($d) { return $d->fromInt(200); }); }); // 设置 Text 组件显示的内容 $text->setText($item); }); }); }); }); }); // 启动一个Activity用于显示脚本界面 $activity->start();
# 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _activity from m8test_java.com.m8test.script.GlobalVariables import _composeView from m8test_java.com.m8test.script.GlobalVariables import _iterables # 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView.create(lambda slot: ( # 1. 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 (state := slot.mutableStateListOf(_iterables.listOf("初始数据"))), slot.LazyColumn(lambda lc: ( lc.setModifier(lambda it: it.fillMaxWidth(1.0)), # 2. 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state), # 设置懒列表内容 lc.setContent(lambda lls: ( # 设置列表固定头 lls.stickyHeader(None, None, lambda llss, index: ( # 添加一个 Button 到列表固定头 llss.Button(lambda button: ( # 设置按钮内容 button.setContent(lambda bs: ( # 添加文本到按钮中 bs.Text(lambda text: ( # 设置按钮中文本显示的内容 text.setText("添加项目") )) )), # 4. 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick(lambda: state.add("+++++")) )) )), # 3. 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, None, None, lambda llss, index, item: ( # 状态列表中每个元素显示一个简单的 Text 组件 llss.Text(lambda text: ( text.setModifier(lambda it: ( it.height(lambda d: d.fromInt(200)) )), # 设置 Text 组件显示的内容 text.setText(item) )) )) )) )) )) # 启动一个Activity用于显示脚本界面 _activity.start()
# encoding: utf-8 # 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create do |slot| # 1. 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 state = slot.mutableStateListOf($iterables.listOf("初始数据")) slot.LazyColumn do |lc| lc.setModifier { |it| it.fillMaxWidth(1.0) } # 2. 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state) # 设置懒列表内容 lc.setContent do |lls| # 设置列表固定头 lls.stickyHeader(nil, nil) do |llss, index| # 添加一个 Button 到列表固定头 llss.Button do |button| # 设置按钮内容 button.setContent do |bs| # 添加文本到按钮中 bs.Text do |text| # 设置按钮中文本显示的内容 text.setText("添加项目") end end # 4. 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick { state.add("+++++") } end end # 3. 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, nil, nil) do |llss, index, item| # 状态列表中每个元素显示一个简单的 Text 组件 llss.Text do |text| text.setModifier do |it| it.height { |d| d.fromInt(200) } end # 设置 Text 组件显示的内容 text.setText(item) end end end end end # 启动一个Activity用于显示脚本界面 $activity.start()

聚合状态

有些组件包含多个状态,M8Test 将其封装为聚合状态。你可以通过聚合状态对象修改所需的状态,例如:

import com.m8test.script.GlobalVariables.* fun side1Run() { // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView.create { // 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 val state = mutableStateListOf(_iterables.listOf("初始数据")) // 1. 创建一个懒列表状态,用于控制 LazyColumn val lazyState = newLazyListState {} LazyColumn { setModifier { fillMaxWidth(1f) } // 2. 设置懒列表的状态 setState(lazyState) // 跟踪状态列表,当列表增删改时 LazyColumn 会重组 trackSingleState(state) // 设置懒列表内容 setContent { // 设置列表固定头 stickyHeader(null, null) { index -> // 添加一个 Button 到列表固定头 Button { // 设置按钮内容 setContent { // 添加文本到按钮中 Text { // trackAggregatedState(lazyState) // 这个代码会跟踪 lazyState 中所有的状态, 当任意一个状态发生改变时 Text 都会重组 trackSingleState(lazyState.getFirstVisibleItemIndexState()) // 3. 这个代码仅仅会跟踪 lazyState 的第一个可见项目索引, 当该状态发生改变时 Text 会重组, 推荐使用这种方式, 只跟踪用到的状态 // 4. 使用跟踪的状态值,如果该状态发生改变,那么 Text 文本会更新 setText("添加项目${lazyState.getFirstVisibleItemIndexState().getValue()}") } } // 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 setOnClick { state.add("+++++") } } } // 将状态列表中的数据显示到 LazyColumn 中 itemsIndexed(state, null, null) { index, item -> // 状态列表中每个元素显示一个简单的 Text 组件 Text { setModifier { height { d -> d.fromInt(200) } } // 设置 Text 组件显示的内容 setText(item) } } } } } // 启动一个Activity用于显示脚本界面 _activity.start() } //-m8test-remove side1Run();
// 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create { slot -> // 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 def state = slot.mutableStateListOf($iterables.listOf("初始数据")) // 1. 创建一个懒列表状态,用于控制 LazyColumn def lazyState = slot.newLazyListState {} slot.LazyColumn { lc -> lc.setModifier { it.fillMaxWidth(1f) } // 2. 设置懒列表的状态 lc.setState(lazyState) // 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state) // 设置懒列表内容 lc.setContent { lls -> // 设置列表固定头 lls.stickyHeader(null, null) { llss, index -> // 添加一个 Button 到列表固定头 llss.Button { button -> // 设置按钮内容 button.setContent { bs -> // 添加文本到按钮中 bs.Text { text -> // text.trackAggregatedState(lazyState) // 这个代码会跟踪 lazyState 中所有的状态, 当任意一个状态发生改变时 Text 都会重组 text.trackSingleState(lazyState.getFirstVisibleItemIndexState()) // 3. 这个代码仅仅会跟踪 lazyState 的第一个可见项目索引, 当该状态发生改变时 Text 会重组, 推荐使用这种方式, 只跟踪用到的状态 // 4. 使用跟踪的状态值,如果该状态发生改变,那么 Text 文本会更新 text.setText("添加项目" + lazyState.getFirstVisibleItemIndexState().getValue()) } } // 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick { state.add("+++++") } } } // 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, null, null) { llss, index, item -> // 状态列表中每个元素显示一个简单的 Text 组件 llss.Text { text -> text.setModifier { it.height { d -> d.fromInt(200) } } // 设置 Text 组件显示的内容 text.setText(item) } } } } } // 启动一个Activity用于显示脚本界面 $activity.start()
// 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create(slot => { // 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 const state = slot.mutableStateListOf($iterables.listOf("初始数据")); // 1. 创建一个懒列表状态,用于控制 LazyColumn const lazyState = slot.newLazyListState(() => {}); slot.LazyColumn(lc => { lc.setModifier(it => it.fillMaxWidth(1)); // 2. 设置懒列表的状态 lc.setState(lazyState); // 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state); // 设置懒列表内容 lc.setContent(lls => { // 设置列表固定头 lls.stickyHeader(null, null, (llss, index) => { // 添加一个 Button 到列表固定头 llss.Button(button => { // 设置按钮内容 button.setContent(bs => { // 添加文本到按钮中 bs.Text(text => { // text.trackAggregatedState(lazyState) // 这个代码会跟踪 lazyState 中所有的状态, 当任意一个状态发生改变时 Text 都会重组 text.trackSingleState(lazyState.getFirstVisibleItemIndexState()); // 3. 这个代码仅仅会跟踪 lazyState 的第一个可见项目索引, 当该状态发生改变时 Text 会重组, 推荐使用这种方式, 只跟踪用到的状态 // 4. 使用跟踪的状态值,如果该状态发生改变,那么 Text 文本会更新 text.setText("添加项目" + lazyState.getFirstVisibleItemIndexState().getValue()); }); }); // 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick(() => state.add("+++++")); }); }); // 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, null, null, (llss, index, item) => { // 状态列表中每个元素显示一个简单的 Text 组件 llss.Text(text => { text.setModifier(it => { it.height(d => d.fromInt(200)); }); // 设置 Text 组件显示的内容 text.setText(item); }); }); }); }); }); // 启动一个Activity用于显示脚本界面 $activity.start();
-- 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView:create(function(slot) -- 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 local state = slot:mutableStateListOf(_iterables:listOf("初始数据")) -- 1. 创建一个懒列表状态,用于控制 LazyColumn local lazyState = slot:newLazyListState(function() end) slot:LazyColumn(function(lc) lc:setModifier(function(it) return it:fillMaxWidth(1.0) end) -- 2. 设置懒列表的状态 lc:setState(lazyState) -- 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc:trackSingleState(state) -- 设置懒列表内容 lc:setContent(function(lls) -- 设置列表固定头 lls:stickyHeader(nil, nil, function(llss, index) -- 添加一个 Button 到列表固定头 llss:Button(function(button) -- 设置按钮内容 button:setContent(function(bs) -- 添加文本到按钮中 bs:Text(function(text) -- text:trackAggregatedState(lazyState) -- 这个代码会跟踪 lazyState 中所有的状态, 当任意一个状态发生改变时 Text 都会重组 text:trackSingleState(lazyState:getFirstVisibleItemIndexState()) -- 3. 这个代码仅仅会跟踪 lazyState 的第一个可见项目索引, 当该状态发生改变时 Text 会重组, 推荐使用这种方式, 只跟踪用到的状态 -- 4. 使用跟踪的状态值,如果该状态发生改变,那么 Text 文本会更新 text:setText("添加项目" .. tostring(lazyState:getFirstVisibleItemIndexState():getValue())) end) end) -- 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button:setOnClick(function() state:add("+++++") end) end) end) -- 将状态列表中的数据显示到 LazyColumn 中 lls:itemsIndexed(state, nil, nil, function(llss, index, item) -- 状态列表中每个元素显示一个简单的 Text 组件 llss:Text(function(text) text:setModifier(function(it) return it:height(function(d) return d:fromInt(200) end) end) -- 设置 Text 组件显示的内容 text:setText(item) end) end) end) end) end) -- 启动一个Activity用于显示脚本界面 _activity:start()
<?php /** @var m8test_java\com\m8test\script\core\api\ui\compose\ComposeView $composeView */ global $composeView; /** @var m8test_java\com\m8test\script\core\api\ui\Activity $activity */ global $activity; /** @var m8test_java\com\m8test\script\core\api\collections\Iterables $iterables */ global $iterables; // 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView->create(function ($slot) { global $iterables; // 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 $state = $slot->mutableStateListOf($iterables->listOf(javaString("初始数据"))); // 1. 创建一个懒列表状态,用于控制 LazyColumn $lazyState = $slot->newLazyListState(function () { }); $slot->LazyColumn(function ($lc) use ($lazyState, $state) { $lc->setModifier(function ($it) { $it->fillMaxWidth(1.0); }); // 2. 设置懒列表的状态 $lc->setState($lazyState); // 跟踪状态列表,当列表增删改时 LazyColumn 会重组 $lc->trackSingleState($state); // 设置懒列表内容 $lc->setContent(function ($lls) use ($lazyState, $state) { // 设置列表固定头 $lls->stickyHeader(null, null, function ($llss, $index) use ($lazyState, $state) { // 添加一个 Button 到列表固定头 $llss->Button(function ($button) use ($lazyState, $state) { // 设置按钮内容 $button->setContent(function ($bs) use ($lazyState) { // 添加文本到按钮中 $bs->Text(function ($text) use ($lazyState) { // $text->trackAggregatedState($lazyState); // 这个代码会跟踪 lazyState 中所有的状态, 当任意一个状态发生改变时 Text 都会重组 $text->trackSingleState($lazyState->getFirstVisibleItemIndexState()); // 3. 这个代码仅仅会跟踪 lazyState 的第一个可见项目索引, 当该状态发生改变时 Text 会重组, 推荐使用这种方式, 只跟踪用到的状态 // 4. 使用跟踪的状态值,如果该状态发生改变,那么 Text 文本会更新 $text->setText(javaString("添加项目") . $lazyState->getFirstVisibleItemIndexState()->getValue()); }); }); // 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 $button->setOnClick(function () use ($state) { $state->add(javaString("+++++")); }); }); }); // 将状态列表中的数据显示到 LazyColumn 中 $lls->itemsIndexed($state, null, null, function ($llss, $index, $item) { // 状态列表中每个元素显示一个简单的 Text 组件 $llss->Text(function ($text) use ($item) { $text->setModifier(function ($it) { $it->height(function ($d) { return $d->fromInt(200); }); }); // 设置 Text 组件显示的内容 $text->setText($item); }); }); }); }); }); // 启动一个Activity用于显示脚本界面 $activity->start();
# 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _composeView from m8test_java.com.m8test.script.GlobalVariables import _iterables from m8test_java.com.m8test.script.GlobalVariables import _activity # 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 _composeView.create(lambda slot: ( # 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 (state := slot.mutableStateListOf(_iterables.listOf("初始数据"))), # 1. 创建一个懒列表状态,用于控制 LazyColumn # [修复] 这里的lambda需要接收一个参数但可以忽略它 (lazyState := slot.newLazyListState(lambda _: None)), slot.LazyColumn(lambda lc: ( lc.setModifier(lambda it: it.fillMaxWidth(1.0)), # 2. 设置懒列表的状态 lc.setState(lazyState), # 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state), # 设置懒列表内容 lc.setContent(lambda lls: ( # 设置列表固定头 lls.stickyHeader(None, None, lambda llss, index: ( # 添加一个 Button 到列表固定头 llss.Button(lambda button: ( # 设置按钮内容 button.setContent(lambda bs: ( # 添加文本到按钮中 bs.Text(lambda text: ( # text.trackAggregatedState(lazyState) # 这个代码会跟踪 lazyState 中所有的状态, 当任意一个状态发生改变时 Text 都会重组 text.trackSingleState(lazyState.getFirstVisibleItemIndexState()), # 3. 这个代码仅仅会跟踪 lazyState 的第一个可见项目索引, 当该状态发生改变时 Text 会重组, 推荐使用这种方式, 只跟踪用到的状态 # 4. 使用跟踪的状态值,如果该状态发生改变,那么 Text 文本会更新 text.setText("添加项目" + str(lazyState.getFirstVisibleItemIndexState().getValue())) )) )), # 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick(lambda: state.add("+++++")) )) )), # 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, None, None, lambda llss, index, item: ( # 状态列表中每个元素显示一个简单的 Text 组件 llss.Text(lambda text: ( text.setModifier(lambda it: ( it.height(lambda d: d.fromInt(200)) )), # 设置 Text 组件显示的内容 text.setText(item) )) )) )) )) )) # 启动一个Activity用于显示脚本界面 _activity.start()
# encoding: utf-8 # 创建一个 ComposeView, 可以通过声明式ui创建脚本界面 $composeView.create do |slot| # 创建一个状态列表,向 LazyColumn 提供数据,当其中的元素发生改变(增删改)时,用到该状态列表的组件会重组 state = slot.mutableStateListOf($iterables.listOf("初始数据")) # 1. 创建一个懒列表状态,用于控制 LazyColumn lazyState = slot.newLazyListState {} slot.LazyColumn do |lc| lc.setModifier { |it| it.fillMaxWidth(1.0) } # 2. 设置懒列表的状态 lc.setState(lazyState) # 跟踪状态列表,当列表增删改时 LazyColumn 会重组 lc.trackSingleState(state) # 设置懒列表内容 lc.setContent do |lls| # 设置列表固定头 lls.stickyHeader(nil, nil) do |llss, index| # 添加一个 Button 到列表固定头 llss.Button do |button| # 设置按钮内容 button.setContent do |bs| # 添加文本到按钮中 bs.Text do |text| # text.trackAggregatedState(lazyState) // 这个代码会跟踪 lazyState 中所有的状态, 当任意一个状态发生改变时 Text 都会重组 text.trackSingleState(lazyState.getFirstVisibleItemIndexState()) # 3. 这个代码仅仅会跟踪 lazyState 的第一个可见项目索引, 当该状态发生改变时 Text 会重组, 推荐使用这种方式, 只跟踪用到的状态 # 4. 使用跟踪的状态值,如果该状态发生改变,那么 Text 文本会更新 text.setText("添加项目" + lazyState.getFirstVisibleItemIndexState().getValue().to_s) end end # 设置按钮点击事件,当按钮被点击时会将内容添加到状态列表中,此时 LazyColumn 会重组,并显示新的内容 button.setOnClick { state.add("+++++") } end end # 将状态列表中的数据显示到 LazyColumn 中 lls.itemsIndexed(state, nil, nil) do |llss, index, item| # 状态列表中每个元素显示一个简单的 Text 组件 llss.Text do |text| text.setModifier do |it| it.height { |d| d.fromInt(200) } end # 设置 Text 组件显示的内容 text.setText(item) end end end end end # 启动一个Activity用于显示脚本界面 $activity.start()
09 December 2025