Unusual field/backspaceKey behavior

The place to discuss anything and everything about running your LiveCode on Android

Moderators: Klaus, FourthWorld, heatherlaine, kevinmiller, robinmiller

Post Reply
atmosk
Posts: 32
Joined: Wed Feb 27, 2013 5:50 pm

Unusual field/backspaceKey behavior

Post by atmosk » Tue Jan 24, 2017 12:23 pm

I've been messing with android stuff for a good long while now and currently working on another android project and again stumbled upon the same problem.

In short, the backspaceKey/message doesn't consistently trigger with non-native fields.
Tried on multiple different livecode versions getting the same results.
(Yes, I should use the mobilecontrols, but they're just such an horrible approach especially when regular fields do everything and more with fraction of the effort.)

I wouldn't even bother mentioning if it flat out didn't work or random works/doesn't work, but I noticed it's actually consistent.
If you type 1 key, you need to press the software backspace once (doesn't trigger messages or erase) and once more to start erasing.
Same if you type 2 keys, you'll need to press twice with no reaction and then it'll start erasing (you have to press backspace the same amount of times you typed keys to start erasing).

As if there is some additional message muting keys being added after the field string, "abc---".

So, it looks a whole lot like a "simple" bug that would make regular fields completely viable and I'm wondering if anyone has overcome this before or if anyone has a clue where the keyboard (messages/)behavior is defined?

Any input is appreciated!

LiveCode_Panos
Livecode Staff Member
Livecode Staff Member
Posts: 695
Joined: Fri Feb 06, 2015 4:03 pm

Re: Unusual field/backspaceKey behavior

Post by LiveCode_Panos » Tue Jan 24, 2017 12:44 pm

Hi atmosk,

If I remember correctly, I had the same problem some time ago. The issue seemed to be related to the version of the "Google Keyboard" I had installed in my Android phone, and it was fixed once I installed the latest version.

Do you have the most recent version of "Android Keyboard" installed in this device? This is how to check:

1. Launch the Play Store App
2. Tap on the top left "hamburger" icon and select "My Apps and Games"
3. Scroll down until you find the "Google Keyboard" app.
4. If you see an "Update" option, I suggest to do so.

Best regards,
Panos
--

atmosk
Posts: 32
Joined: Wed Feb 27, 2013 5:50 pm

Re: Unusual field/backspaceKey behavior

Post by atmosk » Tue Jan 24, 2017 1:42 pm

That's what I've tried as well, but that's fairly inconsistent also. With the updated google keyboard (gboard nowadays apparently) the above behavior persists on all of my livecode android projects. If I uninstall all the updates from the gboard, I get completely normal behavior in a blank + 2 field controls project while getting no backspace action on the other one.
I circumvented this problem before by using "Go Keyboard" which worked fine until it decided not to work as well.

Bizarre stuff, but gonna keep trying in hopes of stumbling on something that'll work.

rmuzzini
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 60
Joined: Mon Oct 08, 2012 11:30 am

Re: Unusual field/backspaceKey behavior

Post by rmuzzini » Thu Feb 09, 2017 2:37 pm

it's not a matter of "google keyboard", panos.
it's something more complex, related to various bugs still open (http://quality.livecode.com/show_bug.cgi?id=18876 - http://quality.livecode.com/show_bug.cgi?id=11489 - http://quality.livecode.com/show_bug.cgi?id=13229)

and it is related to the "SMART TYPING" features.

it happens on android, no matter which version it is, 2.3, 4.1, 5…
no matter the LC version you used to compile (7, 8, 9…).
no matter "G keyboard" is installed or not.

recipe:
create a stack with one standard LC field
compile for android
run the app on device with "SMART TYPING > Auto check spelling" ON
write something into the field
case 1:
- write a known (i.e. "correct") word, "house" for example
- put a SPACE after the word
expected result: "house "
observed result: "house " -> OK

case 2
- write an unknown (i.e. "misspelled" or a name) word, "panos" for example
- put a SPACE after the word
expected result: "panos "
observed result: "panospanos" -> NOT OK -> app unusable.

as mentioned above, in my opinion it is linked to another bug related to backspace key, reported by atmosk here.
if you have "SMART TYPING - Predictvive text" -> ON then here's what happens:
- write a word, any.
- hit the backspace to cancel last char
expected result: last char is erased
observed result: you have to hit again the backspace. and, the longer is the word the more times you have to hit the backspace before starting to erase chars.
to fix this one you have to tell users to turn the "Predictvive text" feature OFF.
NOTE: that occurs on SAMSUNG tablets. on ASUS tablets to fix this one you have to ACTIVATE the "Predictvive text" feature, on the contrary…

both misbehaviors well reported in bug http://quality.livecode.com/show_bug.cgi?id=18876
and, so to speak…,bug http://quality.livecode.com/show_bug.cgi?id=13229 was reported 2,5 years ago. :-(
i don't know why other LC developers don't mourn about this. android apps are pretty useless, in such conditions.

please, panos… :-)
do your best so this bug be fixed quickly…
i (we) count on you…
:-)

regards

atmosk
Posts: 32
Joined: Wed Feb 27, 2013 5:50 pm

Re: Unusual field/backspaceKey behavior

Post by atmosk » Mon Feb 13, 2017 1:34 pm

Yup, I'm guessing (based on gut feels) that it has something to do with how the non-native fields pass information to the keyboard or how the soft keyboard logics pass their 'info' to the fields. Since it seems like the non-native fields create a new "variable" for their strings every time it get's focus while not considering what already existed and that probably causes the other issues as well (if what I'm feelstimating is even remotely correct).
(Btw, I'm dealing with lenovo tablets and neither 'fix' managed to make it work consistently.)

Regardless, the fix might come never and even then it'd require moving to a new version which is a huge gamble because every new version of livecode (for me) requires setting up all the android dependencies from scratch and then it'll work for only that version, not the older ones.

So I just went with the native fields, kinda.
Wrote a script that overlays all the fields on that specific card with mobileControls if you add a custom prop "androidInput" and set it to true.

Code: Select all

--card script
/*on preOpenCard
   if the environment is "mobile" then 
      set the visible of fld "Mobiler" to false
      send "OverlayFields" to fld "Mobiler"
   end if
end preOpenCard

on closeCard
   if the environment is "mobile" then 
      send "DeleteFields" to fld "Mobiler"
   end if   
end closeCard*/

--non-native field script sample
/*on focusIn
answer "inputBeginEditing/focusIn"
end focusIn

on focusOut
answer "inputEndEditing/focusOut"
end focusOut

on textChanged
answer "textChanged" && the innerText of me
end textChanged

on rawKeyDown k
   if (k = "65293") then answer "rawKeyDown" && the innerText of me 
end rawKeyDown*/

local controlAssociations

on DeleteFields
   if (the last line of the keys of controlAssociations is not 0) then
      repeat with n = 1 to (the num lines in the keys of controlAssociations/3)
         set the text of controlAssociations[n,"non-native"] to the innerText of controlAssociations[n,"non-native"]
         mobileControlDelete controlAssociations[n,"native"]
      end repeat
   end if
   put empty into controlAssociations
end DeleteFields

on OverlayFields
   lock screen
   if (the environment is not "mobile") then exit OverlayFields
   if (controlAssociations is not empty) then
      answer "Fields created already"
      exit OverlayFields
   end if
   put 1 into counter
   repeat with x = 1 to the num of controls in this card
      if ("field" is among the words of the long name of control x of this card AND \ 
            the control x of this card is not me AND \
            the androidInput of control x of this card is true) then
         --create the overlay
         if (the textSize of control x of this card is empty) then put 12 into tHeight
         else put the textSize of control x of this card into tHeight
         if (the height of control x of this card > tHeight*1.9) then
            put "multiline" into inputType
            put "default" into returnKeyType
         else
            put "input" into inputType
            put "done" into returnKeyType
         end if
         
         put "inputControl_" & counter into controlAssociations[counter, "native"]
         put the long id of control x of this card into controlAssociations[counter, "non-native"]
         get inputCreator("inputControl_" & counter, inputType, controlAssociations[counter, "non-native"], "FALSE", "TRUE", "FALSE", "none", "default", returnKeyType, "red", "left", tHeight)
         set the innerText of controlAssociations[counter, "non-native"] to the text of controlAssociations[counter,"non-native"]
         mobileControlSet controlAssociations[counter,"native"], "text", the text of controlAssociations[counter, "non-native"]
         set the text of controlAssociations[counter,"non-native"] to empty
         if (the script of control x of this card is not empty) then
            put the script of control x of this card into tempScript
            put "0000" into controlAssociations[counter, "messages"]
            -- check whether to pass focusIn
            if (matchText(tempScript, "on focusIn")) then put "1" into char 1 of controlAssociations[counter, "messages"]
            -- check whether to pass inputEndEditing/focusOut
            if (matchText(tempScript, "on focusOut")) then put "1" into char 2 of controlAssociations[counter, "messages"]
            -- check whether to textChanged/textChanged
            if (matchText(tempScript, "on textChanged")) then put "1" into char 3 of controlAssociations[counter, "messages"]
            -- check whether to pass returnKey/rawKeyDown
            if (matchText(tempScript, "on rawKeyDown")) then put "1" into char 4 of controlAssociations[counter, "messages"]
            
         end if
         add 1 to counter
      end if
   end repeat
   unlock screen
end OverlayFields

--maps to "focusIn"
/*on focusIn
if (the evinronment is "mobile") then put the innerText of me into theText
else put the text of me into theText
--do  things where "theText" is the text of the fld
end focusIn*/
on inputBeginEditing
   if (the last line of the keys of controlAssociations is not 0) then
      repeat with n = 1 to (the num lines in the keys of controlAssociations/3)
         if (mobileControlTarget() is controlAssociations[n,"native"] AND \
               char 1 of controlAssociations[n,"messages"] is "1") then
            put mobileControlGet(controlAssociations[n, "native"], "text") into k
            set the innerText of controlAssociations[n,"non-native"] to k
            send "focusIn" to controlAssociations[n,"non-native"]
         end if
      end repeat
   end if
end inputBeginEditing

--maps to "focusOut"
/*on focusOut
if (the evinronment is "mobile") then put the innerText of me into theText
else put the text of me into theText
--do  things where "theText" is the text of the fld
end focusOut*/
on inputEndEditing
   if (the last line of the keys of controlAssociations is not 0) then
      repeat with n = 1 to (the num lines in the keys of controlAssociations/3)
         if (mobileControlTarget() is controlAssociations[n,"native"] AND \
               char 2 of controlAssociations[n,"messages"] is "1") then
            put mobileControlGet(controlAssociations[n, "native"], "text") into k
            set the innerText of controlAssociations[n,"non-native"] to k
            send "focusOut" to controlAssociations[n,"non-native"]
         end if
      end repeat
   end if
end inputEndEditing

--maps to "textChanged"
/*on textChanged
if (the evinronment is "mobile") then put the innerText of me into theText
else put the text of me into theText
--do  things where "theText" is the text of the fld
end textChanged*/
on inputTextChanged
   if (the last line of the keys of controlAssociations is not 0) then
      repeat with n = 1 to (the num lines in the keys of controlAssociations/3)
         if (mobileControlTarget() is controlAssociations[n,"native"] AND \
               char 3 of controlAssociations[n,"messages"] is "1") then
            put mobileControlGet(controlAssociations[n, "native"], "text") into k
            set the innerText of controlAssociations[n,"non-native"] to k
            send "textChanged" to controlAssociations[n,"non-native"]
         end if
      end repeat
   end if
end inputTextChanged

--maps to "rawKeyDown 65293"
/*on rawKeyDown k --non-native control script
if (k = "65293") then
   --do things
end if
end rawKeyDown*/
on inputReturnKey
   if (the last line of the keys of controlAssociations is not 0) then
      repeat with n = 1 to (the num lines in the keys of controlAssociations/3)
         if (mobileControlTarget() is controlAssociations[n,"native"] AND \
               char 4 of controlAssociations[n,"messages"] is "1") then
            put mobileControlGet(controlAssociations[n, "native"], "text") into k
            set the innerText of controlAssociations[n,"non-native"] to k
            send "rawKeyDown" && "65293" to controlAssociations[n,"non-native"]
         end if
      end repeat
   end if
end inputReturnKey

--slightly modified version of http://forums.livecode.com/viewtopic.php?f=49&t=26810#p139691 by "quailcreek"
function inputCreator pName, pKind, pRect, pAutoClear, pAutoFit, pAutoCap, pAutoCorrect, pKeyboardType, pReturnKey, pBackgroundColor, ptextAlign, pfontSize
   mobileControlCreate pKind, pName
   mobileControlSet pName, "visible", true
   if (pKind is "input") then
      put the rect of pRect into tRect
      put item 2 of tRect - 6 into item 2 of tRect
      put item 4 of tRect + 8 into item 4 of tRect
      mobileControlSet pName, "rect", tRect
   else
      mobileControlSet pName, "rect", the rect of pRect
   end if 
   mobileControlSet pName, "opaque", false
   mobileControlSet pName, "autoFit", pAutoFit
   mobileControlSet pName, "autoClear", pAutoClear
   mobileControlSet pName, "autoCapitalizationType", pAutoCap
   mobileControlSet pName, "autoCorrectionType", pAutoCorrect
   mobileControlSet pName, "keyboardType", pKeyboardType
   mobileControlSet pName, "returnKeyType", pReturnKey
   mobileControlSet pName, "clearButtonMode", "while editing"
   mobileControlSet pName, "borderStyle", "none"
   mobileControlSet pName, "fontName", "Arial"
   mobileControlSet pName, "textColor", the foregroundColor of pRect
   mobileControlSet pName, "backgroundColor", pBackgroundColor
   mobileControlSet pName, "textAlign", ptextAlign
   mobileControlSet pName, "Alpha", 0
   mobilecontrolSet pName, "fontSize", pfontSize
   if (pKind is "input") then 
      mobilecontrolSet pName, "scrollingEnabled", false
      mobileControlSet pName, "multiline", false
   end if
end inputCreator


I plan on finishing it properly, but just in case I don't I'm posting it here for future people.

Anywho, the basic gist of it is that it finds the fields you want to 'mobilize' (on the card you place the "mobiler" fld) and then creates the input controls and passes on the messages to the (parent) non-native fields. This way you can test out whether something works in the ide and the script takes care of the message handling while running it on android.

To use it, you c+p the card stuff to your card script, the fld stuff to your field that you've added the custom prop (androidInput = true) or

Code: Select all

set the androidInput of fld "Field" to true
and create a new fld named "Mobiler" to which you c+p the whole thing as it's what creates the Inputs, receives all the messages and will pass the messages to the non-native fields.
Attachments
androidBackKeyTest.rar
Sample stack for the above script
(3.4 KiB) Downloaded 158 times

rmuzzini
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 60
Joined: Mon Oct 08, 2012 11:30 am

Re: Unusual field/backspaceKey behavior

Post by rmuzzini » Mon Feb 13, 2017 2:54 pm

thank you for sharing this, atmork.
quite impressive.
not sure if i can use that in my apps (the ones i'm developing right now, at least), 'cause i rely a lot on fields custom properties (things like pMandatory, pMaxChar, pMinChar, etc…) and on behaviors more than fields script (i am used to set a field behavior according to its type: alpha, numbers, integers, email address, etc., so that a "beep!" alerts user the input data is not allowed, and it's easy to control this by behaviors: 1 button for x fields). and, last but not least, i usually check the field position relative to virtual keyboard, moving the field while editing if it's hidden… all easy, using LC fields. simplicity is the most valuable reason of using LC.

about the behaviors maybe it could be enough to change your

Code: Select all

if (the script of control x of this card is not empty) then
with

Code: Select all

  switch (the behavior of control x)
      case empty
         put the script of control x of this card into theScript
         break
      default
         put the script of (the behavior of control x of this card) into theScript
         break
   end switch
   if theScript is not empty then
assuming you DO NOT use both field script AND behavior, of course…

for the properties and related alert messages in case of illegal inputs probably it could be simple to tune your script-mapping to get same… well, behaviors… :-)

but after having did all this stuff (so to speak: one of the my current app is a data collector with pages of data inputs for around 300 different fields of different types - dates, integers, text-only, and so on - to be saved/retrieved in/from sqlite db, and some with auto-calculation depending of the values entered in other fields), the answer is: why i'd have to use liveCode for developing if i must use native fields and set up this huge workaround?
:-/

this is my feeling today ("LC i love you but i hate you but i love you but…"). maybe tomorrow i'll wake up with a more positive mood and i'll try to give my contribute to your excellent workaround.
:)

regards.

Post Reply

Return to “Android Deployment”