blob: 098d12edd5c02eab2449b8872e3e0f99d67f4a99 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.text.method.cts;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.widget.TextView.BufferType.EDITABLE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.app.Activity;
import android.app.Instrumentation;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.text.Spannable;
import android.text.method.BaseMovementMethod;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerProperties;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.compatibility.common.util.WidgetTestUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test {@link BaseMovementMethod}.
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
public class BaseMovementMethodTest {
private Instrumentation mInstrumentation;
private BaseMovementMethod mMovementMethod;
private TextView mTextView;
@Rule
public ActivityTestRule<CtsActivity> mActivityRule = new ActivityTestRule<>(CtsActivity.class);
@Before
public void setup() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mMovementMethod = new BaseMovementMethod();
}
@Test
public void testOnGenericMotionEvent_horizontalScroll() throws Throwable {
final String testLine = "some text some text";
final String testString = testLine + "\n" + testLine;
mActivityRule.runOnUiThread(() -> mTextView = createTextView());
// limit lines for horizontal scroll
mTextView.setSingleLine();
mTextView.setText(testString, EDITABLE);
// limit width for horizontal scroll
setContentView(mTextView, (int) mTextView.getPaint().measureText(testLine) / 3);
// assert the default scroll position
assertEquals(0, mTextView.getScrollX());
final Spannable text = (Spannable) mTextView.getText();
final double lineSpacing = Math.ceil(mTextView.getPaint().getFontSpacing());
// scroll right
MotionEvent event = createScrollEvent(1, 0);
assertTrue(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView, null);
assertEquals(lineSpacing, mTextView.getScrollX(), lineSpacing / 4);
event.recycle();
// scroll left
event = createScrollEvent(-1, 0);
assertTrue(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView, null);
assertEquals(0, mTextView.getScrollX());
event.recycle();
// cannot scroll to left
event = createScrollEvent(-1, 0);
assertFalse(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
event.recycle();
// cannot scroll to right
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView,
() -> mTextView.scrollTo((int) mTextView.getLayout().getLineWidth(0), 0));
event = createScrollEvent(1, 0);
assertFalse(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
event.recycle();
// meta shift on
// reset scroll
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView,
() -> mTextView.scrollTo(0, 0));
// scroll top becomes scroll right
event = createScrollEvent(0, 1, KeyEvent.META_SHIFT_ON);
assertTrue(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView, null);
assertEquals(lineSpacing, mTextView.getScrollX(), lineSpacing / 4);
event.recycle();
// scroll down becomes scroll left
event = createScrollEvent(0, -1, KeyEvent.META_SHIFT_ON);
assertTrue(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView, null);
assertEquals(0, mTextView.getScrollX());
event.recycle();
}
@Test
public void testOnGenericMotionEvent_verticalScroll() throws Throwable {
final String testLine = "some text some text";
final String testString = testLine + "\n" + testLine;
mActivityRule.runOnUiThread(() -> mTextView = createTextView());
// limit lines for vertical scroll
mTextView.setMaxLines(1);
mTextView.setText(testString, EDITABLE);
setContentView(mTextView, WRAP_CONTENT);
// assert the default scroll positions
assertEquals(0, mTextView.getScrollY());
final Spannable text = (Spannable) mTextView.getText();
final int lineHeight = mTextView.getLineHeight();
// scroll down
MotionEvent event = createScrollEvent(0, -1);
assertTrue(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView, null);
assertEquals(lineHeight, mTextView.getScrollY(), lineHeight / 4);
event.recycle();
// scroll up
event = createScrollEvent(0, 1);
assertTrue(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView, null);
assertEquals(0, mTextView.getScrollY());
event.recycle();
// cannot scroll up
event = createScrollEvent(0, 1);
assertFalse(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
event.recycle();
// cannot scroll down
WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mTextView,
() -> mTextView.scrollTo(0, mTextView.getLayout().getHeight()));
event = createScrollEvent(0, -1);
assertFalse(mMovementMethod.onGenericMotionEvent(mTextView, text, event));
event.recycle();
}
private TextView createTextView() {
final TextView textView = new TextViewNoIme(mActivityRule.getActivity());
textView.setFocusable(true);
textView.setMovementMethod(mMovementMethod);
textView.setTextDirection(View.TEXT_DIRECTION_LTR);
return textView;
}
private void setContentView(@NonNull TextView textView, int textWidth) throws Throwable {
final Activity activity = mActivityRule.getActivity();
final FrameLayout layout = new FrameLayout(activity);
layout.addView(textView, new ViewGroup.LayoutParams(textWidth, WRAP_CONTENT));
mActivityRule.runOnUiThread(() -> {
activity.setContentView(layout, new ViewGroup.LayoutParams(MATCH_PARENT,
MATCH_PARENT));
textView.requestFocus();
});
mInstrumentation.waitForIdleSync();
assertTrue(textView.isFocused());
}
private static MotionEvent createScrollEvent(int horizontal, int vertical) {
return createScrollEvent(horizontal, vertical, 0);
}
private static MotionEvent createScrollEvent(int horizontal, int vertical, int meta) {
final PointerProperties[] pointerProperties = new PointerProperties[1];
pointerProperties[0] = new PointerProperties();
pointerProperties[0].id = 0;
final MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[1];
coords[0] = new MotionEvent.PointerCoords();
coords[0].setAxisValue(MotionEvent.AXIS_VSCROLL, vertical);
coords[0].setAxisValue(MotionEvent.AXIS_HSCROLL, horizontal);
final long time = SystemClock.uptimeMillis();
return MotionEvent.obtain(time, time, MotionEvent.ACTION_SCROLL, 1,
pointerProperties, coords, meta, 0, 1.0f, 1.0f, 0, 0,
InputDevice.SOURCE_CLASS_POINTER, 0);
}
}