2010-11-10 26 views
12

Mon application a un tabhost avec quatre onglets, et maintenant j'essaie de faire de jolies mises en page pour le mode paysage. Afin de faire usage de l'espace horizontal supplémentaire je veux mettre TabWidget sur le côté droit de l'écran, et de cource tous les onglets doivent être l'un sous l'autre (comme dans une colonne). Mais lorsque vous passez en mode paysage, tous les onglets sont alignés à la suite, cela semble plutôt moche. Comment réparer ça?android: orientation = "vertical" ne fonctionne pas pour 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

J'ai vraiment essayé d'obtenir des onglets verticaux à travaillez en utilisant tabhost/tabwidget. Je ne l'ai jamais eu à travailler. vous devrez probablement lancer votre propre onglet pour le faire. – Falmarri

+0

Je suis d'accord avec Falmarri. Cela doit être fait dans votre propre disposition personnalisée. TabHost n'est pas très agréable lorsque vous essayez de le personnaliser pour qu'il soit beau à la fois pour le portrait et le paysage. –

+0

Falmarri, Austyn Mahoney, merci pour l'explication. Existe-t-il un moyen réalisable de mettre en place son propre tabwidget? – aiboman

Répondre

4

TabHost ne supporte pas l'attribut d'orientation et des languettes ne peut être utilisé à l'horizontale.

+0

Merci beaucoup, Romain Guy – aiboman

+0

Merci beaucoup, Informations utiles 1+ pour cela. – Harshad

21

C'est ainsi que j'ai configuré le TabHost pour afficher les onglets sur la gauche de l'écran, avec les onglets empilés verticalement.

Il est nécessaire de configurer 2 configurations différentes pour l'activité, l'une en mode portrait («normal»), l'autre en mode paysage. Cela implique pas utilisez TabActivity.

J'ai copié la disposition utilisée par TabActivity dans mon propre projet et l'ai appelé main_view.xml (stocké dans res/layout). Ici, il est:

<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> 

Il faut réutiliser les ids Android onglets et tabcontent.

Dans le paysage, j'ai changé cela en inversant les attributs de hauteur de mise en page/largeur pour tous les contrôles et réglage de l'orientation des LinearLayout à l'horizontale (la TabWidget et FrameLayout doit être à côté de l'autre, à l'horizontale). Voici le résultat, dans res/mise en terre, aussi appelé 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> 

Notez que si vous voulez que les onglets à droite, vous mettez le TabWidget après la FrameLayout dans le fichier XML au dessus.

TabWidget est lui-même un LinearLayout. Notez que je n'ai pas défini l'orientation en XML. Ceci parce que TabWidget le fait dans son propre code (oui, il est codé en dur). Pour contrer cela, il faut redéfinir l'orientation dans le code. Voici comment je l'ai fait dans mon activité oncreate

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); 
} 

Comme TabHost est créé par setContentView, on doit appeler sa méthode de configuration explicitement.

La manière habituelle de créer un onglet est d'appeler:

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

La méthode setIndicator, en prenant une chaîne de titre et dessinable en tant que paramètres, crée une mise en page qui est valable uniquement en mode portrait. On doit créer sa propre vue et la donner à setIndicator.Il suffit de copier le TabSpec.LabelAndIconIndicatorStrategy.createIndicatorView code:

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 différence avec le code Google d'origine est que la mise en page de vue elle-même, la TextView et ImageView ids sont de notre propre application , pas les identifiants internes Android.

Pour le mode portrait, on peut réutiliser les tab_indicator.xml d'Android, que nous stockons dans res/mise en page:

<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> 

Encore une fois, cela est identique à XML Android d'origine, à l'exception des ids. Pour une version compatible paysage, nous devons inverser à nouveau les attributs largeur et hauteur de la mise en page. Ce qui nous donne dans res/mise en terre:

<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> 

(j'ai changé marginLeft et marginRight à marginTop et marginBottom mais ne suis pas sûr qu'il est utile)

Ces derniers fichiers XML de référence @ drawable/tab_indicator , donc nous devons le copier à partir du code source Android, ainsi que drawable/tab_selected.9.png, drawable/tab_unselected.9.png, drawable/tab_focus.9.png.

en train de créer un onglet devient:

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

EDIT: un projet de démonstration est disponible à l'adresse: VerticalTabHost on SkyDrive

+0

je fais comme vous dites, mais quand l'écran est horizontal, mon obtenir le résultat est que l'écran ne peut pas montrer tabWidget, seulement afficher tabContent – pengwang

+0

Avez-vous un moyen de publier votre projet? Je peux regarder et comparer avec le mien. – Timores

+0

pouvez-vous avoir un email, je peux vous envoyer un courriel, merci – pengwang

3

Alors, seulement important pense que vous devez faire est la suivante:

getTabWidget().setOrientation(LinearLayout.VERTICAL); 

Parce que TabWidget a codé en dur setOrientation(LinearLayout.HORIZONTAL); dans la méthode initTabWidget(). Je ne sais pas pourquoi.

+1

Quand je fais cela, mon TabWidget disparaît. – Davor