Android: orientation = "vertical" не работает для TabWidget

У моего приложения есть tabhost с четырьмя вкладками, и теперь я пытаюсь сделать красивые макеты для ландшафтного режима. Чтобы использовать дополнительное горизонтальное пространство, я хочу поместить TabWidget в правую сторону экрана, и, конечно, все вкладки должны быть под другим (например, в столбце). Но при переключении в альбомный режим все вкладки выравниваются в ряд, это выглядит довольно уродливо. Как это исправить?

Скриншот

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

Вот как я настраивал TabHost, чтобы отображать вкладки слева от экрана, при этом вкладки располагаются вертикально.

Нужно настроить два разных макета для активности, один в портретном («нормальном») режиме, один в альбомном режиме. Это означает, что нельзя использовать TabActivity.

Я скопировал макет, используемый TabActivity, в свой собственный проект и назвал его main_view.xml (сохраненный в res / layout). Вот:

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

Необходимо повторно использовать вкладки ids Android и tabcontent .

В ландшафте я изменил это, изменив атрибуты высоты / ширины макета для всех элементов управления и установив ориентацию LinearLayout на горизонтальную ( TabWidget и FrameLayout должны быть рядом друг с другом по горизонтали). Вот результат: res / layout-land, также называемый 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> 

Обратите внимание: если вы хотите, чтобы вкладки справа, вы кладете TabWidget после FrameLayout в XML выше.

TabWidget – это LinearLayout . Обратите внимание, что я не задал ориентацию в XML. Это потому, что TabWidget делает это в своем собственном коде (да, это жестко запрограммировано). Чтобы противостоять этому, нужно повторно установить ориентацию в коде. Вот как я это сделал в своей деятельности 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); } 

Поскольку TabHost создается через setContentView , нужно явно вызвать его метод установки.

Обычным способом создания вкладки является вызов:

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

Метод setIndicator , взяв строку заголовка и извлекаемую как параметры, создает макет, который действителен только в портретном режиме. Нужно создать собственное представление и дать ему setIndicator . Достаточно скопировать код 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; } 

Разница с исходным кодом Google заключается в том, что сам макет представления, идентификаторы TextView и ImageView – из нашего собственного приложения, а не из внутренних идентификаторов Android.

Для портретного режима мы можем повторно использовать tab_indicator.xml с Android, который мы сохраняем в res / layout:

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

Опять же, это идентично оригинальному Android XML, за исключением идентификаторов. Для удобной для ландшафта версии нам нужно снова изменить атрибуты ширины и высоты макета. Что дает нам в res / layout-land:

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

(Я изменил marginLeft и marginRight на marginTop и marginBottom, но я не уверен, что это полезно)

Эти последние XML-файлы ссылаются на @ drawable / tab_indicator, поэтому нам нужно скопировать их из исходного кода Android, а также drawable / tab_selected.9.png, drawable / tab_unselected.9.png, drawable / tab_focus.9.png.

Теперь создание вкладки будет:

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

EDIT: демонстрационный проект доступен по адресу: VerticalTabHost на SkyDrive

TabHost не поддерживает атрибут ориентации, а вкладки могут использоваться только по горизонтали.

Итак, важно только то, что вы должны это сделать:

 getTabWidget().setOrientation(LinearLayout.VERTICAL); 

Поскольку TabWidget имеет setOrientation(LinearLayout.HORIZONTAL); В initTabWidget() . Я не знаю, почему.

Здесь у меня есть аналогичное решение для просмотра вертикальной вкладки Tab

Просьба посетить эту ссылку: – как изменить макет в макете кадра при событии click?

Спасибо, Happpieeee, кодирование