Home | History | Annotate | Download | only in focus
      1 /*
      2  * Copyright (C) 2007 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 
     17 package android.widget.focus;
     18 
     19 import android.graphics.Rect;
     20 import android.test.InstrumentationTestCase;
     21 import android.test.suitebuilder.annotation.LargeTest;
     22 import android.test.suitebuilder.annotation.MediumTest;
     23 import android.util.InternalSelectionView;
     24 import android.view.KeyEvent;
     25 import android.widget.ListView;
     26 
     27 
     28 /**
     29  * TODO: extract base test case that launches {@link ListOfInternalSelectionViews} with
     30  * bundle params.
     31  */
     32 public class ScrollingThroughListOfFocusablesTest extends InstrumentationTestCase {
     33 
     34     Rect mTempRect = new Rect();
     35 
     36     private ListOfInternalSelectionViews mActivity;
     37     private ListView mListView;
     38 
     39     private int mNumItems = 4;
     40     private int mNumRowsPerItem = 5;
     41     private double mScreenHeightFactor = 5 /4;
     42 
     43     @Override
     44     protected void setUp() throws Exception {
     45         mActivity = launchActivity(
     46                 "com.android.frameworks.coretests",
     47                 ListOfInternalSelectionViews.class,
     48                 ListOfInternalSelectionViews.getBundleFor(
     49                     mNumItems,      // 4 items
     50                     mNumRowsPerItem,      // 5 internally selectable rows per item
     51                     mScreenHeightFactor)); // each item is 5 / 4 screen height tall
     52         mListView = mActivity.getListView();
     53         // Make sure we have some fading edge regardless of ListView style.
     54         mListView.setVerticalFadingEdgeEnabled(true);
     55         mListView.setFadingEdgeLength(10);
     56         ensureNotInTouchMode();
     57     }
     58 
     59     @Override
     60     protected void tearDown() throws Exception {
     61         mActivity.finish();
     62         super.tearDown();
     63     }
     64 
     65     @MediumTest
     66     public void testPreconditions() throws Exception {
     67         assertNotNull(mActivity);
     68         assertNotNull(mListView);
     69         assertEquals(mNumItems, mActivity.getNumItems());
     70         assertEquals(mNumRowsPerItem, mActivity.getNumRowsPerItem());
     71     }
     72 
     73     @MediumTest
     74     public void testScrollingDownInFirstItem() throws Exception {
     75 
     76         for (int i = 0; i < mNumRowsPerItem; i++) {
     77             assertEquals(0, mListView.getSelectedItemPosition());
     78 
     79             InternalSelectionView view = mActivity.getSelectedView();
     80 
     81             assertInternallySelectedRowOnScreen(view, i);
     82 
     83             // move to next row
     84             if (i < mNumRowsPerItem - 1) {
     85                 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
     86                 getInstrumentation().waitForIdleSync();
     87             }
     88         }
     89 
     90         {
     91             assertEquals(0, mListView.getSelectedItemPosition());
     92             InternalSelectionView view = (InternalSelectionView)
     93                     mListView.getSelectedView();
     94 
     95             // 1 pixel tolerance in case height / 4 is not an even number
     96             final int bottomFadingEdgeTop =
     97                 mListView.getBottom() - mListView.getVerticalFadingEdgeLength();
     98             assertTrue("bottom of view should be just above fading edge",
     99                     view.getBottom() == bottomFadingEdgeTop);
    100         }
    101 
    102         // make sure fading edge is the expected view
    103         {
    104             assertEquals("should be a second view visible due to the fading edge",
    105                             2, mListView.getChildCount());
    106             InternalSelectionView peekingChild = (InternalSelectionView)
    107                     mListView.getChildAt(1);
    108             assertNotNull(peekingChild);
    109             assertEquals("wrong value for peeking list item",
    110                     mActivity.getLabelForPosition(1), peekingChild.getLabel());
    111         }
    112     }
    113 
    114     @MediumTest
    115     public void testScrollingToSecondItem() throws Exception {
    116 
    117         for (int i = 0; i < mNumRowsPerItem; i++) {
    118             sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
    119             getInstrumentation().waitForIdleSync();
    120         }
    121 
    122         assertEquals("should have moved to second item",
    123                 1, mListView.getSelectedItemPosition());
    124     }
    125 
    126     @LargeTest
    127     public void testNoFadingEdgeAtBottomOfLastItem() {
    128 
    129         // move down to last item
    130         for (int i = 0; i < mNumItems; i++) {
    131             for (int j = 0; j < mNumRowsPerItem; j++) {
    132                 if (i < mNumItems - 1 || j < mNumRowsPerItem - 1) {
    133                     sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
    134                     getInstrumentation().waitForIdleSync();
    135                 }
    136             }
    137         }
    138 
    139         assertEquals(mNumItems - 1, mListView.getSelectedItemPosition());
    140         InternalSelectionView view = mActivity.getSelectedView();
    141         assertEquals(mNumRowsPerItem - 1, view.getSelectedRow());
    142 
    143         view.getRectForRow(mTempRect, mNumRowsPerItem - 1);
    144         mListView.offsetDescendantRectToMyCoords(view, mTempRect);
    145 
    146         assertTrue("bottom of last row of last item should be at " +
    147                 "the bottom of the list view (no fading edge)",
    148                 mListView.getBottom() - mListView.getVerticalFadingEdgeLength() < mTempRect.bottom);
    149     }
    150 
    151     @LargeTest
    152     public void testNavigatingUpThroughInternalSelection() throws Exception {
    153 
    154         // get to bottom of second item
    155         for (int i = 0; i < 2; i++) {
    156             for (int j = 0; j < mNumRowsPerItem; j++) {
    157                 if (i < 1 || j < mNumRowsPerItem - 1) {
    158                     sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
    159                     getInstrumentation().waitForIdleSync();
    160                 }
    161             }
    162         }
    163 
    164 
    165         // (make sure we are at last row of second item)
    166         {
    167             assertEquals(1, mListView.getSelectedItemPosition());
    168             InternalSelectionView view = mActivity.getSelectedView();
    169             assertEquals(mNumRowsPerItem - 1, view.getSelectedRow());
    170         }
    171 
    172         // go back up to the top of the second item
    173         for (int i = mNumRowsPerItem - 1; i >= 0; i--) {
    174             assertEquals(1, mListView.getSelectedItemPosition());
    175             InternalSelectionView view = mActivity.getSelectedView();
    176 
    177             assertInternallySelectedRowOnScreen(view, i);
    178 
    179             // move up to next row
    180             if (i > 0) {
    181                 sendKeys(KeyEvent.KEYCODE_DPAD_UP);
    182                 getInstrumentation().waitForIdleSync();
    183             }
    184         }
    185 
    186         // now we are at top row, should have caused scrolling, and fading edge...
    187         {
    188             assertEquals(1, mListView.getSelectedItemPosition());
    189             InternalSelectionView view = mActivity.getSelectedView();
    190             assertEquals(0, view.getSelectedRow());
    191 
    192             view.getDrawingRect(mTempRect);
    193             mListView.offsetDescendantRectToMyCoords(view, mTempRect);
    194             assertEquals("top of selected row should be just below top vertical fading edge",
    195                     mListView.getVerticalFadingEdgeLength(),
    196                     view.getTop());
    197         }
    198 
    199         // make sure fading edge is the view we expect
    200         {
    201             final InternalSelectionView view =
    202                     (InternalSelectionView) mListView.getChildAt(0);
    203             assertEquals(mActivity.getLabelForPosition(0), view.getLabel());
    204         }
    205 
    206 
    207     }
    208 
    209     /**
    210      * @param internalFocused The view to check
    211      * @param row
    212      */
    213     private void assertInternallySelectedRowOnScreen(
    214             InternalSelectionView internalFocused,
    215             int row) {
    216         assertEquals("expecting selected row",
    217                 row, internalFocused.getSelectedRow());
    218 
    219         internalFocused.getRectForRow(mTempRect, row);
    220         mListView.offsetDescendantRectToMyCoords(internalFocused, mTempRect);
    221 
    222         assertTrue("top of row " + row + " should be on sreen",
    223                 mTempRect.top >= 0);
    224         assertTrue("bottom of row " + row + " should be on sreen",
    225                 mTempRect.bottom < mActivity.getScreenHeight());
    226     }
    227 
    228     private void ensureNotInTouchMode() {
    229         // If in touch mode inject a DPAD down event to exit that mode.
    230         if (mListView.isInTouchMode()) {
    231             sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
    232             getInstrumentation().waitForIdleSync();
    233         }
    234     }
    235 }
    236