Titanium Community Questions & Answer Archive

We felt that 6+ years of knowledge should not die so this is the Titanium Community Questions & Answer Archive

Android window focus/blur event handling diffs

I am completely confused as to how Android handles window and field focus and blur events vs. iOS. If I set up a simple window with one text input field, and set focus and blur event handlers on both the text field and the window, and just open the window, here's how the two OSs work:

iOS:

[INFO] WINDOW FOCUS event: src=[object TiUIWindow], typ=focus, val=undefined

This is as I expect.

Android:

[INFO] [397,1067849] TEXT FOCUS event: src=[Ti.UI.TextField], typ=focus, val=
[INFO] [4,1067853] WINDOW FOCUS event: src=[Ti.UI.TextField], typ=focus, val=
[INFO] [5,1067858] WINDOW FOCUS event: src=[Ti.UI.Window], typ=focus, val=null

I get a focus on the text field, a window focus coming from the text field, and then another window focus coming from the window itself(!). I understand that the order of the info messages may not be correct due to the async nature of event handlers, but why are so many events coming out? Does Android pass along focus/blur events to all listeners regardless of who processes one?

Further, if I add a 'return' event handler on the text field in Android (for the keyboard Done or Return button) to call the '.blur()' event handler explicitly (otherwise the keyboard closes but no event is detected), I get this interesting mix of events:

[INFO] [3154,1564119] TEXT RETURN event: src=[Ti.UI.TextField], typ=return, val=
[INFO] [38,1564157] TEXT FOCUS event: src=[Ti.UI.TextField], typ=focus, val=
[INFO] [9,1564166] WINDOW FOCUS event: src=[Ti.UI.TextField], typ=focus, val=
[INFO] [9,1564175] TEXT BLUR event: src=[Ti.UI.TextField], typ=blur, val=
[INFO] [23,1564198] WINDOW BLUR event: src=[Ti.UI.TextField], typ=blur, val=

In iOS, I get one TEXT BLUR event. Here is a pastie of the sample code showing the above behavior.

Is there a way to suppress further event handling by returning a true or false value, or some other workaround to get the behavior I need?

Running 1.5.1 and Android SDK 2.2; iOS 4.2.

— asked January 17th 2011 by Richard Baughman
  • android
  • blur
  • event
  • focus
  • window
3 Comments
  • As an aside, I would refrain from using numbers as booleans in JavaScript - here's a nice article on "Truthy" and "Falsy" values in JavaScript, which may help in explaining the somewhat confusing nature of true and false values in JS.

    — commented January 20th 2011 by Kevin Whinnery
  • Thanks for the heads up, Kevin.

    — commented January 20th 2011 by Richard Baughman
  • SDK 2.1.1, TextFields still fire 'focus' on main window

    — commented August 8th 2012 by Marco Seguri

3 Answers

  • Accepted Answer

    a new better solution / workaround…

    when spawning the new child window, I now add a 'close' event listener to the new window that calls the function I wanted called on the return 'focus' event… so it's not the focus event calling it at all, but it gets done anyway by the window closing…

    and thanks Kevin and the rest of the team. I know you've got a beast of a job, and balancing cross-platform stability vs. us all clamoring for the newest features must be quite a challenge. I still appreciate the tool immensely, (couldn't do what I'm doing without it!) but just wanted to put my opinion forward that I, for one, would prefer cross-platform uniformity and stability over cutting-edge features.

    Thanks!
    David

    — answered January 22nd 2011 by david hoare
    permalink
    1 Comment
    • David: This works great on both platforms, and is very easy - just didn't think of this approach. For other viewers, the code is:

      var mywin = Ti.UI.currentWindow;
      var mytab = Ti.UI.currentTab;
      var subwin = Ti.UI.createWindow(...);
      mytab.open(subwin, {animated: true});
      subwin.addEventListener('close', function() { mywin.close() });
      

      Thanks!

      — commented January 22nd 2011 by Richard Baughman
  • I was experiencing difficulties with the window.focus event in android, and here's how I solved it - perhaps it will help others… but it's still messed up!

    I was opening a new window (used for setting prefs) and wanted an event to run when the user closed the prefs window, and returned to the original one.
    The focus event was firing on iOS, but not android. IF, however, I added an automatic call to the focus() event on any object in the new prefs window – I focused on the table being used for choices eg. tableview.focus() – when I returned to the original calling window, the window.focus event fired!

    of course, THIS solution DIDN'T work on iOS - threw an error: tableview.focus() [undefinend] is not a function. Same error doing it to the window, to a button, to a textfield, or view… don't know what I was doing wrong there…

    BUT… if the prefs window included ANOTHER window (with an admob function in it, which basically created a webview pointing to the admob code), then when I exit back to the original calling window the Android and iOS 'focus' event gets called…

    hope that helps!
    David

    BTW - - WHY is it so difficult to do cross-platform development on a platform that exists to make cross-platform development easier? Every time I've got something working on one platform, it DOESN'T work on the other. It's almost more time-consuming than coding them separately! :-)

    — answered January 20th 2011 by david hoare
    permalink
    2 Comments
    • I'm with you on that sentiment. We are disappointed in the amount of work we have to do to make a working iOS app function properly on Android (and in a somewhat diminished fashion at that). I understand the complexities of dealing with "native" behavior and keeping both sides happy, but perhaps Appcelerator could look at providing one or more "compatibility" flags/levels that would favor cross-platform commonality over native but incompatible behavior, such as that described above with interrupt handling. We (and I'm sure many others) would at a minimum love to have a flag for each project that, if set, says "make interrupt handling match" (based on iOS, of course). This would allow developers to choose which behavior they want, and Appcel to surround all their interrupt handling adjustments with conditionals, isolating potential backwards-compatible issues.

      — commented January 20th 2011 by Richard Baughman
    • Normalizing APIs across platforms is definitely one of our biggest challenges, given that we're trying to create a meta framework over the top of native frameworks that behave very differently. This might be akin to cross-browser concerns on the web for the developer, which we know can be annoying - we're trying to stamp out the differences as quickly as we can.

      — commented January 20th 2011 by Kevin Whinnery
  • Hi Richard,

    Event propagation does work differently in iOS versus Android. In Android, events tend to bubble all the way up through the hierarchy, and we don't currently have a way to cancel the rest of the chain. That's an area where we're looking to become more consistent in 1.6.0 (consistent behavior cross-platform, and sane interpretations of when an event should be triggered on an object).

    In the meantime, you have found the best way to react to this in your code. Window focus is particularly chatty, so it's important to check the source of the event to determine how the event was fired.

    — answered January 20th 2011 by Kevin Whinnery
    permalink
    0 Comments
The ownership of individual contributions to this community generated content is retained by the authors of their contributions.
All trademarks remain the property of the respective owner.