Comment ouvrir l'onglet dans Espresso
-
21-12-2019 - |
Question
Comment puis-je ouvrir l’onglet dans le test Espresso ?j'ai essayé de faire Espresso.onView(ViewMatchers.withId(R.id.practice_results_tab)).perform(ViewActions.click());
, mais ça ne marche pas.Dans ce code, j'ai ouvert la mise en page de cet onglet.Il y a le fichier XML :
<TabHost
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/practice_tabHost">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TabWidget>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="@+id/practice_settings_tab"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/practice_results_tab"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
Quel identifiant dois-je utiliser pour ouvrir l'onglet ?
Erreur dans logcat :
Caused by: java.lang.RuntimeException: Action will not be performed because the target view does not match one or more of the following constraints:
at least 90 percent of the view's area is displayed to the user.
Target view: "LinearLayout{id=2131296384, res-name=practice_results_tab, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}"
La solution
Code terminé
Vous devez vraiment ajouter du code pour que nous puissions donner une réponse appropriée.Je suppose ici que vous avez utilisé un TabHost et un TabWidget de la même manière que cet exemple : https://maxalley.wordpress.com/2012/10/25/android-creating-a-tab-layout-with-tabhost-and-tabwidget/
J'ai créé un exemple de projet sur https://github.com/hanscappelle/SO-25016397
Votre activité pourrait alors ressembler à ceci :
public class MainActivity extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabHost tabHost = getTabHost();
// setNewTab(context, tabHost, tag, title, icon, contentID);
this.setNewTab(this, tabHost, "tab1", R.string.textTabTitle1, R.drawable.ic_tab_settings, R.id.practice_settings_tab);
this.setNewTab(this, tabHost, "tab2", R.string.textTabTitle2, R.drawable.ic_tab_results, R.id.practice_results_tab);
}
private void setNewTab(Context context, TabHost tabHost, String tag, int title, int icon, int contentID ){
TabSpec tabSpec = tabHost.newTabSpec(tag);
String titleString = getString(title);
tabSpec.setIndicator(titleString, context.getResources().getDrawable(android.R.drawable.star_on));
tabSpec.setContent(contentID);
tabHost.addTab(tabSpec);
}
}
J'ai trouvé un autre exemple de code sur https://maxalley.wordpress.com/2012/10/27/android-styling-the-tabs-in-a-tabwidget/ avec une méthode d'assistance qui injecte un ImageView
pour les onglets.
private View getTabIndicator(Context context, int title, int icon) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_layout, null);
ImageView iv = (ImageView) view.findViewById(R.id.imageView);
iv.setImageResource(icon);
TextView tv = (TextView) view.findViewById(R.id.textView);
tv.setText(title);
return view;
}
Maintenant, cela devient intéressant car de cette façon, nous pouvons facilement définir un identifiant ou un tag sur ceux injectés. View
objets et utilisez-les dans Espresso.
Une solution:Marquer la vue
Si vous adaptez cet assistant pour accepter une balise pour chaque vue, le code de l'assistant ressemblera à ceci :
private View getTabIndicator(Context context, int title, int icon, int viewId, String viewTag) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_layout, null);
ImageView iv = (ImageView) view.findViewById(R.id.image_view);
iv.setImageResource(icon);
TextView tv = (TextView) view.findViewById(R.id.text_view);
tv.setText(title);
tv.setTag(viewTag);
return view;
}
Si vous utilisez uniquement des icônes, vous pouvez également définir l'ID sur ImageView.
Et le code Espresso pour cliquer sur ces onglets :
Espresso.onView(ViewMatchers.withTagValue(Matchers.is((Object)"tab1"))).perform(ViewActions.click());
Solution alternative:utilisation des ID de vue
Si vous optez pour des identifiants, vous devez définir ces identifiants quelque part.Utilisez un simple fichier de ressources Android avec quelques définitions d'ID.
Le fichier de ressources d'ID de vue, nommé /values/ids.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="tab1" type="id" />
</resources>
L'aide adaptée :
private View getTabIndicator(Context context, int title, int icon, int viewId, String viewTag) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_layout, null);
ImageView iv = (ImageView) view.findViewById(R.id.image_view);
iv.setImageResource(icon);
TextView tv = (TextView) view.findViewById(R.id.text_view);
tv.setText(title);
tv.setId(viewId);
return view;
}
Si vous utilisez uniquement des icônes, vous pouvez également définir l'ID sur ImageView.
Et le code Espresso pour cliquer sur ces onglets :
Espresso.onView(ViewMatchers.withId(R.id.tab1)).perform(ViewActions.click());
À propos des TabHosts en général
Pourquoi avez-vous utilisé ce TabHost en premier lieu ?Notez que cette classe est désormais obsolète.UN ViewPager avec onglets ou la barre d'action pourrait être de meilleures options en fonction de votre cas d’utilisation.
Utiliser l'outil ViewHierarchy
Dans de tels cas, le premier problème est souvent de trouver la bonne vue.Pour cela, utilisez le Afficher la hiérarchie outil.Il fait partie du SDK Android et se trouve dans le répertoire tools.
Vous pouvez le démarrer depuis la ligne de commande comme ceci :
cd ANDROID_SDK_LOCATION/tools
hierarchyviewer
Ou utiliser Android Studio menu:Outils > Android > Moniteur d'appareil Android.Ensuite, ouvrez la perspective Vue hiérarchique à partir du menu du moniteur de périphérique :Fenêtre > Ouvrir la perspective > Vue hiérarchique .
Je préfère la première option simplement parce que Device Monitor en fait beaucoup trop pour nos intentions.
Utilisez maintenant la vue Mise en page en combinaison avec la vue Propriétés de la vue pour rechercher l'ID et les balises de la vue souhaitée.
Quelques instructions sur cet outil : http://developer.android.com/tools/debugging/debugging-ui.html
Autres conseils
la seule chose qui fonctionne pour moi c'est :
public void clickOnTab(String tabText) {
Matcher<View> matcher = allOf(withText(tabText),
isDescendantOfA(withId(R.id.ll_tab_container)));
onView(matcher).perform(click());
}
où ll_tab_container
est la disposition linéaire de ma disposition d'onglets personnalisée.et si vous aviez un onglet appelé "shopping", vous le transmettriez comme tabText.
onView(withText("L'étiquette de votre onglet")).perform(click())
Il est également possible de définir une balise sur le texte de votre onglet sans utiliser de méthode d'indicateur personnalisé.Pour ce faire, accédez à l'onglet TextView
après sa création.
En utilisant le MainActivity
à partir de l'exemple de code de hcpl, cela ressemblerait à ceci :
public MainActivity extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabHost tabHost = getTabHost();
// setNewTab(context, tabHost, tag, title, icon, contentID);
this.setNewTab(this, tabHost, "tab1", R.string.textTabTitle1, R.drawable.ic_tab_settings, R.id.practice_settings_tab);
this.setNewTab(this, tabHost, "tab2", R.string.textTabTitle2, R.drawable.ic_tab_results, R.id.practice_results_tab);
// Set custom tag on first tab
View tabView1 = tabHost.getTabWidget().getChildAt(0);
TextView tabView1Text = (TextView) signUpTabView.findViewById(android.R.id.title);
signUpTextTab.setTag("TAG_TAB_ONE");
// Set custom tag on second tab
View tabView2 = tabHost.getTabWidget().getChildAt(1);
TextView tabView1Text = (TextView) signUpTabView.findViewById(android.R.id.title);
signUpTextTab.setTag("TAG_TAB_TWO");
}
}
Ensuite, dans votre test Espresso, vous pourrez accéder aux onglets comme ceci :
onView(withTagValue(Matchers.is((Object)"TAG_TAB_TWO"))).perform(click());