Moai soft keyboard for Android now available


If you followed my Moai tutorial series, you may recall in this post I mentioned that Android keyboard support currently didn’t exist, although there is an effort underway to fix that.  Well, a user over on the Moai forums got sick of waiting and implemented a soft keyboard using MoaiGui, which I covered in this post.


It is written as a Lua module and the only dependency is you need to pass in your Moaigui object.  Here is the code:

--utility function  function distance ( x1, y1, x2, y2 )          return math.sqrt ((( x2 - x1 ) ^ 2 ) + (( y2 - y1 ) ^ 2 ))  end    k = {}    local kboard = nil  local keysWide = 1  local keySize = 5  local boardHeight = keySize  local left = 50 - keySize/2  local top = 100  local xpos = left  local ypos = top  local rowCount = 0  local speed = 1000  local textbox = nil    --release all gui objects  k.destroyKeyboard = function (self, gui)          if kboard ~= nil then                  for k, v in pairs(kboard) do                          gui:destroyWindow(v)                  end                  kboard = nil          end  end    --setup a new keyboard, starting with only 1 row  k.createKeyboard = function (self, gui, charsWide)          if kboard ~= nil then destroyKeyboard(gui) end          kboard = {}          keysWide = charsWide          boardHeight = keySize          left = 50 - keySize*charsWide/2          xpos = left          top = 100          ypos = top          rowCount = 0  end         local function keyClick(event, data)          --give focus to selected textbox so that it receives the keypress          if textbox ~= nil then data.g:setFocus(textbox) end          --pass keypress to gui          data.g:injectKeyDown(data.character)          data.g:injectKeyUp(data.character)  end         k.addKey = function (self, gui, char)          if kboard == nil then return end          --empty string indicates skipping a key slot          if char ~= "" then                  kboard[char] = gui:createButton()                  kboard[char]:setPos(xpos, ypos)                  kboard[char]:setDim(keySize, keySize)                  kboard[char]:setText(char)                  data = {}                    data.g = gui                  if char == "<" then                          data.character = 8 --backspace                  else                          data.character = string.byte(char) --ascii value of character                  end                    kboard[char]:registerEventHandler(kboard[char].EVENT_BUTTON_CLICK, nil, keyClick, data)          end          --increment to next key in row          rowCount = rowCount + 1          xpos = xpos + keySize          if rowCount >= keysWide then                  --new row                  xpos = left                  ypos = ypos + keySize                  boardHeight = boardHeight + keySize                  rowCount = 0          end  end         --moves the key to its place at the bottom of the screen (or off the screen if show=false).  --NOTE: only returns once the move has finished  local function moveKey(key, show)          local x, y = key:getPos()          --move onto the screen          local newy = y - boardHeight          --move off the screen          if not show then newy = y + boardHeight end          --not really the best way of getting the target location, but the easiest/quickest solution          key:setPos(x, newy)          local tx, ty = key._rootProp:getLoc()          key:setPos(x,y)          --calculate a travel time relevant to the distance being traveled          local travelTime = distance(x, y, x, newy) / speed            MOAIThread.blockOnAction(key._rootProp:seekLoc(tx, ty, travelTime, MOAIEaseType.LINEAR))          --the seekLoc only moves the prop, the prop container is not aware of the move, so tell it.          key:setPos(x, newy)  end         --moves all keys to the desired location  k.showKeyboard = function (self, gui, show)          if kboard == nil then return end          --only need to pass in show when you want to hide the keyboard          if show == nil then show = true end          for k, v in pairs(kboard) do                  --move keys in separate threads        , v, show)          end  end         k.hideKeyboard = function (self, gui)          self:showKeyboard(gui, false)  end    k.setTextbox = function(self, tbox)          textbox = tbox  end    return k     


And here is some code demonstrating the keyboard in action:


local kb = require "keyboard"    kb:createKeyboard(gui, 11)  keys = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "<",          "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "",          "", "a", "s", "d", "f", "g", "h", "j", "k", "l",  "",          "", "", "z", "x", "c", "v", "b", "n", "m"}  for k, v in pairs(keys) do          kb:addKey(gui, v)  end    kb:showKeyboard(gui)    local editBox = nil  local function handleEditBoxGainFocus(self, event)          self._cursorPos = #self._internalText + 1          self:_addCursor()          kb:setTextbox(editBox)          return self:_baseHandleGainFocus(event)  end    editBox = gui:createEditBox()  editBox :setPos(40, 30)  editBox :setDim(20, 5)  editBox :setText("")  editBox ._onHandleGainFocus = handleEditBoxGainFocus     


None of this code is mine, all of the credit goes to lancew over on the Moai forums.  The only thing I have done is slightly changed the formatting to make it a bit more legible. You can read the original thread right here.


Great work Lance!

Programming Moai

Scroll to Top