blob: 1a1244f0a7d147c64f823baceeab6d87a8a3083f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Neal Nguyen1a44d5d2010-01-13 10:42:43 -080017package android.widget;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Siyamed Sinir21914182017-06-16 15:24:00 -070019import static junit.framework.Assert.assertEquals;
20import static junit.framework.Assert.assertNotNull;
21import static junit.framework.Assert.assertTrue;
22
Clara Bayarri5b7665a2015-05-15 16:32:50 +010023import android.app.Activity;
Siyamed Sinir21914182017-06-16 15:24:00 -070024import android.app.Instrumentation;
Clara Bayarri5b7665a2015-05-15 16:32:50 +010025import android.content.Intent;
Seigo Nonaka9863f672016-12-14 17:56:10 +090026import android.graphics.Paint;
Chet Haase9392d402016-06-08 15:40:46 -070027import android.platform.test.annotations.Presubmit;
Siyamed Sinir21914182017-06-16 15:24:00 -070028import android.support.test.InstrumentationRegistry;
29import android.support.test.annotation.UiThreadTest;
30import android.support.test.filters.MediumTest;
31import android.support.test.rule.ActivityTestRule;
32import android.support.test.runner.AndroidJUnit4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.text.GetChars;
Seigo Nonaka9863f672016-12-14 17:56:10 +090034import android.text.Layout;
Clara Bayarri5b7665a2015-05-15 16:32:50 +010035import android.text.Selection;
36import android.text.Spannable;
Seigo Nonaka9863f672016-12-14 17:56:10 +090037import android.view.View;
Siyamed Sinir21914182017-06-16 15:24:00 -070038
39import org.junit.Before;
40import org.junit.Rule;
41import org.junit.Test;
42import org.junit.runner.RunWith;
43
Seigo Nonaka9863f672016-12-14 17:56:10 +090044import java.util.Locale;
Doug Feltcb3791202011-07-07 11:57:48 -070045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046/**
47 * TextViewTest tests {@link TextView}.
48 */
Siyamed Sinir21914182017-06-16 15:24:00 -070049@RunWith(AndroidJUnit4.class)
50@MediumTest
51public class TextViewTest {
52 @Rule
53 public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>(
54 TextViewActivity.class);
55 private Instrumentation mInstrumentation;
56 private Activity mActivity;
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +010057 private TextView mTextView;
Clara Bayarrid7e48e12015-08-21 15:21:08 +010058
Siyamed Sinir21914182017-06-16 15:24:00 -070059 @Before
60 public void setup() {
61 mActivity = mActivityRule.getActivity();
62 mInstrumentation = InstrumentationRegistry.getInstrumentation();
Clara Bayarrid7e48e12015-08-21 15:21:08 +010063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064
Chet Haase9392d402016-06-08 15:40:46 -070065 @Presubmit
Siyamed Sinir21914182017-06-16 15:24:00 -070066 @UiThreadTest
67 @Test
68 public void testArray() {
69 mTextView = new TextView(mActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070
71 char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
72 'W', 'o', 'r', 'l', 'd', '!' };
73
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +010074 mTextView.setText(c, 1, 4);
75 CharSequence oldText = mTextView.getText();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +010077 mTextView.setText(c, 4, 5);
78 CharSequence newText = mTextView.getText();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079
80 assertTrue(newText == oldText);
81
82 assertEquals(5, newText.length());
83 assertEquals('o', newText.charAt(0));
84 assertEquals("o Wor", newText.toString());
85
86 assertEquals(" Wo", newText.subSequence(1, 4));
87
88 char[] c2 = new char[7];
89 ((GetChars) newText).getChars(1, 4, c2, 2);
90 assertEquals('\0', c2[1]);
91 assertEquals(' ', c2[2]);
92 assertEquals('W', c2[3]);
93 assertEquals('o', c2[4]);
94 assertEquals('\0', c2[5]);
95 }
Clara Bayarri5b7665a2015-05-15 16:32:50 +010096
Siyamed Sinir21914182017-06-16 15:24:00 -070097 @Test
98 public void testProcessTextActivityResultNonEditable() throws Throwable {
99 mActivityRule.runOnUiThread(() -> mTextView = new TextView(mActivity));
100 mInstrumentation.waitForIdleSync();
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100101 CharSequence originalText = "This is some text.";
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100102 mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
103 assertEquals(originalText, mTextView.getText().toString());
104 mTextView.setTextIsSelectable(true);
105 Selection.setSelection((Spannable) mTextView.getText(), 0, mTextView.getText().length());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100106
Clara Bayarrid7e48e12015-08-21 15:21:08 +0100107 // We need to run this in the UI thread, as it will create a Toast.
Siyamed Sinir21914182017-06-16 15:24:00 -0700108 mActivityRule.runOnUiThread(() -> {
109 CharSequence newText = "Text is replaced.";
110 Intent data = new Intent();
111 data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
112 mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK,
113 data);
Clara Bayarrid7e48e12015-08-21 15:21:08 +0100114 });
Siyamed Sinir21914182017-06-16 15:24:00 -0700115 mInstrumentation.waitForIdleSync();
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100116
117 // This is a TextView, which can't be modified. Hence no change should have been made.
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100118 assertEquals(originalText, mTextView.getText().toString());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100119 }
120
Siyamed Sinir21914182017-06-16 15:24:00 -0700121 @Test
122 public void testProcessTextActivityResultEditable() throws Throwable {
123 mActivityRule.runOnUiThread(() -> mTextView = new EditText(mActivity));
124 mInstrumentation.waitForIdleSync();
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100125 CharSequence originalText = "This is some text.";
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100126 mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
127 assertEquals(originalText, mTextView.getText().toString());
128 mTextView.setTextIsSelectable(true);
129 Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100130
131 CharSequence newText = "Text is replaced.";
132 Intent data = new Intent();
133 data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100134 mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data);
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100135
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100136 assertEquals(newText, mTextView.getText().toString());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100137 }
138
Siyamed Sinir21914182017-06-16 15:24:00 -0700139 @Test
140 public void testProcessTextActivityResultCancel() throws Throwable {
141 mActivityRule.runOnUiThread(() -> mTextView = new EditText(mActivity));
142 mInstrumentation.waitForIdleSync();
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100143 CharSequence originalText = "This is some text.";
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100144 mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
145 assertEquals(originalText, mTextView.getText().toString());
146 mTextView.setTextIsSelectable(true);
147 Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100148
149 CharSequence newText = "Text is replaced.";
150 Intent data = new Intent();
151 data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText);
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100152 mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED,
153 data);
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100154
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100155 assertEquals(originalText, mTextView.getText().toString());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100156 }
157
Siyamed Sinir21914182017-06-16 15:24:00 -0700158 @Test
159 public void testProcessTextActivityNoData() throws Throwable {
160 mActivityRule.runOnUiThread(() -> mTextView = new EditText(mActivity));
161 mInstrumentation.waitForIdleSync();
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100162 CharSequence originalText = "This is some text.";
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100163 mTextView.setText(originalText, TextView.BufferType.SPANNABLE);
164 assertEquals(originalText, mTextView.getText().toString());
165 mTextView.setTextIsSelectable(true);
166 Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100167
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100168 mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null);
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100169
Andrei Stingaceanu3df24c32016-08-01 17:15:07 +0100170 assertEquals(originalText, mTextView.getText().toString());
Clara Bayarri5b7665a2015-05-15 16:32:50 +0100171 }
Seigo Nonaka9863f672016-12-14 17:56:10 +0900172
Siyamed Sinir21914182017-06-16 15:24:00 -0700173 @Test
174 @UiThreadTest
Seigo Nonaka9863f672016-12-14 17:56:10 +0900175 public void testHyphenationWidth() {
Siyamed Sinir21914182017-06-16 15:24:00 -0700176 mTextView = new TextView(mActivity);
177 mTextView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
178 mTextView.setTextLocale(Locale.US);
Seigo Nonaka9863f672016-12-14 17:56:10 +0900179
Siyamed Sinir21914182017-06-16 15:24:00 -0700180 Paint paint = mTextView.getPaint();
Seigo Nonaka9863f672016-12-14 17:56:10 +0900181
182 String word = "thisissuperlonglongword";
183 float wordWidth = paint.measureText(word, 0, word.length());
184
185 StringBuilder sb = new StringBuilder();
186 for (int i = 0; i < 100; ++i) {
187 sb.append(word);
188 sb.append(" ");
189 }
Siyamed Sinir21914182017-06-16 15:24:00 -0700190 mTextView.setText(sb.toString());
Seigo Nonaka9863f672016-12-14 17:56:10 +0900191
192 int width = (int)(wordWidth * 0.7);
193 int height = 4096; // enough for all text.
194
Siyamed Sinir21914182017-06-16 15:24:00 -0700195 mTextView.measure(
Seigo Nonaka9863f672016-12-14 17:56:10 +0900196 View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
197 View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
Siyamed Sinir21914182017-06-16 15:24:00 -0700198 mTextView.layout(0, 0, width, height);
Seigo Nonaka9863f672016-12-14 17:56:10 +0900199
Siyamed Sinir21914182017-06-16 15:24:00 -0700200 Layout layout = mTextView.getLayout();
Seigo Nonaka9863f672016-12-14 17:56:10 +0900201 assertNotNull(layout);
202
203 int lineCount = layout.getLineCount();
204 boolean hyphenationHappend = false;
205 for (int i = 0; i < lineCount; ++i) {
206 if (layout.getHyphen(i) != 1) {
207 continue; // Hyphantion does not happen.
208 }
209 hyphenationHappend = true;
210
211 int start = layout.getLineStart(i);
212 int end = layout.getLineEnd(i);
213
214 float withoutHyphenLength = paint.measureText(sb, start, end);
215 float withHyphenLength = layout.getLineWidth(i);
216
217 assertTrue("LineWidth should take account of hyphen length.",
218 withHyphenLength > withoutHyphenLength);
219 }
220 assertTrue("Hyphenation must happen on TextView narrower than the word width",
221 hyphenationHappend);
222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223}