深入浅出android/ophone UI实现水平布局的Tab控件

 

作者:anychen

标签: ophone android Tabhost TabWidget
OPhone开发评论(0) ┆ 阅读(2046)

Tab UI控件是非常常见、常用的导航UI组件,使用它能够很方便地迅速切换页面。甚为强大的android当然也少不了它,在android/ophone平台上也可以很方便地使用TabHost,TabWidget来实现你的Tab。有点遗憾的是目前系统自带的UI布局只能实现垂直方向的Tab UI, 在某些项目我们不免需要水平方向的Tab UI,如果你有这种需求你可以参考本文所介绍方法。本文所述方法参考API 源代码内部实现。
1预备知识:TabHost,TabWidget, TabSpec简介
TabHost:是整个Tab ui的布局容器实质上就是是一个扩展的FrameLayout,所有的Tab UI相关组件必须位于该布局里,必须包含的组件有:
      名为TabWidget的(选项卡组件布局)和选项卡内容容器
TabWidget:选项卡组件布局容器,实质上一个线性布局LinearLayout,所有Tab选项控件都放在这里,你可以使用tabHost.addTab(TabSpec tab       Spec)方法将不同的选项卡内容添加的选项卡布局容器中,或许你会有点迷糊这明明是TabSpec嘛,不要急接着看
TabSpec:是一个与选项卡相关描述文件,其内部包含了一个类型为View[更确切地说是RelativeLayout]的tabIndicator,这个tabIndicator就是选项卡对应的视图,当你在执行t         abHost.addTab(TabSpec tabSpec)时,内部会有个操作将此tabIndicator添加到TabWidget中:下面是摘自API的TabHost.java中关于addTab的一段代码
         public void addTab(TabSpec tabSpec) {
          //...
           mTabWidget.addView(tabIndicator);
           mTabSpecs.add(tabSpec);
             //...
        }
外加一个固定ID为 android:id="@android:id/tabcontent"的FrameLayout,用于容纳Tab选项卡对应的内容
2正题:一步一步编写水平方向的Tab:
第一步:改写你的tab_indicator:直接从SDK..\platforms\android-ndata\res\layout中:拷贝tab_indicator.xml命名为tab_indicator_horizontal.xml 存放于工程中layout目录中,并修改如下:

<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="0dip"
    android:layout_marginBottom="0dip"
    android:orientation="vertical"
    android:background="@drawable/tab_indicator_horizontal">

    <ImageView android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="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>

第二步:编写水平Tab选项卡显示状态背景:android:background="@drawable/tab_indicator_horizontal"
 同样直接从SDK..\platforms\android-ndata\res\drawable中直接拷贝tab_indicator.xml并命名为tab_indicator_horizontal.xml 存放于工程中drawable目录中,内容如下,很简单相信你应该明白是怎么回事,这个文件不需要改动,拿来就用:
 <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Non focused states -->
    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected" />
    <item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected" />

    <!-- Focused states -->
    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_focus" />
    <item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_focus" />

    <!-- Pressed -->
    <item android:state_pressed="true" android:drawable="@drawable/tab_press" />
</selector>
 说明:上面的drawable/tab_unselected,drawable/tab_selected实质就是图片,android本身提供的名为9patch的可拉伸自适应填充图,因为系统本身自带的是垂直方向的图,不适合在这里使用,你需要自己修改上述图片,为了简要说明这里直接使自定义图形来适配:
第三步:使用自定义图形来适配选项卡显示状态背景:
tab_focus.xml,其他如tab_unselected你亦可参照此格式自定义,这里不再重复简述
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient android:startColor="#88FF88" android:endColor="#55EE55"
            android:angle="0"/>
    <corners android:radius="6dp" />
</shape>

第四步:编写Tab ui布局main_tab_horizontal.xml:
注意下面图片使用的的定义,请自行修改
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:background="@drawable/style_theme"
 android:layout_width="fill_parent" android:layout_height="fill_parent">
 <TabHost android:id="@+id/tabHost" android:layout_width="fill_parent"
  android:layout_height="fill_parent" android:layout_weight="1">
  <!-- 水平方向的Tab -->
  <LinearLayout android:orientation="horizontal"
   android:layout_width="fill_parent" android:layout_height="fill_parent">
   <!-- Tab标签控件 注意ID的方式-->
   <TabWidget android:id="@android:id/tabs"
    android:layout_height="wrap_content" android:layout_width="wrap_content"
    android:layout_weight="0" />
    
   <!-- Tab 内容控件 注意ID的方式-->
   <FrameLayout android:id="@android:id/tabcontent"
    android:layout_height="fill_parent" android:layout_width="0dip"
    android:layout_weight="1">

    <!-- 使用垂直与水平ScrollView -->
    <HorizontalScrollView android:layout_width="wrap_content"
     android:layout_height="fill_parent" android:fillViewport="true">
     <LinearLayout android:id="@+id/id_tab_view1" android:orientation="horizontal"
      android:layout_width="fill_parent" android:layout_height="fill_parent">
      
      <ImageView android:layout_width="wrap_content"
       android:layout_height="wrap_content" android:layout_gravity="center_horizontal|center_vertical"
       android:src="@drawable/tree2" />
     </LinearLayout>
    </HorizontalScrollView>

    <HorizontalScrollView android:layout_width="wrap_content"
     android:layout_height="fill_parent" android:fillViewport="true">
     <LinearLayout android:id="@+id/id_tab_view2" android:orientation="horizontal"
      android:layout_width="fill_parent" android:layout_height="fill_parent">
      
      <ImageView android:layout_width="wrap_content"
       android:layout_height="wrap_content" android:layout_gravity="center_horizontal|center_vertical"
       android:src="@drawable/building3" />
     </LinearLayout>
    </HorizontalScrollView>
    <HorizontalScrollView android:id="@+id/id_tab_view3" android:layout_width="wrap_content"
     android:layout_height="fill_parent" android:fillViewport="true">
     <LinearLayout android:orientation="horizontal"
      android:layout_width="fill_parent" android:layout_height="fill_parent">
      
      <ImageView android:layout_width="wrap_content"
       android:layout_height="wrap_content" android:layout_gravity="center_horizontal|center_vertical"
       android:src="@drawable/building1" />
     </LinearLayout>
    </HorizontalScrollView>
    <HorizontalScrollView android:id="@+id/id_tab_view4" android:layout_width="wrap_content"
     android:layout_height="fill_parent" android:fillViewport="true">
     <LinearLayout android:orientation="horizontal"
      android:layout_width="fill_parent" android:layout_height="fill_parent">
      
      <ImageView android:layout_width="wrap_content"
       android:layout_height="wrap_content" android:layout_gravity="center_horizontal|center_vertical"
       android:src="@drawable/building2" />
     </LinearLayout>
    </HorizontalScrollView>
   </FrameLayout>
  </LinearLayout>
 </TabHost>
</LinearLayout>

第五步:编写测试代码:
 public class TestActivity extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main_tab_horizontal);
  parseHorizontalTab();
 }

 Drawable icon_tab_1, icon_tab_2, icon_tab_3, icon_tab_4;

 private void parseHorizontalTab() {
  // 注意下面的代码用的是android.R.id.tabhost,在布局中有2个ID参数是固定的需要使用固定的ID:
 
  // 选项卡:TabWidget->android:id/tabs
  // 选项内容:FrameLayout android:id="android:id/tabcontent"
  final TabHost tabHost = (TabHost) findViewById(R.id.tabHost);
  tabHost.setup();
  icon_tab_1 = this.getResources().getDrawable(R.drawable.icon1);
  icon_tab_2 = this.getResources().getDrawable(R.drawable.icon2);
  icon_tab_3 = this.getResources().getDrawable(R.drawable.icon3);
  icon_tab_4 = this.getResources().getDrawable(R.drawable.icon4);
  createHorizontalTab(tabHost);
 }

 private void createHorizontalTab(TabHost tabHost) {
  tabHost.addTab(tabHost
    .newTabSpec("tab1")
    .setIndicator(
      createIndicatorView(this, tabHost, icon_tab_1, "tab1"))
    .setContent(R.id.id_tab_view1));
  tabHost.addTab(tabHost
    .newTabSpec("tab2")
    .setIndicator(
      createIndicatorView(this, tabHost, icon_tab_2, "tab2"))
    .setContent(R.id.id_tab_view2));

  tabHost.addTab(tabHost
    .newTabSpec("tab3")
    .setIndicator(
      createIndicatorView(this, tabHost, icon_tab_3, "tab3"))
    .setContent(R.id.id_tab_view3));
  tabHost.addTab(tabHost
    .newTabSpec("tab4")
    .setIndicator(
      createIndicatorView(this, tabHost, icon_tab_4, "tab4"))
    .setContent(R.id.id_tab_view4));

  TabWidget tw = tabHost.getTabWidget();
  tw.setOrientation(LinearLayout.VERTICAL);//注意在此处设置此参数 使TAB 垂直布局
 }
 
 /**
  * 创建自定义的 选项卡视图
  *
  * @param context
  * @param tabHost
  * @param icon
  * @return
  */
 private View createIndicatorView(Context context, TabHost tabHost,
   Drawable icon, String title) {

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

  View tabIndicator = inflater.inflate(R.layout.tab_indicator_horizontal,
    tabHost.getTabWidget(), false);

  final ImageView iconView = (ImageView) tabIndicator
    .findViewById(R.id.icon);
  final TextView titleView = (TextView) tabIndicator
    .findViewById(R.id.title);
  titleView.setText(title);
  iconView.setImageDrawable(icon);
  return tabIndicator;
 }
 
}

结束:运行效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值