Corona SDK 程式設計教學:TableView

PUBLISHED ON DEC 2, 2018 — MOBILE

    TableView 的用意在於建立清單,和 PickerWheel 類似,TableView 的清單可以捲動,藉以節省行動裝置的畫面。我們將完整的程式碼放在這裡,本文僅節錄部分內容。

    本範例程式的示意圖如下:

    Corona SDK 的 TableView 範例

    本範例是一個武器店的武器清單,這個清單的內容會隨機產生。我們一開始設置武器等級的清單,分為破舊 (shabby)、普通 (common)、優良 (uncommon)、精良 (rare)、史詩 (epic)、傳說 (legendary) 等數個等級:

    註:參考自魔獸世界 (World of Warcraft)。

    -- Init ranks with different weight.
    local ranks = {}
    
    local weight = 1
    
    for i = 1, 15 do
      ranks[weight] = "shabby"
      weight = weight + 1
    end
    
    for i = 1, 50 do
      ranks[weight] = "common"
      weight = weight + 1
    end
    
    for i = 1, 10 do
      ranks[weight] = "uncommon"
      weight = weight + 1
    end
    
    for i = 1, 5 do
      ranks[weight] = "rare"
      weight = weight + 1
    end
    
    for i = 1, 2 do
      ranks[weight] = "epic"
      weight = weight + 1
    end
    
    ranks[weight] = "legendary"

    讀者可發現,普通和優良的數量放比較多,而精良以上的等級數量就比較少,利用這種方式造成機率不平均,製造物以稀為貴的概念。

    接著,產生武器類別的清單:

    local weapons = {
      "gloves",
      "dagger",
      "sword",
      "great sword",
      "mace",
      "great mace",
      "axe",
      "great axe",
      "polearms",
    }

    我們讓每種武器出現的機率平均,故沒有調整清單。

    接著,我們根據上述兩種清單的選項組合後,產生實際列出的武器清單:

    -- Init a seed by system time.
    math.randomseed(os.time())
    
    -- Create a random list of weapons.
    local weaponLists
    
    local function reloadList ()
      weaponLists = {}
    
      for i = 1, 10 do
        iRank = math.random(1, #ranks)
        iWeapon = math.random(1, #weapons)
    
        weaponLists[i] = ranks[iRank] .. " " .. weapons[iWeapon]
      end
    end
    
    -- Init the list.
    reloadList()

    由於我們的清單之後會動態改變,故我們將產生清單的程式碼獨立出來,寫在一個函式中。

    接著,我們撰寫 tableView 物件的事件處理器:

    local function onRowRender (event)
      local row = event.row
    
      -- Cache the row "contentWidth" and "contentHeight" because the row bounds can change as children objects are added
      local rowHeight = row.contentHeight
      local rowWidth = row.contentWidth
    
      local rowTitle = display.newText( row, weaponLists[row.index], 0, 0, nil, 17 )
      rowTitle:setFillColor( 0 )
    
      -- Align the label left and vertically centered
      rowTitle.anchorX = 30
      rowTitle.x = rowWidth * 0.8
      rowTitle.y = rowHeight * 0.5
    end

    由於清單的總量會比畫面上的數量還多,Corona 程式會追蹤目前實際的清單的行數。我們每次在捲動時,其實 Corona 程式都會重繪一次清單,造成視覺上有清單移動的感覺。所以,我們要根據目前 row 所在的行數 (即 row.index) 繪製相對應的內容。

    接著,製作 tableView 物件:

    local tableView = widget.newTableView(
      {
        x = display.contentWidth * 0.5,
        y = display.contentHeight * 0.5,
        width = display.contentWidth * 0.9,
        height = display.contentHeight * 0.5,
        onRowRender = onRowRender,
      }
    )
    
    for i = 1, 10 do
      tableView:insertRow({})
    end

    一開始插入列 (row) 時,不需插入實際的內容,而是插入每一列相關的設定。以本例來說,我們直接用預設值,故插入空的表 (table)。有關設置列的方式,可參考這裡

    最後,我們建立一個按鈕,按按鈕時會重新建立新的武器清單:

    local function btnListener (event)
      if event.phase == "ended" then
        reloadList()
        tableView:reloadData()
      end
    end
    
    -- Create a button here.

    本段程式碼的重點在於更動清單內容後,要呼叫 reloadData 函式以重整清單內容。至於製作按鈕部分的程式碼先前已有類似例子,此處不重覆展示。