Come aprire la scheda in Espresso
-
21-12-2019 - |
Domanda
Come posso aprire la scheda in Espresso test?Ho provato a fare Espresso.onView(ViewMatchers.withId(R.id.practice_results_tab)).perform(ViewActions.click());
, ma non funziona.In quel codice ho aperto Layout di questa scheda.C'è il file 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>
Quale ID devo utilizzare per aprire la scheda?
Errore nel 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}"
Soluzione
Codice completato
Hai davvero bisogno di aggiungere il codice per permetterci di dare una risposta corretta.Immagino che tu abbia utilizzato TabHost e TabWidget come fa questo esempio: https://maxalley.wordpress.com/2012/10/25/android-creating-a-tab-layout-with-tabhost-and-tabwidget/
Ho creato un progetto di esempio su https://github.com/hanscappelle/SO-25016397
La tua attività potrebbe quindi assomigliare a questa:
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);
}
}
Ho trovato un altro esempio di codice su https://maxalley.wordpress.com/2012/10/27/android-styling-the-tabs-in-a-tabwidget/ con un metodo helper che inietta un file ImageView
per le schede.
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;
}
Ora la cosa diventa interessante perché in questo modo possiamo facilmente impostare un ID o un tag su questi iniettati View
oggetti e utilizzarli in Espresso.
Una soluzione:Etichetta la vista
Se adatti l'helper per accettare un tag per ciascuna visualizzazione, il codice dell'helper sarà simile a questo:
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;
}
Se usi solo le icone puoi impostare l'ID anche su ImageView.
E il codice Espresso per fare clic su queste schede:
Espresso.onView(ViewMatchers.withTagValue(Matchers.is((Object)"tab1"))).perform(ViewActions.click());
Soluzione alternativa:utilizzando gli ID di visualizzazione
Se scegli gli ID, è necessario che questi ID siano definiti da qualche parte.Utilizza un semplice file di risorse Android con alcune definizioni di ID.
Il file di risorse dell'ID della vista, denominato /values/ids.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="tab1" type="id" />
</resources>
L'aiutante adattato:
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;
}
Se usi solo le icone puoi impostare l'ID anche su ImageView.
E il codice Espresso per fare clic su queste schede:
Espresso.onView(ViewMatchers.withId(R.id.tab1)).perform(ViewActions.click());
Informazioni su TabHost in generale
Perché hai utilizzato questo TabHost in primo luogo?Tieni presente che questa classe è ormai deprecata.UN ViewPager con schede O la barra delle azioni potrebbero essere opzioni migliori a seconda del caso d'uso.
Utilizzare lo strumento ViewHierarchy
In casi come questi il primo problema è spesso trovare la visuale corretta.Per questo utilizzare il Visualizza gerarchia attrezzo.Fa parte dell'SDK di Android e si trova nella directory degli strumenti.
Puoi avviarlo dalla riga di comando in questo modo:
cd ANDROID_SDK_LOCATION/tools
hierarchyviewer
Oppure utilizzare Studio Android menù:Strumenti > Android > Monitoraggio dispositivo Android.Quindi apri la prospettiva Vista gerarchia dal menu nel monitor del dispositivo:Finestra > Apri prospettiva > Vista gerarchia .
Preferisco la prima opzione solo perché Device Monitor fa troppo per le nostre intenzioni.
Ora utilizza la vista layout in combinazione con la vista Proprietà vista per trovare l'ID e i tag della vista che desideri.
Alcune istruzioni su questo strumento: http://developer.android.com/tools/debugging/debugging-ui.html
Altri suggerimenti
L'unica cosa che funziona per me è:
public void clickOnTab(String tabText) {
Matcher<View> matcher = allOf(withText(tabText),
isDescendantOfA(withId(R.id.ll_tab_container)));
onView(matcher).perform(click());
}
.
Dove ll_tab_container
è il linearloyout per il mio layout della scheda personalizzato.E se avessi una scheda chiamata "Shopping", allora lo passeresti come TABTEXT.
OnView (withtext ("Label etichetta")). Esegui (click ())
È anche possibile impostare un tag sul testo della scheda senza utilizzare un metodo indicatore personalizzato.Lo fai accedendo alla scheda TextView
della scheda dopo che è stato creato.
Utilizzo del MainActivity
dal codice di esempio di HCPL, che sembrerebbe qualcosa del genere:
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");
}
}
.
Poi nel test Espresso, è possibile accedere alle schede come questa:
onView(withTagValue(Matchers.is((Object)"TAG_TAB_TWO"))).perform(click());
.