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

[HomepageConversion] Make RadioButtonWithEditText UI widget

Creating RadioButtonWithEditText to achieve entering customized URL in a radio
button group. By extending RadioButonWithDescription, this new UI widget
shared most of the margin and style with the original button.

Bug: 1036470
Change-Id: I395120490303e4a2f150248c551a8f1e952c4c0a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1966355
Auto-Submit: Wenyu Fu <wenyufu@chromium.org>
Commit-Queue: Theresa  <twellington@chromium.org>
Reviewed-by: default avatarBrandon Wylie <wylieb@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#727840}
parent 2d488224
......@@ -29,14 +29,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
app:titleText="@string/sync_import_existing_data" />
app:primaryText="@string/sync_import_existing_data" />
<org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
android:id="@+id/sync_keep_separate_choice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
app:titleText="@string/sync_keep_existing_data_separate" />
app:primaryText="@string/sync_keep_existing_data_separate" />
</LinearLayout>
</ScrollView>
......@@ -20,7 +20,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
app:titleText="@string/themes_system_default_title"
app:primaryText="@string/themes_system_default_title"
app:descriptionText="@string/themes_system_default_summary" />
<!-- override default padding top and bottom -->
......@@ -32,7 +32,7 @@
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:background="?attr/selectableItemBackground"
app:titleText="@string/light_mode" />
app:primaryText="@string/light_mode" />
<org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
android:id="@+id/dark"
......@@ -42,7 +42,7 @@
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:background="?attr/selectableItemBackground"
app:titleText="@string/dark_mode" />
app:primaryText="@string/dark_mode" />
</org.chromium.chrome.browser.ui.widget.RadioButtonWithDescriptionLayout>
......
......@@ -25,7 +25,7 @@
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:background="?android:attr/selectableItemBackground"
app:titleText="@string/website_settings_category_allowed" />
app:primaryText="@string/website_settings_category_allowed" />
<org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
android:id="@+id/ask"
......@@ -33,7 +33,7 @@
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:background="?android:attr/selectableItemBackground"
app:titleText="@string/website_settings_category_ask" />
app:primaryText="@string/website_settings_category_ask" />
<org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
android:id="@+id/blocked"
......@@ -41,7 +41,7 @@
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:background="?android:attr/selectableItemBackground"
app:titleText="@string/website_settings_category_blocked" />
app:primaryText="@string/website_settings_category_blocked" />
</org.chromium.chrome.browser.ui.widget.RadioButtonWithDescriptionLayout>
</LinearLayout>
......@@ -22,6 +22,7 @@ android_library("java") {
"java/src/org/chromium/chrome/browser/ui/widget/RadioButtonLayout.java",
"java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescription.java",
"java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayout.java",
"java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithEditText.java",
"java/src/org/chromium/chrome/browser/ui/widget/RoundedCornerImageView.java",
"java/src/org/chromium/chrome/browser/ui/widget/TintedDrawable.java",
"java/src/org/chromium/chrome/browser/ui/widget/ViewResourceFrameLayout.java",
......@@ -100,6 +101,7 @@ android_library("ui_widget_java_tests") {
"java/src/org/chromium/chrome/browser/ui/widget/PromoDialogTest.java",
"java/src/org/chromium/chrome/browser/ui/widget/RadioButtonLayoutTest.java",
"java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayoutTest.java",
"java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithEditTextTest.java",
"java/src/org/chromium/chrome/browser/ui/widget/WrappingLayoutTest.java",
"java/src/org/chromium/chrome/browser/ui/widget/highlight/ViewHighlighterTest.java",
]
......
......@@ -18,7 +18,7 @@
android:background="@null" />
<TextView
android:id="@+id/title"
android:id="@+id/primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/radio_button"
......@@ -29,8 +29,8 @@
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@id/title"
android:layout_below="@id/title"
android:layout_alignStart="@id/primary"
android:layout_below="@id/primary"
android:textAppearance="@style/TextAppearance.BlackHint2"
android:visibility="gone" />
</merge>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<!-- RadioButtonWithEditText extends RelativeLayout -->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<RadioButton
android:id="@+id/radio_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:clickable="false"
android:focusable="false"
android:background="@null" />
<!-- Hint will be added programmatically so we're ignoring the lint warning. -->
<EditText
tools:ignore="LabelFor"
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/radio_button"
android:layout_centerVertical="true"
android:textAppearance="@style/TextAppearance.BlackTitle1"
android:inputType="text" />
<!-- This TextView is hidden if it has no text, so the initial visibility should be "gone". -->
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@id/edit_text"
android:layout_below="@id/edit_text"
android:textAppearance="@style/TextAppearance.BlackHint2"
android:visibility="gone" />
</merge>
......@@ -23,10 +23,15 @@
</declare-styleable>
<declare-styleable name="RadioButtonWithDescription">
<attr name="titleText" format="string" />
<attr name="primaryText" format="string" />
<attr name="descriptionText" format="string" />
</declare-styleable>
<declare-styleable name="RadioButtonWithEditText">
<attr name="android:hint"/>
<attr name="android:inputType" />
</declare-styleable>
<declare-styleable name="RoundedCornerImageView">
<attr name="cornerRadiusTopStart" format="dimension" />
<attr name="cornerRadiusTopEnd" format="dimension" />
......
......@@ -17,10 +17,30 @@ import android.view.View.OnClickListener;
import android.widget.RadioButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.List;
/**
* A RadioButton with a title and descriptive text to the right.
* <p>
* A RadioButton with a primary and descriptive text to the right.
* The radio button is designed to be contained in a group, with {@link
* RadioButtonWithDescriptionLayout} as the parent view. By default, the object will be inflated
* from {@link R.layout.radio_button_with_description).
* </p>
*
* <p>
* The primary of the text and an optional description to be contained in the group may be set in
* XML. Sample declaration in XML:
* <pre> {@code
* <org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
* android:id="@+id/system_default"
* android:layout_width="match_parent"
* android:layout_height="wrap_content"
* android:background="?attr/selectableItemBackground"
* app:primaryText="@string/feature_foo_option_one"
* app:descriptionText="@string/feature_foo_option_one_description" />
* } </pre>
* </p>
*/
public class RadioButtonWithDescription extends RelativeLayout implements OnClickListener {
/**
......@@ -35,8 +55,9 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
}
private RadioButton mRadioButton;
private TextView mTitle;
private TextView mPrimary;
private TextView mDescription;
private ButtonCheckedStateChangedListener mButtonCheckedStateChangedListener;
private List<RadioButtonWithDescription> mGroup;
......@@ -49,11 +70,9 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
*/
public RadioButtonWithDescription(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.radio_button_with_description, this, true);
LayoutInflater.from(context).inflate(getLayoutResource(), this, true);
mRadioButton = (RadioButton) findViewById(R.id.radio_button);
mTitle = (TextView) findViewById(R.id.title);
mDescription = (TextView) findViewById(R.id.description);
setViewsInternal();
if (attrs != null) applyAttributes(attrs);
......@@ -76,12 +95,53 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
setFocusable(true);
}
private void applyAttributes(AttributeSet attrs) {
/**
* Set the view elements that included in xml internally.
*/
protected void setViewsInternal() {
mRadioButton = getRadioButtonView();
mPrimary = getPrimaryTextView();
mDescription = getDescriptionTextView();
}
/**
* @return The layout resource id used for inflating this {@link RadioButtonWithDescription}.
*/
protected int getLayoutResource() {
return R.layout.radio_button_with_description;
}
/**
* @return RadioButton View inside this {@link RadioButtonWithDescription}.
*/
protected RadioButton getRadioButtonView() {
return (RadioButton) findViewById(R.id.radio_button);
}
/**
* @return TextView displayed as primary inside this {@link RadioButtonWithDescription}.
*/
protected TextView getPrimaryTextView() {
return (TextView) findViewById(R.id.primary);
}
/**
* @return TextView displayed as description inside this {@link RadioButtonWithDescription}.
*/
protected TextView getDescriptionTextView() {
return (TextView) findViewById(R.id.description);
}
/**
* Apply the customized AttributeSet to current view.
* @param attrs AttributeSet that will be applied to current view.
*/
protected void applyAttributes(AttributeSet attrs) {
TypedArray a = getContext().getTheme().obtainStyledAttributes(
attrs, R.styleable.RadioButtonWithDescription, 0, 0);
String titleText = a.getString(R.styleable.RadioButtonWithDescription_titleText);
if (titleText != null) mTitle.setText(titleText);
String primaryText = a.getString(R.styleable.RadioButtonWithDescription_primaryText);
if (primaryText != null) mPrimary.setText(primaryText);
String descriptionText =
a.getString(R.styleable.RadioButtonWithDescription_descriptionText);
......@@ -89,7 +149,7 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
mDescription.setText(descriptionText);
mDescription.setVisibility(View.VISIBLE);
} else {
((LayoutParams) mTitle.getLayoutParams()).addRule(RelativeLayout.CENTER_VERTICAL);
((LayoutParams) mPrimary.getLayoutParams()).addRule(RelativeLayout.CENTER_VERTICAL);
}
a.recycle();
......@@ -111,17 +171,17 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
}
/**
* Sets the text shown in the title section.
* Sets the text shown in the primary section.
*/
public void setTitleText(CharSequence text) {
mTitle.setText(text);
public void setPrimaryText(CharSequence text) {
mPrimary.setText(text);
}
/**
* @return The text shown in the title section.
* @return The text shown in the primary section.
*/
public CharSequence getTitleText() {
return mTitle.getText();
public CharSequence getPrimaryText() {
return mPrimary.getText();
}
/**
......@@ -131,10 +191,10 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
mDescription.setText(text);
if (TextUtils.isEmpty(text)) {
((LayoutParams) mTitle.getLayoutParams()).addRule(RelativeLayout.CENTER_VERTICAL);
((LayoutParams) mPrimary.getLayoutParams()).addRule(RelativeLayout.CENTER_VERTICAL);
mDescription.setVisibility(View.GONE);
} else {
((LayoutParams) mTitle.getLayoutParams()).removeRule(RelativeLayout.CENTER_VERTICAL);
((LayoutParams) mPrimary.getLayoutParams()).removeRule(RelativeLayout.CENTER_VERTICAL);
mDescription.setVisibility(View.VISIBLE);
}
}
......@@ -187,11 +247,11 @@ public class RadioButtonWithDescription extends RelativeLayout implements OnClic
// LinearLayout (no id):
// |-> RadioButtonWithDescription (id=sync_confirm_import_choice)
// | |-> RadioButton (id=radio_button)
// | |-> TextView (id=title)
// | |-> TextView (id=primary)
// | \-> TextView (id=description)
// \-> RadioButtonWithDescription (id=sync_keep_separate_choice)
// |-> RadioButton (id=radio_button)
// |-> TextView (id=title)
// |-> TextView (id=primary)
// \-> TextView (id=description)
//
// This causes the automagic state saving and recovery to do the wrong thing and restore all
......
......@@ -10,16 +10,15 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioGroup;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* Manages a group of exclusive RadioButtonWithDescriptions, automatically inserting a margin in
* between the rows to prevent them from squishing together. Has the option to set an accessory view
* on any given RadioButtonWithDescription. Only one accessory view per layout is supported.
*
* <pre>
* -------------------------------------------------
* | O | MESSAGE #1 |
* description_1 |
......@@ -27,41 +26,27 @@ import java.util.List;
* | O | MESSAGE #N |
* description_n |
* -------------------------------------------------
* </pre>
* </p>
*
* <p>
* To declare in XML, define a RadioButtonWithDescriptionLayout that contains
* RadioButtonWithDescription and/or RadioButtonWithEditText children.
* For example:
* <pre>{@code
* <org.chromium.chrome.browser.ui.widget.RadioButtonWithDescriptionLayout
* android:layout_width="match_parent"
* android:layout_height="match_parent" >
* <org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
* ... />
* <org.chromium.chrome.browser.ui.widget.RadioButtonWithEditText
* ... />
* </org.chromium.chrome.browser.ui.widget.RadioButtonWithDescriptionLayout>
* }</pre>
* </p>
*/
public final class RadioButtonWithDescriptionLayout
extends RadioGroup implements RadioButtonWithDescription.ButtonCheckedStateChangedListener {
/** Encapsulates information required to build a layout. */
public static class Option {
private final CharSequence mTitle;
private final CharSequence mDescription;
private final Object mTag;
/**
* @param title The title for this option. This will be displayed as the main text for the
* checkbox.
* @param description The description for this option. This will be displayed as the subtext
* under the main text for the checkbox.
* @param tag The tag for this option. This can be used to identify the checkbox in event
* listeners.
*/
public Option(CharSequence title, CharSequence description, @Nullable Object tag) {
mTitle = title;
mDescription = description;
mTag = tag;
}
public CharSequence getTitle() {
return mTitle;
}
public CharSequence getDescription() {
return mDescription;
}
public Object getTag() {
return mTag;
}
}
private final int mMarginBetweenRows;
private final List<RadioButtonWithDescription> mRadioButtonsWithDescriptions;
......@@ -110,24 +95,14 @@ public final class RadioButtonWithDescriptionLayout
}
/**
* Given a set of {@link Option} creates a set of {@link RadioButtonWithDescription}. When lists
* are built this way, there are two options for getting the checkbox you want in an event
* listener callback.
* 1. Set a tag on the Option and use that with {@link View#findViewWithTag).
* 2. Use the id passed through to {@link RadioGroup.OnCheckedChangeListener#onCheckedChanged}.
* with {@link View#findViewById}.
*
* @param options List of options to add to this group.
* Add group of {@link RadioButtonWithDescription} into current layout. For buttons that already
* exist in other radio button group, the radio button group will be transferred into the group
* inside current layout.
* @param buttons List of {@link RadioButtonWithDescription} to add to this group.
*/
public void addOptions(List<Option> options) {
for (Option option : options) {
RadioButtonWithDescription b = new RadioButtonWithDescription(getContext(), null);
b.setTitleText(option.getTitle());
b.setDescriptionText(option.getDescription());
b.setTag(option.getTag());
public void addButtons(List<RadioButtonWithDescription> buttons) {
for (RadioButtonWithDescription b : buttons) {
setupButton(b);
addView(b, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.ui.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* A radio button that contains a text edit box. The text value inside the entry box could used to
* represent the value when this radio button is selected. This class also supports the
* functionality of adding a description the same as {@link RadioButtonWithDescription}.
*
* By default, this class is inflated from {@link R.layout.radio_button_with_edit_text}.
* </p>
*
* <p>
* There is no default hint provided in the EditText. User could set the hint message through {@link
* #setHint} API, or through android:hint attribute in xml definition.
* </p>
*
* <p>
* This class also provides an interface {@link RadioButtonWithEditText.OnLongClickListener} to
* observe the text changing in its entry box. To use, implement the interface {@link
* RadioButtonWithEditText.OnLongClickListener} and call {@link
* RadioButtonWithEditText#addTextChangeListener(OnTextChangeListener)} to start listening to
* changes in the EditText.
* </p>
*
* <p>
* The input type, text, hint message of EditText box and an optional description to be contained in
* the group may be set in XML. Sample declaration in XML:
* <pre>{@code
* <org.chromium.chrome.browser.ui.widget.RadioButtonWithEditText
* android:id="@+id/system_default"
* android:layout_width="match_parent"
* android:layout_height="wrap_content"
* android:background="?attr/selectableItemBackground"
* android:inputType="text"
* android:hint="@string/hint_text_bar"
* app:primaryText="@string/feature_foo_option_one"
* app:descriptionText="@string/feature_foo_option_one_description" />
* }</pre>
* </p>
*/
public class RadioButtonWithEditText extends RadioButtonWithDescription {
/**
* Interface that will subscribe to changes to the text inside {@link RadioButtonWithEditText}.
*
*/
public interface OnTextChangeListener {
/**
* Will be called when the EditText has a value change.
* @param newText The updated text in EditText.
*/
void onTextChanged(CharSequence newText);
}
private EditText mEditText;
private List<OnTextChangeListener> mListeners;
public RadioButtonWithEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mListeners = new ArrayList<>();
}
@Override
protected int getLayoutResource() {
return R.layout.radio_button_with_edit_text;
}
@Override
protected void setViewsInternal() {
super.setViewsInternal();
mEditText = (EditText) getPrimaryTextView();
mEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
// Text set through AttributionSet will trigger this function before mListeners
// initialize, so we only notify listeners after initialization.
if (mListeners == null) return;
for (OnTextChangeListener listener : mListeners) {
listener.onTextChanged(s);
}
}
});
}
@Override
protected TextView getPrimaryTextView() {
return findViewById(R.id.edit_text);
}
@Override
protected void applyAttributes(AttributeSet attrs) {
super.applyAttributes(attrs);
TypedArray a = getContext().getTheme().obtainStyledAttributes(
attrs, R.styleable.RadioButtonWithEditText, 0, 0);
String hint = a.getString(R.styleable.RadioButtonWithEditText_android_hint);
if (hint != null) setHint(hint);
int inputType = a.getInt(
R.styleable.RadioButtonWithEditText_android_inputType, InputType.TYPE_CLASS_TEXT);
setInputType(inputType);
a.recycle();
}
/**
* 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
*/
public void addTextChangeListener(OnTextChangeListener listener) {
mListeners.add(listener);
}
/**
* Remove the listener from the subscription list
* @param listener Listener that will no longer listening to text edit changes
*/
public void removeTextChangeListener(OnTextChangeListener listener) {
mListeners.remove(listener);
}
/**
* Set the input type of text editor
* @param inputType An input type from {@link android.text.InputType}
*/
public void setInputType(int inputType) {
mEditText.setInputType(inputType);
}
/**
* Set the hint message of text edit box
*/
public void setHint(CharSequence hint) {
mEditText.setHint(hint);
}
/**
* Set the hint message of text edit box using pre-defined string from {@link R.string}
*/
public void setHint(int hintId) {
mEditText.setHint(hintId);
}
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.ui.widget;
import android.app.Activity;
import android.support.test.filters.SmallTest;
import android.text.InputType;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.chrome.browser.ui.widget.test.R;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.test.util.DummyUiActivityTestCase;
/**
* Unit tests for {@link RadioButtonWithEditText}.
*/
@RunWith(BaseJUnit4ClassRunner.class)
public class RadioButtonWithEditTextTest extends DummyUiActivityTestCase {
private class TestListener implements RadioButtonWithEditText.OnTextChangeListener {
private CharSequence mCurrentText;
private int mNumberOfTimesTextChanged;
TestListener() {
mNumberOfTimesTextChanged = 0;
}
/**
* Will be called when the text edit has a value change.
*/
@Override
public void onTextChanged(CharSequence newText) {
mCurrentText = newText;
mNumberOfTimesTextChanged += 1;
}
void setCurrentText(CharSequence currentText) {
mCurrentText = currentText;
}
/**
* Get the current text stored inside
* @return current text updated by RadioButtonWithEditText
*/
CharSequence getCurrentText() {
return mCurrentText;
}
int getTimesCalled() {
return mNumberOfTimesTextChanged;
}
}
private TestListener mListener;
private Activity mActivity;
private RadioButtonWithEditText mRadioButtonWithEditText;
private RadioButton mButton;
private EditText mEditText;
@Override
public void setUpTest() throws Exception {
super.setUpTest();
mActivity = getActivity();
mListener = new TestListener();
setupViewsForTest();
}
private void setupViewsForTest() {
TestThreadUtils.runOnUiThreadBlocking(() -> {
View layout = LayoutInflater.from(mActivity).inflate(
R.layout.radio_button_with_edit_text_test, null, false);
mActivity.setContentView(layout);
mRadioButtonWithEditText =
(RadioButtonWithEditText) layout.findViewById(R.id.test_radio_button);
Assert.assertNotNull(mRadioButtonWithEditText);
mButton = layout.findViewById(R.id.radio_button);
mEditText = layout.findViewById(R.id.edit_text);
Assert.assertNotNull("Radio Button should not be null", mButton);
Assert.assertNotNull("Edit Text should not be null", mEditText);
});
}
@Test
@SmallTest
public void testViewSetup() {
Assert.assertFalse("Button should not be set checked after init.", mButton.isChecked());
Assert.assertTrue(
"Text entry should be empty after init.", TextUtils.isEmpty(mEditText.getText()));
// Test if apply attr works
int textUriInputType = InputType.TYPE_TEXT_VARIATION_URI | InputType.TYPE_CLASS_TEXT;
Assert.assertEquals("EditText input type is different than attr setting.", textUriInputType,
mEditText.getInputType());
Assert.assertEquals("EditText input hint is different than attr setting.",
mActivity.getResources().getString(R.string.test_uri), mEditText.getHint());
TextView description = mActivity.findViewById(R.id.description);
Assert.assertNotNull("Description should not be null", description);
Assert.assertEquals("Description is different than attr setting.",
mActivity.getResources().getString(R.string.test_string), description.getText());
}
@Test
@SmallTest
public void testSetHint() {
final CharSequence hintMsg = "Text hint";
final String resourceString = mActivity.getResources().getString(R.string.test_string);
TestThreadUtils.runOnUiThreadBlocking(() -> {
mRadioButtonWithEditText.setHint(hintMsg);
Assert.assertEquals("Hint message set from string is different from test setting",
hintMsg.toString(), mEditText.getHint().toString());
mRadioButtonWithEditText.setHint(R.string.test_string);
Assert.assertEquals("Hint message set from resource id is different from test setting",
resourceString, mEditText.getHint().toString());
});
}
@Test
@SmallTest
public void testSetInputType() {
int[] commonInputTypes = {
InputType.TYPE_CLASS_DATETIME,
InputType.TYPE_CLASS_NUMBER,
InputType.TYPE_CLASS_PHONE,
InputType.TYPE_CLASS_TEXT,
InputType.TYPE_TEXT_VARIATION_URI,
InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS,
InputType.TYPE_DATETIME_VARIATION_DATE,
};
for (int type : commonInputTypes) {
mRadioButtonWithEditText.setInputType(type);
Assert.assertEquals(mEditText.getInputType(), type);
}
}
@Test
@SmallTest
public void testChangeEditText() {
final CharSequence str1 = "First string";
final CharSequence str2 = "SeConD sTrINg";
CharSequence origStr = mRadioButtonWithEditText.getPrimaryText();
// Test if changing the text edit will result in changing of listener
mRadioButtonWithEditText.addTextChangeListener(mListener);
mListener.setCurrentText(origStr);
int timesCalled = mListener.getTimesCalled();
// Test changes for edit text
TestThreadUtils.runOnUiThreadBlocking(
() -> { mRadioButtonWithEditText.setPrimaryText(str1); });
Assert.assertEquals("New String value should be updated", str1.toString(),
mRadioButtonWithEditText.getPrimaryText().toString());
Assert.assertEquals("Text message in listener should be updated accordingly",
str1.toString(), mListener.getCurrentText().toString());
Assert.assertEquals("TestListener#OnTextChanged should be called once", timesCalled + 1,
mListener.getTimesCalled());
// change to another text from View
timesCalled = mListener.getTimesCalled();
TestThreadUtils.runOnUiThreadBlocking(() -> { mEditText.setText(str2); });
Assert.assertEquals("New String value should be updated", str2.toString(),
mRadioButtonWithEditText.getPrimaryText().toString());
Assert.assertEquals("Text message in listener should be updated accordingly",
str2.toString(), mListener.getCurrentText().toString());
Assert.assertEquals("TestListener#OnTextChanged should be called once", timesCalled + 1,
mListener.getTimesCalled());
// change to another text from View
mRadioButtonWithEditText.removeTextChangeListener(mListener);
timesCalled = mListener.getTimesCalled();
TestThreadUtils.runOnUiThreadBlocking(
() -> { mRadioButtonWithEditText.setPrimaryText(str1); });
Assert.assertEquals("New String value should be updated", str1.toString(),
mRadioButtonWithEditText.getPrimaryText().toString());
Assert.assertEquals("Text message in listener should not be updated.", str2.toString(),
mListener.getCurrentText().toString());
Assert.assertEquals("TestListener#OnTextChanged should not be called any more", timesCalled,
mListener.getTimesCalled());
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<org.chromium.chrome.browser.ui.widget.RadioButtonWithDescriptionLayout
android:id="@+id/test_radio_button_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- RadioButtonWithDescription - With primary, without description. -->
<org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
android:id="@+id/test_radio_description_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:primaryText="@string/test_string" />
<!-- RadioButtonWithDescription - With primary and description. -->
<org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription
android:id="@+id/test_radio_description_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:primaryText="@string/test_string"
app:descriptionText="@string/test_string" />
<!-- RadioButtonWithDescription - With primary, without description. -->
<org.chromium.chrome.browser.ui.widget.RadioButtonWithEditText
android:id="@+id/test_radio_edit_text_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/min_touch_target_size"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:inputType="text"
android:hint="@string/test_uri"
app:primaryText="@string/test_string" />
<!-- RadioButtonWithDescription - With primary and description. -->
<org.chromium.chrome.browser.ui.widget.RadioButtonWithEditText
android:id="@+id/test_radio_edit_text_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/min_touch_target_size"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:inputType="text"
android:hint="@string/test_uri"
app:primaryText="@string/test_string"
app:descriptionText="@string/test_string" />
</org.chromium.chrome.browser.ui.widget.RadioButtonWithDescriptionLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<org.chromium.chrome.browser.ui.widget.RadioButtonWithEditText
android:id="@+id/test_radio_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/min_touch_target_size"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:inputType="textUri"
android:hint="@string/test_uri"
android:background="?attr/selectableItemBackground"
app:descriptionText="@string/test_string" />
</FrameLayout>
......@@ -9,4 +9,7 @@
<string name="promo_dialog_test_primary_button">OK</string>
<string name="promo_dialog_test_secondary_button">Cancel</string>
<string name="promo_dialog_test_footer">Learn more</string>
<string name="test_string">A String used for tests</string>
<string name="test_uri">https://www.example.com</string>
</resources>
\ No newline at end of file
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