2015-02-12 20 views
58

Wie kann ich Espresso verwenden, um auf eine bestimmte Ansicht in einem RecyclerView Element zu klicken? Ich weiß, ich kann an Position das Element klicken 0 mit:Verwenden von Espresso, um innerhalb RecyclerView-Element zu klicken

onView(withId(R.id.recyclerView)) .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));

Aber ich muß innerhalb dieses Elements auf eine bestimmte Ansicht klicken und nicht auf dem Artikel selbst.

Vielen Dank im Voraus.

- bearbeiten -

genauer zu sein: Ich habe einen RecyclerView (R.id.recycler_view), die Artikel sind CardView (R.id.card_view). In jedem CardView habe ich vier Tasten (unter anderem) und ich möchte auf eine bestimmte Schaltfläche klicken (R.id.bt_deliver).

Ich möchte die neuen Funktionen von Espresso 2.0 verwenden, aber ich bin mir nicht sicher, ob das möglich ist.

nicht möglich, wenn, möchte ich so etwas wie diese (mit Thomas Keller-Code) verwenden:

onRecyclerItemView(R.id.card_view, ???, withId(R.id.bt_deliver)).perform(click()); 

aber ich weiß nicht, was auf den Fragezeichen zu setzen.

+0

Check [diese] (http://stackoverflow.com/a/27479995/4385913) –

+1

Hallo, Tanks für die schnelle Antwort! :-) Ich habe diese Frage gesehen, aber ich kann keine Hilfe finden, wie man ** RecyclerViewActions ** benutzt, um zu tun, was ich will. Soll ich die _Alte Antwort_ verwenden? Danke. –

+0

Haben Sie eine Lösung für Ihr Problem gefunden? – HowieH

Antwort

80

Sie können dies mit Aktion anpassen Aktion tun.

public class MyViewAction { 

    public static ViewAction clickChildViewWithId(final int id) { 
     return new ViewAction() { 
      @Override 
      public Matcher<View> getConstraints() { 
       return null; 
      } 

      @Override 
      public String getDescription() { 
       return "Click on a child view with specified id."; 
      } 

      @Override 
      public void perform(UiController uiController, View view) { 
       View v = view.findViewById(id); 
       v.performClick(); 
      } 
     }; 
    } 

} 

Dann können Sie es klicken

onView(withId(R.id.rv_conference_list)).perform(
      RecyclerViewActions.actionOnItemAtPosition(0, MyViewAction.clickChildViewWithId(R.id. bt_deliver))); 
+0

Die obige Antwort von Blade sollte die akzeptierte Antwort sein. – Peter

+2

Ich würde die Nullprüfung entfernen, so dass, wenn die untergeordnete Ansicht nicht gefunden wird, eine Ausnahme ausgelöst wird, anstatt nichts stillschweigend zu tun. –

+0

Danke für die Antwort. Aber in einem Problem getroffen. In der onPerform() - Funktion, wenn ich onView (withId()) -Funktion verwendet, dann wird die Funktion getroffen. Was ist der Grund für dieses Verhalten? – thedarkpassenger

-4

Geben Sie zunächst Ihre Schaltflächen eindeutige contentDescriptions, d. H. "Delivery Button Zeile 5".

<button android:contentDescription=".." />

dann Zeile bewegen:

onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.scrollToPosition(5));

Dann wählen die Ansicht basierend auf content.

onView(withContentDescription("delivery button row 5")).perform(click());

Inhalt Beschreibung ist eine gute Möglichkeit, Espressos OnView zu nutzen und Ihre App besser zugänglich zu machen.

+4

Die Inhaltsbeschreibung sollte _nicht_ so verwendet werden - es macht Ihre App nicht zugänglicher für Ansichten, um technische oder Debug-Informationen auszugeben für Benutzer mit besonderen Bedürfnissen - die CD dafür sollte wahrscheinlich so etwas wie "Order button" sein. 'withText (" Order ")' würde auch funktionieren und würde nicht erfordern, dass Sie zur Testzeit wissen, was Sie bestellen. – ataulm

38

Jetzt mit android.support.test.espresso.contrib es ist einfacher geworden:

1) test Abhängigkeit

androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.0') { 
    exclude group: 'com.android.support', module: 'appcompat' 
    exclude group: 'com.android.support', module: 'support-v4' 
    exclude module: 'recyclerview-v7' 
} 

* 3 Module ausschließen, weil sehr wahrscheinlich, dass Sie bereits haben

2) Dann tun Sie etwas wie

onView(withId(R.id.recycler_grid)) 
      .perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); 

Oder

onView(withId(R.id.recyclerView)) 
    .perform(RecyclerViewActions.actionOnItem(
      hasDescendant(withText("whatever")), click())); 

Oder

onView(withId(R.id.recycler_linear)) 
      .check(matches(hasDescendant(withText("whatever")))); 
+1

Dank, diese Module nicht auszuschließen, führt zu einem java.lang.IncompatibleClassChangeError für mich. – hboy

+4

und was zu tun, um zu klicken, sagen wir im fünften Punkt der Liste eine bestimmte Ansicht? In den mitgelieferten Beispielen sehe ich nur, wie man auf den fünften Gegenstand klickt oder auf den Gegenstand mit der Nachkommenansicht klickt, aber nicht beides zusammen, oder habe ich etwas übersehen? – donfuxx

+1

Ich musste tun 'Gruppe ausschließen: 'com.android.support' Modul ausschließen: 'Recyclerview-v7'' –

2

nächsten Ansatz versuchen:

onView(withRecyclerView(R.id.recyclerView) 
        .atPositionOnView(position, R.id.bt_deliver)) 
        .perform(click()); 

    public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) { 
      return new RecyclerViewMatcher(recyclerViewId); 
    } 

public class RecyclerViewMatcher { 
    final int mRecyclerViewId; 

    public RecyclerViewMatcher(int recyclerViewId) { 
     this.mRecyclerViewId = recyclerViewId; 
    } 

    public Matcher<View> atPosition(final int position) { 
     return atPositionOnView(position, -1); 
    } 

    public Matcher<View> atPositionOnView(final int position, final int targetViewId) { 

     return new TypeSafeMatcher<View>() { 
      Resources resources = null; 
      View childView; 

      public void describeTo(Description description) { 
       int id = targetViewId == -1 ? mRecyclerViewId : targetViewId; 
       String idDescription = Integer.toString(id); 
       if (this.resources != null) { 
        try { 
         idDescription = this.resources.getResourceName(id); 
        } catch (Resources.NotFoundException var4) { 
         idDescription = String.format("%s (resource name not found)", id); 
        } 
       } 

       description.appendText("with id: " + idDescription); 
      } 

      public boolean matchesSafely(View view) { 

       this.resources = view.getResources(); 

       if (childView == null) { 
        RecyclerView recyclerView = 
          (RecyclerView) view.getRootView().findViewById(mRecyclerViewId); 
        if (recyclerView != null) { 

         childView = recyclerView.findViewHolderForAdapterPosition(position).itemView; 
        } 
        else { 
         return false; 
        } 
       } 

       if (targetViewId == -1) { 
        return view == childView; 
       } else { 
        View targetView = childView.findViewById(targetViewId); 
        return view == targetView; 
       } 

      } 
     }; 
    } 
} 
Verwandte Themen