2010-11-10 7 views
12

La mia app ha un tabhost con quattro schede, e ora sto cercando di fare dei buoni layout per la modalità orizzontale. Per utilizzare lo spazio orizzontale aggiuntivo, desidero mettere TabWidget sul lato destro dello schermo, e di tutte le schede deve essere uno sotto l'altro (come in una colonna). Ma quando si passa alla modalità orizzontale tutte le schede vengono allineate in fila, sembra abbastanza brutto. Come risolverlo?android: orientation = "vertical" non funziona con TabWidget

Screenshot

<?xml version="1.0" encoding="utf-8"?> 
<TabHost xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/tabhost" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 
    <LinearLayout 

     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     > 

     <FrameLayout 
      android:id="@android:id/tabcontent" 
      android:layout_width="wrap_content" 
      android:layout_height="fill_parent" 
      android:layout_weight="1"> 

      <include layout="@layout/filter_wizard"/> 
      <include layout="@layout/filter_wizard"/> 
      <include layout="@layout/filter_wizard"/> 
      <include layout="@layout/filter_wizard"/> 

      </FrameLayout> 

      <TabWidget 
      android:background="#75ffffff" 
      android:id="@android:id/tabs" 
      android:layout_width="wrap_content" android:orientation="vertical" 
      android:layout_height="fill_parent" android:layout_weight="0" /> 



    </LinearLayout> 
</TabHost> 
+0

realtà ho cercato di ottenere schede verticali lavorare usando il tabhost/tabwidget. Non l'ho mai fatto funzionare. probabilmente dovrai visualizzare la tabulazione per farlo. – Falmarri

+0

Sono d'accordo con Falmarri. Questo deve essere fatto nel tuo layout personalizzato. TabHost non è molto bello quando si cerca di personalizzarlo per avere un bell'aspetto sia verticale che orizzontale. –

+0

Falmarri, Austyn Mahoney, grazie per la spiegazione. C'è un modo fattibile per implementare il proprio tabwidget? – aiboman

risposta

4

TabHost non supporta l'attributo orientamento e schede può essere utilizzato solo orizzontalmente.

+0

Grazie mille, Romain Guy – aiboman

+0

Grazie mille, Informazioni utili 1+ per quello. – Harshad

21

Ecco come ho impostato il TabHost per visualizzare le schede sulla sinistra dello schermo, con le schede sovrapposte verticalmente.

Uno ha bisogno di impostare 2 layout diversi per l'attività, uno in modalità ritratto ("normale"), uno in modalità orizzontale. Ciò implica a non utilizzare TabActivity.

Ho copiato il layout utilizzato da TabActivity nel mio progetto e l'ho chiamato main_view.xml (memorizzato in res/layout). Eccolo:

<TabHost xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/tabHost" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 
    <LinearLayout android:orientation="vertical" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent"> 
     <TabWidget android:id="@android:id/tabs" 
        android:layout_height="wrap_content" 
        android:layout_width="match_parent" 
        android:layout_weight="0" /> 
     <FrameLayout android:id="@android:id/tabcontent" 
        android:layout_width="match_parent" 
        android:layout_height="0dip" 
        android:layout_weight="1"/> 
    </LinearLayout> 
</TabHost> 

Bisogna riutilizzare gli ID Android schede e tabcontent.

Nel panorama, ho cambiato invertendo l'altezza la layout/attributi width per tutti i controlli e modificando l'orientamento del LinearLayout ad orizzontale (la TabWidget e FrameLayout devono essere uno accanto all'altro, in orizzontale). Ecco il risultato, in res/layout terra, chiamato anche main_view.xml:

<TabHost xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/tabHost" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 
    <LinearLayout android:orientation="horizontal" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent"> 
     <TabWidget android:id="@android:id/tabs" 
        android:layout_height="match_parent" 
        android:layout_width="wrap_content" 
        android:layout_weight="0" /> 
     <FrameLayout android:id="@android:id/tabcontent" 
        android:layout_height="match_parent" 
        android:layout_width="0dip" 
        android:layout_weight="1"/> 
    </LinearLayout> 
</TabHost> 

Si noti che se si desidera che le schede sulla destra, si inserisce il TabWidget dopo la FrameLayout in XML sopra.

TabWidget è esso stesso un LinearLayout. Si noti che non ho impostato l'orientamento in XML. Questo perché TabWidget lo fa nel proprio codice (sì, è hardcoded). Per contrastare questo, è necessario reimpostare l'orientamento nel codice. Ecco come ho fatto in

setContentView(R.layout.main_view); 

final TabHost tabHost = (TabHost) findViewById(R.id.tabHost); 
tabHost.setup(); 

Resources res = getResources(); 
Configuration cfg = res.getConfiguration(); 
boolean hor = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE; 

if (hor) { 
    TabWidget tw = tabHost.getTabWidget(); 
    tw.setOrientation(LinearLayout.VERTICAL); 
} 

Come si crea TabHost attraverso setContentView, si deve chiamare il suo metodo di impostazione OnCreate della mia attività in modo esplicito.

Il solito modo per creare una scheda è di chiamare:

tabHost.addTab(tabHost.newTabSpec("tab name").setIndicator("title", icon).setContent(...)); 

Il setIndicator metodo, prendendo una stringa titolo e un disegnabile come parametri, crea un layout che è valida solo in modalità verticale. Si deve creare la propria vista e darla a setIndicator.E 'sufficiente copiare il codice TabSpec.LabelAndIconIndicatorStrategy.createIndicatorView:

private View createIndicatorView(TabHost tabHost, CharSequence label, Drawable icon) { 

     LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

     View tabIndicator = inflater.inflate(R.layout.tab_indicator, 
       tabHost.getTabWidget(), // tab widget is the parent 
       false); // no inflate params 

     final TextView tv = (TextView) tabIndicator.findViewById(R.id.title); 
     tv.setText(label); 

     final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon); 
     iconView.setImageDrawable(icon); 

     return tabIndicator; 
    } 

La differenza con il codice originale di Google è che il layout di visualizzazione in sé, il TextView e ImageView ID vengono dalla nostra propria applicazione , non gli ID interni di Android.

Per la modalità ritratto, possiamo riutilizzare il tab_indicator.xml da Android, che memorizziamo in res/layout di:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="0dip" 
    android:layout_height="64dip" 
    android:layout_weight="1" 
    android:layout_marginLeft="-3dip" 
    android:layout_marginRight="-3dip" 
    android:orientation="vertical" 
    android:background="@drawable/tab_indicator"> 

    <ImageView android:id="@+id/icon" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
    /> 

    <TextView android:id="@+id/title" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     style="?android:attr/tabWidgetStyle" 
    /> 

</RelativeLayout> 

Ancora una volta, questo è identico al codice XML Android originale, fatta eccezione per gli ID. Per una versione che rispetta l'ambiente, dobbiamo invertire nuovamente gli attributi di larghezza e altezza del layout. Che ci dà in res/layout terra:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="64dip" 
    android:layout_height="0dip" 
    android:layout_weight="1" 
    android:layout_marginTop="-3dip" 
    android:layout_marginBottom="-3dip" 
    android:orientation="vertical" 
    android:background="@drawable/tab_indicator"> 

    <ImageView android:id="@+id/icon" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
    /> 

    <TextView android:id="@+id/title" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     style="?android:attr/tabWidgetStyle" 
    /> 
</RelativeLayout> 

(ho cambiato marginLeft e marginRight a marginTop e MarginBottom, ma non sono così sicuro che sia utile)

Questi ultimi file XML riferimento @ drawable/tab_indicator , quindi abbiamo bisogno di copiarlo dal codice sorgente Android, così come disegnabile/tab_selected.9.png, disegnabile/tab_unselected.9.png, disegnabile/tab_focus.9.png.

Ora la creazione di una scheda diventa:

tabHost.addTab(tabHost.newTabSpec(AllTabName) 
       .setIndicator(createIndicatorView(tabHost, "tab title", icon))) 
       .setContent(this)); 

EDIT: un progetto demo è disponibile all'indirizzo: VerticalTabHost on SkyDrive

+0

faccio come dici tu, ma quando lo schermo è orizzontale, il mio risultato è che lo schermo non può mostrare tabWidget, mostra solo tabContent – pengwang

+0

Hai un modo per pubblicare il tuo progetto? Posso dare un'occhiata e confrontarmi con la mia. – Timores

+0

puoi avere e-mail, posso inviarti un'email, grazie – pengwang

3

Quindi, importante solo pensare che si deve fare è questo:

getTabWidget().setOrientation(LinearLayout.VERTICAL); 

Perché TabWidget ha il codice di protezione setOrientation(LinearLayout.HORIZONTAL); nel metodo initTabWidget(). Non so perché.

+1

Quando lo faccio, il mio TabWidget scompare. – Davor