位元詩人 [Solar2D] 程式設計教學:使用 TableView 建立長清單

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

[注意事項] Corona 已改名為 Solar2D

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

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

{{< figure src="img/corona-sdk/tableview.png" alt="Solar2D 的 TableView 範例" class="phone" >}}

本範例是一個武器店的武器清單,這個清單的內容會隨機產生。我們一開始設置武器等級的清單,分為破舊 (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

由於清單的總量會比畫面上的數量還多,Solar2D 程式會追蹤目前實際的清單的行數。我們每次在捲動時,其實 Solar2D 程式都會重繪一次清單,造成視覺上有清單移動的感覺。所以,我們要根據目前 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 函式以重整清單內容。至於製作按鈕部分的程式碼先前已有類似例子,此處不重覆展示。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。