Disabling a native text field, making it not editable?

Hello,

The user has previously entered some text in a view and when he later returns to that view, the text is displayed. However, by tapping an edit icon, I want the user to be able to edit the text. If the text is displayed as a simple Text object, I need to hide it and display a TextField. That will cause a “jolt” in the text that does not look nice. What I want is that when the user taps the edit icon, the cursor and the keyboard just appears smoothly but no jolts in the text.

Hence, I need to have the text displayed as a TextField already from the beginning and then just enable tit for editing when the user taps the edit icon.

Is there a way to make a TextField non-editable or can I achieve the above in some other way?

You can use your various events that come from editing your testField and if you have a flag saying the field is locked, just ignore the edits. Though visually hiding/showing the textField over top of a display.newText would work too. I don’t think it will be that jarring of an experience in particular if they are having to press an “edit” button.

Rob

@Rob:

I’m not quite sure how you mean “ignoring the edits”. The listener that I can register for a TextField can not prevent the cursor nor the keyboard from appearing regardless of what events I use…

The (ugly) workaround that I am using now is to create a transparent, non-editable TextBox on top of the TextField. That TextBox then prevents any touch events from reaching the TextField below.

Each time the user tries to make a change in the text field, you get an “editing” event. Your text field should have a listener function that receives these events. If you detect an “editing” event and you have the field non-editable, just set the text back to what it was before the edit happens. 

Rob

@Rob:

Technically that would work, yes, but it would not look good from a user friendliness perspective if there is a keyboard that pops up but you can’t use it. Personally, I would think: if I am not allowed to enter text at this point, then why display the keyboard at all?

Just call native.setKeyboardFocus(nil) in the began phase of the text field listener if you want to disable it. The keyboard will be dismissed before it shows. Meaning it will never show.

@ojnab:

Never thought of that, thanks! :slight_smile:

@divergent monkey … you asked the same question I was going to ask today!

My use:   displaying some URLs, one per line (one per textfield).  If a line has a URL, I want a single tap to select it, *NOT edit it.

If it’s empty, I want the single tap to start editing the field.

I was about to try the invisible boxes over the non-empty fields … I’ll try @ojnab’s technique.  thanks!

For other posters here:  “ignore the editing events” is more complicated than it sounds. 

The first tap gets an editing “begin” event, *but* tapping outside the field later … ever … gets an “ended” event. 

At present, I will get that dangling ‘end’ event later, which I have to code for :slight_smile:

Thinking it through, I’m concerned that although setting keyboard focus to nil might work for most cases, what about for systems with attached physical keyboards?  I suspect touching a physical key after the initial tap would still send an editing event.  So, guess I’ll have to code for that, too :slight_smile:

@sieler2: I thought long about this and finally decided to go for the transparent, non-editable TextBox. The main reason for this is exactly what you say: I wanted to avoid triggering an event altogether since it might create some weird effects on some devices. The transparent TextBox solution has worked fine this far.

After doing more testing, I’m going to do that to.  I tried the focus, and had problems.

In particular, for reasons I don’t understand, after I bring the 8 textfields (or textboxes for that matter) back to visibility and

then tap on one of them (any one) … and then tap outside all of them (to go back to my main screen), I get between one

and five “begin” and “ended” events the next time I tap anywhere on the screen … sort of like someone was saying "gosh,

since *any* text field had become active/selected, then the *all* are active".  (Well, that does explain what I see :slight_smile:

So…more work, but it should be a better result.

@sieler2,
 
Sounds like you’re using a global listener?
 
I suggest using a local listener, one per text field object.  That way the code is associated directly with that object ONLY.

 local function textListener( event ) end local tmp = native.newTextField( 150, 150, 180, 30 ) tmp.userInput = textListener tmp:addEventListener( "userInput" ) local tmp = native.newTextField( 150, 200, 180, 30 ) tmp.userInput = textListener tmp:addEventListener( "userInput" ) local tmp = native.newTextField( 150, 250, 180, 30 ) tmp.userInput = textListener tmp:addEventListener( "userInput" ) ...

Tip: With a little ingenuity you can emulate the ‘isEditable’ attribute of textBox but for a text field.

I recently answered a question about ‘restoring a text field value’ if the user edits it, then cancels the edit.  The code for that answer is here:

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/01/cancelText.zip

You can extend this code to ‘lock’ and ‘unlock’ a text field’s edit-ability.

Why are you not using a display.newText() with a touch or tap handler?  Using a text field for something like a URL to be tapped on seems like making it overly complex.

Rob

display,newText is for displaying text, not editing it, right?

I want to display a list of URLs (up to about 7 of them), one per line (one per field).

If the user taps on a URL, I want to load/play it.

If the user taps on ‘Edit’, and then taps on a URL, I want to let them edit it, including tapping from URL to URL to URL to edit as they please (until they tap outside a text box, or on “Back” ).

If the user taps on an empty/blank URL (without tapping ‘Edit’ first), I’d like to fall into edit mode.

I.e., I want to minimize taps, and maximize friendliness.

That means, at least at first glance, it would be convenient to have a textfield (or box), not a newText.

Hope that helps explain my goal!

(Sure, I could have two button by each URL: play and edit … but a small button is much harder to hit for a finger

than a large URL text field is … and that implies a modal approach.)

@rominggamer … you actually have only one listener, shared amongst the fields.

My code is similar … 7 calls to newTextField:

 for inx = 1, max\_urls do textfield = native.newTextField (x, y, 200, 30) remember\_thing (thing\_textfield, textfield, "text field # " .. tostring (inx)) textfield.which = inx textfield:addEventListener ("userInput", bh\_edit\_url) y = y + 40 end textfield = nil

The “remember_thing” is my version of scenes, I guess.  It tracks all display objects I create, and I can flag each

object as to which state(s) they’re visible in .  Late, a switch_to_state (n) automatically sets appropriate items

to be invisible, and others to be visible.

I tried the isEditable, with textBox, but still had the problem of dangling events.

Sorry I missed the bit about wanting to edit it. I saw that you did not want to have taps edit it.

Rob

@sieler2 - It isn’t actually what I would call shared. It is defined once and assigned to each object.

When the objects call the listener, the call is specific to that object only.  The function itself is not aware of the other objects till they call it.

What I seems you have going on is multiple (accumulated) listeners getting one object’s events, or the events from all text field objects going to a single listener. I think it is the prior.

I see this problem a lot when people use a global listener incorrectly and/or don’t remove them.

Regardless. I am sure you can implement a locking feature. Hopefully you have this worked out soon.

Cheers,

Ed

Curious, I was also going to ask this question.

So I only intervened to say that I think it is useful to add isEditable also for textField in the future.