Commit dee80872 authored by Wenyu Fu's avatar Wenyu Fu Committed by Commit Bot

Handle focus and enabled state changes for RadioButtonWithEditText

Add focus & setEnabled related enhancement to RadioButtonWithEditText and
add some test.

Change-Id: Iad713ddaa108f084e9f98e882bcd6e6135384756
Bug: 1036470
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1991717
Commit-Queue: Wenyu Fu <wenyufu@chromium.org>
Auto-Submit: Wenyu Fu <wenyufu@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732548}
parent bf928ee4
......@@ -24,6 +24,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/radio_button"
android:cursorVisible="false"
android:textAppearance="@style/TextAppearance.BlackTitle1"
android:inputType="text" />
......
......@@ -237,6 +237,15 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
mGroup = group;
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
mDescription.setEnabled(enabled);
mPrimary.setEnabled(enabled);
mRadioButton.setEnabled(enabled);
}
@Override
protected Parcelable onSaveInstanceState() {
// Since this View is designed to be used multiple times in the same layout and contains
......
......@@ -12,6 +12,8 @@ import android.widget.RadioGroup;
import androidx.annotation.VisibleForTesting;
import org.chromium.ui.base.ViewUtils;
import java.util.ArrayList;
import java.util.List;
......@@ -52,7 +54,6 @@ public final class RadioButtonWithDescriptionLayout
private final int mMarginBetweenRows;
private final List<RadioButtonWithDescription> mRadioButtonsWithDescriptions;
private OnCheckedChangeListener mOnCheckedChangeListener;
private View mAccessoryView;
public RadioButtonWithDescriptionLayout(Context context) {
this(context, null);
......@@ -156,6 +157,14 @@ public final class RadioButtonWithDescriptionLayout
mRadioButtonsWithDescriptions.add(radioButton);
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
for (int i = 0; i < getChildCount(); i++) {
ViewUtils.setEnabledRecursive(getChildAt(i), enabled);
}
}
/**
* Marks a RadioButton child as being checked.
*
......
......@@ -306,6 +306,44 @@ public class RadioButtonWithDescriptionLayoutTest {
Assert.assertTrue(b4.isChecked());
}
@Test
@SmallTest
public void testSetEnable() {
View content = LayoutInflater.from(mContext).inflate(
R.layout.radio_button_with_description_layout_test, null, false);
RadioButtonWithDescriptionLayout layout =
content.findViewById(R.id.test_radio_button_layout);
RadioButtonWithDescription b1 = content.findViewById(R.id.test_radio_description_1);
RadioButtonWithDescription b2 = content.findViewById(R.id.test_radio_description_2);
RadioButtonWithEditText b3 = content.findViewById(R.id.test_radio_edit_text_1);
RadioButtonWithEditText b4 = content.findViewById(R.id.test_radio_edit_text_2);
final TextView textView1 = new TextView(mContext);
final TextView textView3 = new TextView(mContext);
layout.attachAccessoryView(textView1, b1);
layout.attachAccessoryView(textView3, b3);
layout.setEnabled(false);
Assert.assertFalse(b1.isEnabled());
Assert.assertFalse(b2.isEnabled());
Assert.assertFalse(b3.isEnabled());
Assert.assertFalse(b4.isEnabled());
Assert.assertFalse(textView1.isEnabled());
Assert.assertFalse(textView3.isEnabled());
layout.setEnabled(true);
Assert.assertTrue(b1.isEnabled());
Assert.assertTrue(b2.isEnabled());
Assert.assertTrue(b3.isEnabled());
Assert.assertTrue(b4.isEnabled());
Assert.assertTrue(textView1.isEnabled());
Assert.assertTrue(textView3.isEnabled());
}
private RadioButtonWithDescription createRadioButtonWithDescription(
String primary, String description, Object tag) {
RadioButtonWithDescription b = new RadioButtonWithDescription(mContext, null);
......
......@@ -13,6 +13,8 @@ import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.TextView;
import org.chromium.ui.KeyboardVisibilityDelegate;
import java.util.ArrayList;
import java.util.List;
......@@ -103,6 +105,21 @@ public class RadioButtonWithEditText extends RadioButtonWithDescription {
}
}
});
// Handles keyboard actions
mEditText.setOnEditorActionListener((v, actionId, event) -> {
mEditText.clearFocus();
return false;
});
// Handle touches beside the Edit text
mEditText.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
mEditText.setCursorVisible(true);
} else {
releaseFocusForEditText();
}
});
}
@Override
......@@ -127,6 +144,15 @@ public class RadioButtonWithEditText extends RadioButtonWithDescription {
a.recycle();
}
/**
* Sets the checked status.
*/
@Override
public void setChecked(boolean checked) {
super.setChecked(checked);
mEditText.clearFocus();
}
/**
* Add a listener that will be notified when text inside this url has been changed
* @param listener New listener that will be notified when text edit has been changed
......@@ -164,4 +190,12 @@ public class RadioButtonWithEditText extends RadioButtonWithDescription {
public void setHint(int hintId) {
mEditText.setHint(hintId);
}
/**
* Handle focus when the edit text is selected
*/
private void releaseFocusForEditText() {
mEditText.setCursorVisible(false);
KeyboardVisibilityDelegate.getInstance().hideKeyboard(mEditText);
}
}
......@@ -5,11 +5,14 @@
package org.chromium.components.browser_ui.widget;
import android.app.Activity;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.text.InputType;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
......@@ -20,7 +23,11 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.components.browser_ui.widget.test.R;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.ui.KeyboardVisibilityDelegate;
import org.chromium.ui.test.util.DummyUiActivityTestCase;
/**
......@@ -69,6 +76,8 @@ public class RadioButtonWithEditTextTest extends DummyUiActivityTestCase {
private RadioButton mButton;
private EditText mEditText;
private Button mDummyButton;
@Override
public void setUpTest() throws Exception {
super.setUpTest();
......@@ -86,7 +95,9 @@ public class RadioButtonWithEditTextTest extends DummyUiActivityTestCase {
mRadioButtonWithEditText =
(RadioButtonWithEditText) layout.findViewById(R.id.test_radio_button);
mDummyButton = (Button) layout.findViewById(R.id.dummy_button);
Assert.assertNotNull(mRadioButtonWithEditText);
Assert.assertNotNull(mDummyButton);
mButton = layout.findViewById(R.id.radio_button);
mEditText = layout.findViewById(R.id.edit_text);
......@@ -199,4 +210,66 @@ public class RadioButtonWithEditTextTest extends DummyUiActivityTestCase {
Assert.assertEquals("TestListener#OnTextChanged should not be called any more", timesCalled,
mListener.getTimesCalled());
}
@Test
@SmallTest
public void testFocusChange() {
Assert.assertFalse(mRadioButtonWithEditText.hasFocus());
TestThreadUtils.runOnUiThreadBlocking(() -> { mRadioButtonWithEditText.setChecked(true); });
Assert.assertFalse("Edit text should not gain focus when radio button is checked",
mEditText.hasFocus());
Assert.assertFalse("Cursor in EditText should be hidden", mEditText.isCursorVisible());
// Test requesting focus on the EditText
TestThreadUtils.runOnUiThreadBlocking(() -> { mEditText.requestFocus(); });
Assert.assertTrue("Cursor in EditText should be visible", mEditText.isCursorVisible());
// Requesting focus elsewhere
TestThreadUtils.runOnUiThreadBlocking(() -> { mDummyButton.requestFocus(); });
Assert.assertFalse("Cursor in EditText should be visible", mEditText.isCursorVisible());
assertIsKeyboardShowing(false);
// Click to show keyboard
TouchCommon.singleClickView(mEditText);
Assert.assertTrue("Cursor in EditText should be visible", mEditText.isCursorVisible());
assertIsKeyboardShowing(true);
// Test editor action
InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
Assert.assertFalse("Cursor in EditText should be visible", mEditText.isCursorVisible());
assertIsKeyboardShowing(false);
}
@Test
@SmallTest
public void testSetEnabled() {
TestThreadUtils.runOnUiThreadBlocking(
() -> { mRadioButtonWithEditText.setEnabled(false); });
Assert.assertFalse("Primary TextView should be set to disabled.",
mRadioButtonWithEditText.getPrimaryTextView().isEnabled());
Assert.assertFalse("Description TextView should be set to disabled.",
mRadioButtonWithEditText.getDescriptionTextView().isEnabled());
Assert.assertFalse("RadioButton should be set to disabled.",
mRadioButtonWithEditText.getRadioButtonView().isEnabled());
TestThreadUtils.runOnUiThreadBlocking(() -> { mRadioButtonWithEditText.setEnabled(true); });
Assert.assertTrue("Primary TextView should be set to enabled.",
mRadioButtonWithEditText.getPrimaryTextView().isEnabled());
Assert.assertTrue("Description TextView should be set to enabled.",
mRadioButtonWithEditText.getDescriptionTextView().isEnabled());
Assert.assertTrue("RadioButton should be set to enabled.",
mRadioButtonWithEditText.getRadioButtonView().isEnabled());
}
private void assertIsKeyboardShowing(boolean isShowing) {
CriteriaHelper.pollUiThread(
new Criteria("Keyboard visibility does not consist with test setting.") {
@Override
public boolean isSatisfied() {
return KeyboardVisibilityDelegate.getInstance().isKeyboardShowing(
mActivity, mEditText)
== isShowing;
}
});
}
}
......@@ -19,4 +19,11 @@
android:hint="@string/test_uri"
android:background="?attr/selectableItemBackground"
app:descriptionText="@string/test_string" />
<!-- A View used to transfer focus of radio button-->
<Button
android:id="@+id/dummy_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/test_string" />
</FrameLayout>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment