| /* |
| * Copyright (C) 2007 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.widget.focus; |
| |
| import android.graphics.Rect; |
| import android.test.InstrumentationTestCase; |
| import android.test.suitebuilder.annotation.LargeTest; |
| import android.test.suitebuilder.annotation.MediumTest; |
| import android.util.InternalSelectionView; |
| import android.view.KeyEvent; |
| import android.widget.ListView; |
| |
| |
| /** |
| * TODO: extract base test case that launches {@link ListOfInternalSelectionViews} with |
| * bundle params. |
| */ |
| public class ScrollingThroughListOfFocusablesTest extends InstrumentationTestCase { |
| |
| Rect mTempRect = new Rect(); |
| |
| private ListOfInternalSelectionViews mActivity; |
| private ListView mListView; |
| |
| private int mNumItems = 4; |
| private int mNumRowsPerItem = 5; |
| private double mScreenHeightFactor = 5 /4; |
| |
| @Override |
| protected void setUp() throws Exception { |
| mActivity = launchActivity( |
| "com.android.frameworks.coretests", |
| ListOfInternalSelectionViews.class, |
| ListOfInternalSelectionViews.getBundleFor( |
| mNumItems, // 4 items |
| mNumRowsPerItem, // 5 internally selectable rows per item |
| mScreenHeightFactor)); // each item is 5 / 4 screen height tall |
| mListView = mActivity.getListView(); |
| // Make sure we have some fading edge regardless of ListView style. |
| mListView.setVerticalFadingEdgeEnabled(true); |
| mListView.setFadingEdgeLength(10); |
| ensureNotInTouchMode(); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| mActivity.finish(); |
| super.tearDown(); |
| } |
| |
| @MediumTest |
| public void testPreconditions() throws Exception { |
| assertNotNull(mActivity); |
| assertNotNull(mListView); |
| assertEquals(mNumItems, mActivity.getNumItems()); |
| assertEquals(mNumRowsPerItem, mActivity.getNumRowsPerItem()); |
| } |
| |
| @MediumTest |
| public void testScrollingDownInFirstItem() throws Exception { |
| |
| for (int i = 0; i < mNumRowsPerItem; i++) { |
| assertEquals(0, mListView.getSelectedItemPosition()); |
| |
| InternalSelectionView view = mActivity.getSelectedView(); |
| |
| assertInternallySelectedRowOnScreen(view, i); |
| |
| // move to next row |
| if (i < mNumRowsPerItem - 1) { |
| sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); |
| getInstrumentation().waitForIdleSync(); |
| } |
| } |
| |
| { |
| assertEquals(0, mListView.getSelectedItemPosition()); |
| InternalSelectionView view = (InternalSelectionView) |
| mListView.getSelectedView(); |
| |
| // 1 pixel tolerance in case height / 4 is not an even number |
| final int bottomFadingEdgeTop = |
| mListView.getBottom() - mListView.getVerticalFadingEdgeLength(); |
| assertTrue("bottom of view should be just above fading edge", |
| view.getBottom() == bottomFadingEdgeTop); |
| } |
| |
| // make sure fading edge is the expected view |
| { |
| assertEquals("should be a second view visible due to the fading edge", |
| 2, mListView.getChildCount()); |
| InternalSelectionView peekingChild = (InternalSelectionView) |
| mListView.getChildAt(1); |
| assertNotNull(peekingChild); |
| assertEquals("wrong value for peeking list item", |
| mActivity.getLabelForPosition(1), peekingChild.getLabel()); |
| } |
| } |
| |
| @MediumTest |
| public void testScrollingToSecondItem() throws Exception { |
| |
| for (int i = 0; i < mNumRowsPerItem; i++) { |
| sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); |
| getInstrumentation().waitForIdleSync(); |
| } |
| |
| assertEquals("should have moved to second item", |
| 1, mListView.getSelectedItemPosition()); |
| } |
| |
| @LargeTest |
| public void testNoFadingEdgeAtBottomOfLastItem() { |
| |
| // move down to last item |
| for (int i = 0; i < mNumItems; i++) { |
| for (int j = 0; j < mNumRowsPerItem; j++) { |
| if (i < mNumItems - 1 || j < mNumRowsPerItem - 1) { |
| sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); |
| getInstrumentation().waitForIdleSync(); |
| } |
| } |
| } |
| |
| assertEquals(mNumItems - 1, mListView.getSelectedItemPosition()); |
| InternalSelectionView view = mActivity.getSelectedView(); |
| assertEquals(mNumRowsPerItem - 1, view.getSelectedRow()); |
| |
| view.getRectForRow(mTempRect, mNumRowsPerItem - 1); |
| mListView.offsetDescendantRectToMyCoords(view, mTempRect); |
| |
| assertTrue("bottom of last row of last item should be at " + |
| "the bottom of the list view (no fading edge)", |
| mListView.getBottom() - mListView.getVerticalFadingEdgeLength() < mTempRect.bottom); |
| } |
| |
| @LargeTest |
| public void testNavigatingUpThroughInternalSelection() throws Exception { |
| |
| // get to bottom of second item |
| for (int i = 0; i < 2; i++) { |
| for (int j = 0; j < mNumRowsPerItem; j++) { |
| if (i < 1 || j < mNumRowsPerItem - 1) { |
| sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); |
| getInstrumentation().waitForIdleSync(); |
| } |
| } |
| } |
| |
| |
| // (make sure we are at last row of second item) |
| { |
| assertEquals(1, mListView.getSelectedItemPosition()); |
| InternalSelectionView view = mActivity.getSelectedView(); |
| assertEquals(mNumRowsPerItem - 1, view.getSelectedRow()); |
| } |
| |
| // go back up to the top of the second item |
| for (int i = mNumRowsPerItem - 1; i >= 0; i--) { |
| assertEquals(1, mListView.getSelectedItemPosition()); |
| InternalSelectionView view = mActivity.getSelectedView(); |
| |
| assertInternallySelectedRowOnScreen(view, i); |
| |
| // move up to next row |
| if (i > 0) { |
| sendKeys(KeyEvent.KEYCODE_DPAD_UP); |
| getInstrumentation().waitForIdleSync(); |
| } |
| } |
| |
| // now we are at top row, should have caused scrolling, and fading edge... |
| { |
| assertEquals(1, mListView.getSelectedItemPosition()); |
| InternalSelectionView view = mActivity.getSelectedView(); |
| assertEquals(0, view.getSelectedRow()); |
| |
| view.getDrawingRect(mTempRect); |
| mListView.offsetDescendantRectToMyCoords(view, mTempRect); |
| assertEquals("top of selected row should be just below top vertical fading edge", |
| mListView.getVerticalFadingEdgeLength(), |
| view.getTop()); |
| } |
| |
| // make sure fading edge is the view we expect |
| { |
| final InternalSelectionView view = |
| (InternalSelectionView) mListView.getChildAt(0); |
| assertEquals(mActivity.getLabelForPosition(0), view.getLabel()); |
| } |
| |
| |
| } |
| |
| /** |
| * @param internalFocused The view to check |
| * @param row |
| */ |
| private void assertInternallySelectedRowOnScreen( |
| InternalSelectionView internalFocused, |
| int row) { |
| assertEquals("expecting selected row", |
| row, internalFocused.getSelectedRow()); |
| |
| internalFocused.getRectForRow(mTempRect, row); |
| mListView.offsetDescendantRectToMyCoords(internalFocused, mTempRect); |
| |
| assertTrue("top of row " + row + " should be on sreen", |
| mTempRect.top >= 0); |
| assertTrue("bottom of row " + row + " should be on sreen", |
| mTempRect.bottom < mActivity.getScreenHeight()); |
| } |
| |
| private void ensureNotInTouchMode() { |
| // If in touch mode inject a DPAD down event to exit that mode. |
| if (mListView.isInTouchMode()) { |
| sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); |
| getInstrumentation().waitForIdleSync(); |
| } |
| } |
| } |