Corona SDK 程式設計教學:ProgressView、Stepper、Switch

PUBLISHED ON SEP 13, 2018 — MOBILE

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

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

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

    在 Corona 程式中,藉由按鈕觸發事件

    一開始,我們建立 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
        }
      )