位元詩人 [Solar2D] 程式設計教學:練習進度條 (ProgressView)、步進器 (Stepper)、開關 (Switch) 等元件的使用方式

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

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

本文仍然是元件的練習,學習的重點在操作 ProgressView (進度條)、Stepper (步進器) 和 Switch (開關) 等元件。ProgressView 是圖形介面程式中的進度條 (progress bar),常常用來顯示程式運行的進度。Stepper 可遞增 (或減) 程式內部的某項狀態。Switch 則像是開關,只有開 (on) 和關 (off) 兩種狀態。

由於範例稍長,我們將完整範例放在這裡,本文僅節錄部分內容。

本範例程式開啟的畫面如下:

{{< figure src="/img/corona-sdk/progressview-stepper-switch.png" alt="在 Solar2D 程式中,藉由按鈕觸發事件" class="phone" >}}

一開始,我們建立 progressView 物件,該物件內部的計數器為 progressprogress 的數字為介於 0.01.0 間的浮點數:

-- Init the internal counter of the progress view.
local progress = 0

-- Init the ProgressView object.
local progressView =
  widget.newProgressView(
    {
      x = display.contentWidth * 0.47,
      y = display.contentHeight * 0.36,
      width = display.contentWidth * 0.7,
      isAnimated = false
    }
  )

-- Set the initial progress for the ProgressView object.
progressView:setProgress(progress)

我們另外宣告了幾個變數。由於 Lua 本身的特性,我們很難直接從程式碼看出每個變數的意義,這大概只能在必要時加強註解。stepper 是一個 Stepper 物件的變數,因為待會有幾個 event handler 會呼叫此變數,故在此提前宣告。count 是用來調整 progress 的計數器,step 是用來調整 stepper 內部狀態的計數器,而 isRunning 則是用來調整一個 Switch 的內部狀態的旗標:

-- Init some parameters.
local stepper
local step = 0
local count = 0
local isRunning = true

我們在此建立按鈕物件 btnProgress 和其 event handler btnProgressListener。在此 event handler 中,我們要先確認 isRunning 的狀態為 true,若為真,則啟動一個 timertimer 的參數為時間差、一個回呼函式 (callback) 和執行次數,我們將時間差調到 5 ms,讓 progressView 的進度條跑快一點;執行次數和 count 的值相反,當 count1 時,執行 100 次,而 count 較高時,則執行次數會變少;真正執行程式行為的程式碼位於回呼函式中,在每輪調整 progressView 的值,看起來就有移動的效果,另外同步 stepper 內部的狀態:

-- Declare the listener to the progress Button object.
local function btnProgressListener(event)
  if isRunning and event.phase == "ended" then
    timer.performWithDelay(
      5,
      function()
        if count < 100 then
          count = count + 1
        end

        progress = count / 100
        progressView:setProgress(progress)

        if count % 10 == 0 then
          step = count / 10
          stepper:setValue(step)
        end
      end,
      101 - count
    )
  end
end

-- Init the progress Button object.
local btnProgress =
  widget.newButton(
    {
      left = display.contentWidth * 0.12,
      top = display.contentHeight * 0.44,
      label = "Run",
      isEnabled = true,
      onEvent = btnProgressListener,
      shape = "roundedRect",
      width = 100,
      labelColor = {
        default = {0 / 255, 0 / 255, 0 / 255},
        over = {0 / 255, 0 / 255, 0 / 255}
      },
      fillColor = {
        default = {180 / 255, 255 / 255, 255 / 255},
        over = {110 / 255, 255 / 255, 255 / 255}
      }
    }
  )

btnRollback 基本上做類似的事情,只是方向相反,此處不重覆貼出程式碼。

接著,我們建立 stepper 物件及其 event handler onStepperPress。在建立 Stepper 物件時,要設置其 initialValue (起始值)、minValue (最小值)、maxValue (最大值),之後再調整 Stepper 時,就是... Stepper 的 event handler 要處理四個階段,分別是 "increment" (遞增)、"decrement" (遞減)、"minLimit" (極小值)、"maxLimit" (極大值)。程式碼如下:

-- Declare the listener to Stepper object.
local function onStepperPress(event)
  if isRunning then
    if event.phase == "increment" then
      step = step + 1
      count = (step / 10) * 100
      stepper:setValue(step)
      progress = step / 10
      progressView:setProgress(progress)
    elseif event.phase == "decrement" then
      step = step - 1
      count = (step / 10) * 100
      stepper:setValue(step)
      progress = step / 10
      progressView:setProgress(progress)
    elseif event.phase == "minLimit" then
    -- Pass.
    elseif event.phase == "maxLimit" then
    -- Pass.
    end
  end
end

-- Init the Stepper object.
stepper =
  widget.newStepper(
    {
      x = display.contentWidth * 0.35,
      y = display.contentHeight * 0.64,
      initialValue = step,
      minimumValue = 0,
      maximumValue = 10,
      onPress = onStepperPress
    }
  )

在本範例中,onOff 元件的作用在於控制其他的元件是否有作用,當 onOff 元件為關時,其他元件不會有反應,調控的方法是調整 isRunning 這個內部的旗標:

-- Declare the listener to on-off Switch object.
local function onOffPress(event)
  local switch = event.target

  if switch.isOn then
    isRunning = false
  else
    isRunning = true
  end
end

-- Init the on-off Switch object.
local onOff =
  widget.newSwitch(
    {
      x = display.contentWidth * 0.65,
      y = display.contentHeight * 0.64,
      initialSwitchState = true,
      onPress = onOffPress
    }
  )
關於作者

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

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