Skip to content

Commit

Permalink
[TIMOB-26167] Android: Fixed TextField/TextArea focus/blur handling. (#…
Browse files Browse the repository at this point in the history
…10149)

- Fixed bug where TextField/TextArea cannot be edited while in a ScrollView. (Introduced in 7.3.0.)
- Fixed [TIMOB-26172] where a view's "focus" and "blur" events should not bubble to parent views, like iOS.
- TextField/TextArea and other focusable views no longer receive focus by default when opening a window, like iOS.
  * Resolves tickets [TIMOB-8637], [TIMOB-24138], and [TIMOB-25819].
  • Loading branch information
jquick-axway authored and hansemannn committed Jul 3, 2018
1 parent 880d8eb commit 6c7918a
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,6 @@ public TiVerticalScrollView(Context context, LayoutArrangement arrangement)
}
}
setScrollBarStyle(SCROLLBARS_INSIDE_OVERLAY);
setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
layout = new TiScrollViewLayout(context, arrangement);
FrameLayout.LayoutParams params =
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
Expand Down Expand Up @@ -479,7 +478,6 @@ public TiHorizontalScrollView(Context context, LayoutArrangement arrangement)
super(context);
setScrollBarStyle(SCROLLBARS_INSIDE_OVERLAY);
setScrollContainer(true);
setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);

// Set up nested scrolling. Improves "SwipeRefreshLayout" touch interception handling.
// Note: On Android 5.0 and above, all views support nested child scrolling. We just need to enable it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,18 +422,24 @@ public void run()
// Subclasses can override to provide a custom layout
protected View createLayout()
{
// Set up the view's layout.
LayoutArrangement arrangement = LayoutArrangement.DEFAULT;

String layoutFromIntent = getIntentString(TiC.INTENT_PROPERTY_LAYOUT, "");
if (layoutFromIntent.equals(TiC.LAYOUT_HORIZONTAL)) {
arrangement = LayoutArrangement.HORIZONTAL;

} else if (layoutFromIntent.equals(TiC.LAYOUT_VERTICAL)) {
arrangement = LayoutArrangement.VERTICAL;
}

// set to null for now, this will get set correctly in setWindowProxy()
return new TiCompositeLayout(this, arrangement, null);
// Create the root view to be used by the activity.
// - Set the layout's proxy to null for now. Will be set later via setWindowProxy().
// - Make it focusable so Android won't auto-focus on the first focusable child view in the window.
// This makes it match iOS' behavior where no child view has the focus when a window is opened.
TiCompositeLayout compositeLayout = new TiCompositeLayout(this, arrangement, null);
compositeLayout.setFocusable(true);
compositeLayout.setFocusableInTouchMode(true);
compositeLayout.setDescendantFocusability(TiCompositeLayout.FOCUS_BEFORE_DESCENDANTS);
return compositeLayout;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1186,19 +1186,24 @@ private void applyTouchFeedback(@NonNull Integer backgroundColor, @Nullable Inte
nativeView.setBackground(rippleDrawable);
}

@Override
public void onFocusChange(final View v, boolean hasFocus)
{
// Show/hide the virtual keyboard.
if (hasFocus) {
TiMessenger.postOnMain(new Runnable() {
@Override
public void run()
{
TiUIHelper.requestSoftInputChange(proxy, v);
}
});
fireEvent(TiC.EVENT_FOCUS, getFocusEventObject(hasFocus));
} else {
fireEvent(TiC.EVENT_BLUR, getFocusEventObject(hasFocus));
}

// Fire a focus/blur event. (This event should not be bubbled.)
boolean isBubbled = false;
String eventName = hasFocus ? TiC.EVENT_FOCUS : TiC.EVENT_BLUR;
fireEvent(eventName, getFocusEventObject(hasFocus), isBubbled);
}

protected KrollDict getFocusEventObject(boolean hasFocus)
Expand Down
63 changes: 63 additions & 0 deletions tests/Resources/ti.ui.textfield.addontest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Appcelerator Titanium Mobile
* Copyright (c) 2011-Present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
/* eslint-env mocha */
/* global Ti, Titanium */
/* eslint no-unused-expressions: "off" */
'use strict';
var should = require('./utilities/assertions');

describe('Titanium.UI.TextField', function () {
var win;

afterEach(function () {
if (win) {
win.close();
}
win = null;
});

// TextField must not receive focus by default upon opening a window.
it('focus-win-open', function (finish) {
var textField;
this.timeout(5000);

win = Ti.UI.createWindow();
textField = Ti.UI.createTextField();
textField.addEventListener('focus', function () {
// This should never happen.
finish(new Error('TextField wrongly received focus on open.'));
});
win.add(textField);
win.addEventListener('postlayout', function () {
// If we made it this far, assume TextField did not receive focus.
finish();
});
win.open();
});

// The "focus" and "blur" events are not supposed to bubble up the view hierarchy.
it('focus-blur-bubbles', function (finish) {
var textField;
this.timeout(5000);

win = Ti.UI.createWindow();
textField = Ti.UI.createTextField();
textField.addEventListener('focus', function (e) {
should(e.bubbles).be.eql(false);
textField.blur();
});
textField.addEventListener('blur', function (e) {
should(e.bubbles).be.eql(false);
finish();
});
win.add(textField);
win.addEventListener('open', function () {
textField.focus();
});
win.open();
});
});

0 comments on commit 6c7918a

Please sign in to comment.