App Inventor 2 TableView与SQLite数据展示教程

« 返回首页

概述

已有文档:sqlite_tutorial.md 介绍了SQLite扩展,dynamic_components.md 介绍了动态创建组件。本文聚焦用表格形式展示数据库内容。

App Inventor没有内置TableView

App Inventor没有原生的表格组件。展示表格数据有以下方案:

方案 难度 排版 推荐度
TableArrangement ⭐ 固定行列 ⭐⭐
动态创建布局 ⭐⭐⭐ 灵活 ⭐⭐⭐
WebView + HTML表格 ⭐⭐ 最好 ⭐⭐⭐⭐⭐
Table扩展 ⭐⭐ 好 ⭐⭐⭐⭐
ListView ⭐ 单列 ⭐⭐⭐

方案一:WebView + HTML表格(推荐)

HTML模板

<!-- table_view.html -->
<style>
table { width:100%; border-collapse:collapse; font-size:14px; }
th { background:#4CAF50; color:white; padding:8px; text-align:left; }
td { padding:8px; border-bottom:1px solid #ddd; }
tr:nth-child(even) { background:#f9f9f9; }
tr:active { background:#e0e0e0; }
</style>
<table id="table">
  <thead id="header"></thead>
  <tbody id="body"></tbody>
</table>
<script>
setInterval(function(){
  var msg = window.AppInventor.getWebViewString();
  if(msg && msg !== ""){
    try {
      var data = JSON.parse(msg);
      if(data.cmd === "setData"){
        var cols = data.columns;
        var rows = data.rows;
        document.getElementById('header').innerHTML = '<tr>' + cols.map(function(c){return '<th>'+c+'</th>'}).join('') + '</tr>';
        document.getElementById('body').innerHTML = rows.map(function(row, i){
          return '<tr onclick="selectRow('+i+')">' + cols.map(function(c){return '<td>'+(row[c]||'')+'</td>'}).join('') + '</tr>';
        }).join('');
      }
    } catch(e) { window.AppInventor.setWebViewString("ERROR:"+e.message); }
  }
},100);
function selectRow(i){
  window.AppInventor.setWebViewString("SELECT:"+i);
}
</script>

App Inventor积木块

when Screen1.Initialize() {
  Web浏览器1.HomeUrl = "file:///android_asset/table_view.html"
  SQLite1.OpenDatabase("myapp.db")
}

when 按钮_加载数据.Click() {
  SQLite1.QuerySQL("SELECT * FROM users")
}

when SQLite1.QueryResult(结果) {
  var 列名 = make_list("id", "name", "phone", "email")
  var JSON = join("{\"cmd\":\"setData\",\"columns\":[\"id\",\"name\",\"phone\",\"email\"],\"rows\":", Web1.JsonTextEncode(结果), "}")
  Web浏览器1.WebViewString = JSON
}

when Web浏览器1.WebViewStringChange(value) {
  if (starts_with(value, "SELECT:")) {
    var 行索引 = replace_all(value, "SELECT:", "")
    标签_选中.Text = join("选中第", 行索引 + 1, "行")
  }
}

方案二:Table扩展

extensions/Table.md 已有文档。基本用法:

when Screen1.Initialize() {
  Table1.SetColumnNames(make_list("ID", "姓名", "电话", "邮箱"))
  Table1.SetColumnWidths(make_list(50, 120, 120, 180))
}

when 按钮_加载数据.Click() {
  SQLite1.QuerySQL("SELECT * FROM users")
}

when SQLite1.QueryResult(结果) {
  Table1.ClearData()
  var i = 1
  while (i <= length_of_list(结果)) {
    var 记录 = select_list_item(结果, i)
    Table1.AddRow(make_list(
      get_dictionary_value("id", 记录),
      get_dictionary_value("name", 记录),
      get_dictionary_value("phone", 记录),
      get_dictionary_value("email", 记录)
    ))
    i = i + 1
  }
}

方案三:动态创建布局

参考 dynamic_components.md,使用CompCreator扩展:

when SQLite1.QueryResult(结果) {
  // 先清除之前的行
  清除表格()
  
  // 创建表头
  CompCreator1.CreateLabel(
    HorizontalArrangement_表头, "header",
    "ID    | 姓名    | 电话    | 邮箱", 14, -16777216, true)
  
  // 创建数据行
  var i = 1
  while (i <= length_of_list(结果)) {
    var 记录 = select_list_item(结果, i)
    var 显示 = join(get_dictionary_value("id", 记录), " | ",
      get_dictionary_value("name", 记录), " | ",
      get_dictionary_value("phone", 记录), " | ",
      get_dictionary_value("email", 记录))
    CompCreator1.CreateLabel(
      VerticalArrangement_表格, join("row", i),
      显示, 12, -12303292, false)
    i = i + 1
  }
}

常见问题

Q1: 表格太宽显示不全?

WebView方案可以设置CSS让表格自适应宽度:

table { width:100%; font-size:12px; }
td { word-break:break-all; }

Q2: 数据量大时卡顿?

  • 分页查询:SELECT * FROM users LIMIT 20 OFFSET 0
  • 使用WebView方案性能最好
  • 避免一次加载上千行

总结

方案 推荐度 性能 适用
WebView + HTML ⭐⭐⭐⭐⭐ 好 大数据量
Table扩展 ⭐⭐⭐⭐ 中 中等数据
动态组件 ⭐⭐⭐ 差 小数据量
文档反馈