Home | History | Annotate | Download | only in scroll
      1 /*
      2  * Copyright (C) 2013 DroidDriver committers
      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 io.appium.droiddriver.scroll;
     18 
     19 import android.app.UiAutomation;
     20 import android.widget.ProgressBar;
     21 
     22 import io.appium.droiddriver.DroidDriver;
     23 import io.appium.droiddriver.finders.By;
     24 import io.appium.droiddriver.finders.Finder;
     25 import io.appium.droiddriver.scroll.Direction.Axis;
     26 import io.appium.droiddriver.scroll.Direction.DirectionConverter;
     27 import io.appium.droiddriver.scroll.Direction.PhysicalDirection;
     28 
     29 /**
     30  * Static utility classes and methods pertaining to {@link Scroller} instances.
     31  */
     32 public class Scrollers {
     33   /**
     34    * Augments the delegate {@link ScrollStepStrategy} - after a successful
     35    * scroll, waits until ProgressBar is gone.
     36    */
     37   public static abstract class ProgressBarScrollStepStrategy extends ForwardingScrollStepStrategy {
     38     @Override
     39     public boolean scroll(DroidDriver driver, Finder containerFinder, PhysicalDirection direction) {
     40       if (super.scroll(driver, containerFinder, direction)) {
     41         driver.checkGone(By.className(ProgressBar.class));
     42         return true;
     43       }
     44       return false;
     45     }
     46 
     47     /** Convenience method to wrap {@code delegate} with this class */
     48     public static ScrollStepStrategy wrap(final ScrollStepStrategy delegate) {
     49       return new ProgressBarScrollStepStrategy() {
     50         @Override
     51         protected ScrollStepStrategy delegate() {
     52           return delegate;
     53         }
     54       };
     55     }
     56   }
     57 
     58   /**
     59    * Returns a new default Scroller that works in simple cases. In complex cases
     60    * you may try a {@link StepBasedScroller} with a custom
     61    * {@link ScrollStepStrategy}:
     62    * <ul>
     63    * <li>If the Scroller is used with InstrumentationDriver,
     64    * StaticSentinelStrategy may work and it's the simplest.</li>
     65    * <li>Otherwise, DynamicSentinelStrategy should work in all cases, including
     66    * the case of dynamic list, which shows more items when scrolling beyond the
     67    * end. On the other hand, it's complex and needs more configuration.</li>
     68    * </ul>
     69    * Note if a {@link StepBasedScroller} is returned, it is constructed with
     70    * arguments that apply to typical cases. You may want to customize them for
     71    * specific cases. For instance, {@code perScrollTimeoutMillis} can be 0L if
     72    * there are no asynchronously updated views. To that extent, this method
     73    * serves as an example of how to construct {@link Scroller}s rather than
     74    * providing the "official" {@link Scroller}.
     75    */
     76   public static Scroller newScroller(UiAutomation uiAutomation) {
     77     if (uiAutomation != null) {
     78       return new StepBasedScroller(100/* maxScrolls */, 1000L/* perScrollTimeoutMillis */,
     79           Axis.VERTICAL, new AccessibilityEventScrollStepStrategy(uiAutomation, 1000L,
     80               DirectionConverter.STANDARD_CONVERTER), true/* startFromBeginning */);
     81     }
     82     // TODO: A {@link Scroller} that directly jumps to the view if an
     83     // InstrumentationDriver is used.
     84     return new StepBasedScroller(100/* maxScrolls */, 1000L/* perScrollTimeoutMillis */,
     85         Axis.VERTICAL, StaticSentinelStrategy.DEFAULT, true/* startFromBeginning */);
     86   }
     87 }
     88