zoukankan      html  css  js  c++  java
  • Android

    Android - TabHost

    Overview

    TabHost 虽然早早的就被抛弃了,而且十分不灵活,但是还是值得我们学习的,虽然我们可能并不会用到它。

    TabHost的替代品有

    • FragmentTabHost
    • TabLayout(Material Design)

    效果图

    TabHost 效果图

    第一种实现方式 - 将所有的布局都放在一起

    Activity布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_table_host"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.it.reviewandroid.activity.ui.TableHostActivity">
    
        <TabHost
            android:id="@+id/navTH"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <!--
            在TabWidget外层一定要有一层布局来包裹他
            否则TabHost的显示样式会错乱
            -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
                <!--TabWidget的Id不能够更改-->
                <TabWidget
                    android:id="@android:id/tabs"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
                <!--注意FrameLayout的Id不能够更改-->
                <FrameLayout
                    android:id="@android:id/tabcontent"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
                    <!--第一个TAB1-->
                    <RelativeLayout
                        android:id="@+id/tab1RLayout"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">
    
                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_centerInParent="true"
                            android:text="Tab1"/>
                    </RelativeLayout>
                    <!--第一个TAB2-->
                    <RelativeLayout
                        android:id="@+id/tab2RLayout"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">
    
                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_centerInParent="true"
                            android:text="Tab2"/>
                    </RelativeLayout>
                    <!--第一个TAB3-->
                    <RelativeLayout
                        android:id="@+id/tab3RLayout"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">
    
                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_centerInParent="true"
                            android:text="Tab3"/>
                    </RelativeLayout>
                </FrameLayout>
            </LinearLayout>
        </TabHost>
    </LinearLayout>
    
    

    布局代码有点长...,但是其中关键的地方已经加上了注释。如果大家这样写比较臃肿的话,可以使用 include标签,将各个Tab 提取出来。

    Activity代码

    public class TableHostActivity extends AppCompatActivity {
    
        private TabHost mNavTH;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_table_host);
            initFindView();
            init();
        }
    
        void initFindView() {
            mNavTH = (TabHost) this.findViewById(R.id.navTH);
        }
    
        void init() {
    
            //在添加Tab之前需要调用此方法
            mNavTH.setup();
    
            //添加Tab
            mNavTH.addTab(mNavTH.newTabSpec("Tab1").setIndicator("New").setContent(R.id.tab1RLayout));
            mNavTH.addTab(mNavTH.newTabSpec("Tab2").setIndicator("Video").setContent(R.id.tab2RLayout));
            mNavTH.addTab(mNavTH.newTabSpec("Tab3").setIndicator("Music").setContent(R.id.tab3RLayout));
    		
            //切换Tab触发的事件
            mNavTH.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
                @Override
                public void onTabChanged(String tabId) {
                    Toast.makeText(TableHostActivity.this, tabId, Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    
    

    第二种实现方式 - 将Tab的布局提取出来

    我想第一种方式,应该不会有人用吧,毕竟布局代码都写在一个布局文件中实在不是一件令人赏心悦目的事情,所以,将每一个Tab独立出来是很有必要的。

    首先是Activity的布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_tab_host2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.it.reviewandroid.activity.ui.TabHost2Activity">
    
        <TabHost
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
                <TabWidget
                    android:id="@android:id/tabs"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
                <FrameLayout
                    android:id="@android:id/tabcontent"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"/>
            </LinearLayout>
        </TabHost>
    </LinearLayout>
    
    

    各个Tab的布局文件,因为所有的Tab都是类似,所以这里仅仅贴出了一个

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="Tab1"/>
    </RelativeLayout>
    
    

    Activity代码

    /**
     * 这里实现了TabHost.TabContentFactory,TabHost 将通过此接口来获得View
     */
    public class TabHost2Activity extends AppCompatActivity implements TabHost.TabContentFactory {
    
        View tab1;
        View tab2;
        View tab3;
    
        private TabHost mNavTH;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_tab_host2);
            mNavTH = (TabHost) this.findViewById(R.id.navTH);
            inflateView();
            init();
        }
    
        void inflateView() {
            LayoutInflater inflater = LayoutInflater.from(this);
            tab1 = inflater.inflate(R.layout.item_tabhost_tab1, null, false);
            tab2 = inflater.inflate(R.layout.item_tabhost_tab2, null, false);
            tab3 = inflater.inflate(R.layout.item_tabhost_tab3, null, false);
        }
    
        void init() {
            mNavTH.setup();
    
            mNavTH.addTab(mNavTH.newTabSpec("tab1").setIndicator("New").setContent(this));
            mNavTH.addTab(mNavTH.newTabSpec("tab2").setIndicator("Video").setContent(this));
            mNavTH.addTab(mNavTH.newTabSpec("tab3").setIndicator("Music").setContent(this));
        }
    
        @Override
        public View createTabContent(String tag) {
            switch (tag) {
                case "tab1":
                    return tab1;
                case "tab2":
                    return tab2;
                case "tab3":
                    return tab3;
            }
            return null;
        }
    }
    
    

    第三种实现方式 - Activity实现

    如果说第二种通过view 来实现的方式还是会让大量的代码都堆积在一个Activity中让你不痛快的话,不要紧,还有第三种方式,通过Activity来实现。

    首先还是布局代码,与第二中方式的布局代码相同

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_tab_host2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.it.reviewandroid.activity.ui.TabHost2Activity">
    
        <TabHost
            android:id="@+id/navTH"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
    
                <TabWidget
                    android:id="@android:id/tabs"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
    
                <FrameLayout
                    android:id="@android:id/tabcontent"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"/>
            </LinearLayout>
        </TabHost>
    </LinearLayout>
    
    

    建立需要的Activity

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_temp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.it.reviewandroid.activity.TempActivity">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="Activity1"/>
    </RelativeLayout>
    
    

    Activity的代码

    public class TabHost3Activity extends AppCompatActivity {
    
        private TabHost mNavTH;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_tab_host3);
            mNavTH = (TabHost) this.findViewById(R.id.navTH);
            init(savedInstanceState);
        }
    
        void init(Bundle saveInstanceState) {
            LocalActivityManager localActivityManager = new LocalActivityManager(this, true);
            localActivityManager.dispatchCreate(saveInstanceState);
            
            this.mNavTH.setup(localActivityManager);
    
            mNavTH.addTab(mNavTH.newTabSpec("Tab1").setIndicator("New").setContent(new Intent(this, TempActivity.class)));
            mNavTH.addTab(mNavTH.newTabSpec("Tab2").setIndicator("Video").setContent(new Intent(this, Temp2Activity.class)));
        }
    }
    
    遇到的异常

    在通过Activity的方式实现TahHost时出现了这个样的一个异常LocalActivymanager Activities can't be added until the containing group has been created. 后再StackOverFlow上找到了解决方案

    总结

    关于TabHost的使用已经结束,我们来回忆一下需要注意的地方

    1. TabHost 的布局问题
      1. TabWeight 和 Fragment 必须使用固定的Id不能够更改,Id分别是android.id.tabsandroid.id.tabcontent.
      2. TabWeight要有一层父布局来包裹
    2. 在添加Tab之前需要调用setUp 方法
    3. 使用TabHost时要注意LocalActivityManager的使用,需要调用setup(LocalActivityManager)
    4. 对LocalActivityManager进行设置dispatchCreate() 方法
  • 相关阅读:
    de1ctf_2019_weapon
    ciscn_2019_s_6
    用 Blend 给Windows Phone 应用创建 示例数据
    (转) Wp7 list 中列表项多样化的解决方案-Custom DataTemplateSelector
    Android开发之Java集合类性能分析
    WriteableBitmap 给透明的控件截图的问题
    VS 2013 配置OpenCV
    Cocos2d-x 版本小游戏 《是男人就下100层》 项目开源
    HEAP CORRUPTION DETECTED :after Normal block 错误
    Visual C++ 的代码折叠
  • 原文地址:https://www.cnblogs.com/slyfox/p/8723124.html
Copyright © 2011-2022 走看看