android的Tabhost使用

来源:互联网 发布:云计算开发工程师面试 编辑:程序博客网 时间:2024/05/16 13:56

目前android流行的包含多个功能的网络应用的布局中,有一个类似于windws属性页的布局得到广泛应用,其效果大致类似于多窗口浏览器的标签页,多个activity通过不同的标签页在同一屏幕中显示和切换。这一效果大致是通过Tabhost和一些其他控件结合实现,当然也可以不通过Tabhost,使用ViewPager加一些button也可以实现大致的效果。

1.使用TabHost+ActivityGroup实现,ActivityGroup已经不再使用,这里使用别人写好的例子。参考:http://wazai.net/2114

承上篇文章Android TabHost Without TabActivity,在MainActivity中的TabHost加入頁籤。

?
1
2
3
mHost.addTab(mHost.newTabSpec(getString(R.string.tab_two_name))
                .setIndicator(getString(R.string.tab_two_name))
                .setContent(new Intent(this, ActivityGroup1.class)));

小蛙在測試了上面兩篇文章的方法後發現,必須要在ActivityGroup1中直接先載入Activity1(也就是ActivityGroup僅用來"操作"這些Activity,並沒有實質的內容呈現,如果讓ActivityGroup在這邊有自己的內容呈現,會造成Back Stack運作錯誤,也有可能是小蛙實作上出了問題,如果照著上面兩篇文章試不出來的網友,不妨參照小蛙的做法),以下是ActivityGroup1的程式碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class ActivityGroup1 extends ActivityGroup{
    /** 設定成 static 讓其他的子 Activity 可以存取 */
    public static ActivityGroup1 group;
    /** Back Stack */
    private ArrayList<View> history;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.history = new ArrayList<View>();
        group = this;
 
        // ActivityGroup1 只是一個外框,在這個外框中載入其他要用的 Activity
        // 如果沒有這個外框會發生錯誤
        View view = getLocalActivityManager()
                  .startActivity("Activity1",
                                  new Intent(ActivityGroup1.this, Activity1.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
                  .getDecorView();
        // 馬上載入真正要執行的 Activity
        replaceView(view);
    }
 
    /**
     * 在 ActivityGroup 中切換 Activity
     * @param v
     */
    public void replaceView(View v) {
        // 可在這插入換頁動畫
        history.add(v);
        setContentView(v);
    }
 
    /**
     * 當使用者按下 back 的時候,把之前存起來的 stack 撈回來顯示
     */
    public void back() {
        // 原本的範例是寫 > 0,但會發生錯誤
        if(history.size() > 1) {
            history.remove(history.size()-1);
            View v = history.get(history.size()-1);
            // 可在這插入換頁動畫
            setContentView(v);
        }else {
            // back stack 沒有其他頁面可顯示,直接結束
            finish();
        }
    }
    /**
     * 複寫聆聽按下 back 事件,呼叫 back()
     */
    // 由於我的股票精算師是使用1.6+,因此採用onKeyDown來監聽
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                back();
                break;
        }
        return true;
    }
}

至於在Activity1中的設定如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Activity1 extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity1);
        Button button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 如果沒有這個外框會發生錯誤
                View view = ActivityGroup1.group.getLocalActivityManager().startActivity("Activity2", new Intent(Activity1.this, Activity2.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)).getDecorView();
                // 載入真正要執行的 Activity
                ActivityGroup1.group.replaceView(view);
            }
        });
}

基本上到這邊就已經可以正常運作囉!有什麼問題可以留言在這邊,小蛙會盡可能的協助解決。


2.使用LocalActivityManager+TabHost,LocalActivityManager也是一个新版本已经不再使用,可见这一经典布局渊源流长,这里借用别人的代码说明,摘自:http://www.cnblogs.com/mybkn/articles/2507857.html

2012-05-07 更新)接續Android TabHost中切換Activity記錄了使用ActivityGroup達到在TabHost中切換Activity的方法,也在Android Screen Orientation Event螢幕方向處理+Acitivity Liftcycle記錄了當螢幕方向改變時的處理,這篇小蛙繼續記錄用FragmentActivity取代ActivityGroup,透過FragmentActivity內建的BackStack來管理倒退歷程。

MainTabActivity.java : 主要的Tabhost Activity。

 

复制代码
public class MainTabActivity extends Activity {    private TabHost mHost;    // 在Activity中使用Tabhost必須要有LocalActivityManager物件來設定    LocalActivityManager lam;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        // main layout採用預設的Tabhost        mHost = (TabHost) findViewById(android.R.id.tabhost);         lam = new LocalActivityManager(MainTabActivity.this, false);        lam.dispatchCreate(savedInstanceState);         mHost.setup(lam);        mHost.addTab(mHost.newTabSpec("Tab1").setIndicator("Tab1").setContent(new Intent(MainTabActivity.this, FragmentActivity1.class)));        mHost.addTab(mHost.newTabSpec("Tab2").setIndicator("Tab2").setContent(new Intent(MainTabActivity.this, FragmentActivity2.class)));    }    @Override    protected void onPause() {        // 漏掉這行一定出錯        lam.dispatchPause(isFinishing());        super.onPause();    }    @Override    protected void onResume() {        // 漏掉這行一定出錯        lam.dispatchResume();        super.onResume();    }}
复制代码

FragmentActivity1.java : 第一個Tab中用來管理Fragment的FragmentActivity。(2012-05-07更新)經由Jay留言後,小蛙詳細測了一下,發現FragmentActivity主畫面中的Button是沒辦法消失的(因為FragmentActivity的目的關係),因此改成這樣,讓FragmentActivity純粹當成容器,主要的內容還是以Fragment為主。(這個方法不是唯一,但是一個可行的方法,應該也有更好的做法!)

复制代码
public class FragmentActivity1 extends FragmentActivity {    public static FragmentManager fm;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.fragment_activity_1);        fm = getSupportFragmentManager();        // 只當容器,主要內容已Fragment呈現        initFragment(new Fragment1());    }    // 切換Fragment    public static void changeFragment(Fragment f){        changeFragment(f, false);    }    // 初始化Fragment(FragmentActivity中呼叫)    public static void initFragment(Fragment f){        changeFragment(f, true);    }    private static void changeFragment(Fragment f, boolean init){        FragmentTransaction ft = fm.beginTransaction();        ft.replace(R.id.simple_fragment, f);        if(!init)            ft.addToBackStack(null);        ft.commit();    }}
复制代码

Fragment1.java : 真正使用到的Fragment。

复制代码
public class Fragment1 extends Fragment {    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View v = inflater.inflate(R.layout.fragment_1, container, false);        Button tv = (Button)v.findViewById(R.id.button2);        tv.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                // 直接呼叫FragmentActivity1的靜態方法來做切換                FragmentActivity1.changeFragment(new Fragment2());            }        });        return v;    }}
复制代码

fragment_acitivity_1.xml : FragmentActivity layout。(2012-05-07修改) FragmentActivity只用來當容器,而不真正呈現內容(僅把Fragment內容載入)。

复制代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"    android:id="@+id/simple_fragment"></LinearLayout>
复制代码

fragment1.xml:Fragment layout,FragmentActivity載入的真正內容。

复制代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical">    <Button        android:id="@+id/button2"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Button" /></LinearLayout>
复制代码

最後別忘了在AndroidManifest.xml中加入android:configChanges="orientation"設定。這樣就成功的使用在Activity中使用Tabhost並且透過FragmentActivity來管理Fragment囉!

 

 3.TabHost+TabActivity实现,同样在新版本中不再支持。自己写了个实例研究。

public class addall extends TabActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.add_tool);Resources res = getResources(); // Resource object to get DrawablesTabHost tabHost = getTabHost(); // The activity TabHostTabHost.TabSpec spec; // Resusable TabSpec for each tabIntent intent; // Reusable Intent for each tab// Create an Intent to launch an Activity for the tab (to be reused)intent = new Intent().setClass(this, AppAppActivity.class);// Initialize a TabSpec for each tab and add it to the TabHostView good = (View) LayoutInflater.from(this).inflate(R.layout.tabmini, null);TextView text1 = (TextView) good.findViewById(R.id.tab_label);          text1.setText(R.string.total);  spec = tabHost.newTabSpec("good");//spec.setIndicator(null,res.getDrawable(R.drawable.ic_tab_artists));spec.setIndicator(good);spec.setContent(intent);tabHost.addTab(spec);// Do the same for the other tabsintent = new Intent().setClass(this, AppToolActivity.class);View tool = (View) LayoutInflater.from(this).inflate(R.layout.tabmini, null);TextView text2 = (TextView) tool.findViewById(R.id.tab_label);          text2.setText(R.string.tools); spec = tabHost.newTabSpec("tools");//spec.setIndicator(null,res.getDrawable(R.drawable.ic_tab_artists));spec.setIndicator(tool);spec.setContent(intent);tabHost.addTab(spec);tabHost.setCurrentTab(0);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}

<?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"        android:orientation="vertical"        android:padding="5dp" >        <TabWidget            android:id="@android:id/tabs"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:baselineAligned="true"            android:divider="@null"            android:dividerPadding="0dp"            android:tabStripEnabled="false"            android:showDividers="none|none"            />        <FrameLayout            android:id="@android:id/tabcontent"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:padding="0dp"            />    </LinearLayout></TabHost>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:layout_marginBottom="0dp"    android:background="@drawable/topbar_red"    android:gravity="bottom"    android:orientation="vertical"    android:paddingLeft="5dip"    android:paddingRight="5dip" >    <TextView        android:id="@+id/tab_label"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_gravity="center_horizontal|top"        android:background="#00000000"        android:gravity="center_horizontal|top"        android:textSize="@dimen/Medium_text_size"        android:textColor="#ffffffff"        android:textStyle="bold" />    <ImageView        android:id="@+id/imageView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="bottom|center_horizontal"        android:src="@drawable/tab_arrow" /></LinearLayout>


 4。TabHost+FragmentActivity,这个是目前官方建议的方式

public class MainActivity extends FragmentActivity {TabHost tHost;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tHost = (TabHost) findViewById(android.R.id.tabhost);tHost.setup();/** Setting tabchangelistener for the tab */tHost.setOnTabChangedListener(tabChangeListener);/** Defining tab builder for Andriod tab */TabHost.TabSpec tSpecAndroid = tHost.newTabSpec("Autognosis");tSpecAndroid.setIndicator("快速自诊",getResources().getDrawable(R.drawable.android));tSpecAndroid.setContent(new DummyTabContent(getBaseContext()));tHost.addTab(tSpecAndroid);/** Defining tab builder for Apple tab */TabHost.TabSpec tSpecApple = tHost.newTabSpec("Doctor");tSpecApple.setIndicator("求医问药",getResources().getDrawable(R.drawable.apple));tSpecApple.setContent(new DummyTabContent(getBaseContext()));tHost.addTab(tSpecApple);TabHost.TabSpec tSpecAndroid1 = tHost.newTabSpec("News");tSpecAndroid1.setIndicator("论坛新闻",getResources().getDrawable(R.drawable.android));tSpecAndroid1.setContent(new DummyTabContent(getBaseContext()));tHost.addTab(tSpecAndroid1);TabHost.TabSpec tSpecApple1 = tHost.newTabSpec("Center");tSpecApple1.setIndicator("我的中心",getResources().getDrawable(R.drawable.apple));tSpecApple1.setContent(new DummyTabContent(getBaseContext()));tHost.addTab(tSpecApple1);}@Overridepublic void onAttachedToWindow() {// TODO Auto-generated method stubsuper.onAttachedToWindow();}/** * Defining Tab Change Listener event. This is invoked when tab is * changed */private TabHost.OnTabChangeListener tabChangeListener = new TabHost.OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {android.support.v4.app.FragmentManager fm = getSupportFragmentManager();AutognosisFragment autognosisFragment = (AutognosisFragment) fm.findFragmentByTag("Autognosis");DoctorFragment doctorFragment = (DoctorFragment) fm.findFragmentByTag("Doctor");NewsFragment newsFragment = (NewsFragment) fm.findFragmentByTag("News");CenterFragment centerFragment = (CenterFragment) fm.findFragmentByTag("Center");FragmentTransaction ft = fm.beginTransaction();/** Detaches the applefragment if exists */if (autognosisFragment != null)ft.detach(autognosisFragment);/** Detaches the androidfragment if exists */if (doctorFragment != null)ft.detach(doctorFragment);/** Detaches the applefragment if exists */if (newsFragment != null)ft.detach(newsFragment);/** Detaches the applefragment if exists */if (centerFragment != null)ft.detach(centerFragment);/** If current tab is android */   if (tabId.equalsIgnoreCase("Autognosis")) {if (autognosisFragment == null) {/** * Create AndroidFragment and adding to fragmenttransaction */ft.add(R.id.realtabcontent, new AutognosisFragment(),"Autognosis");} else {/** * Bring to the front, if already exists in the * fragmenttransaction */ft.attach(autognosisFragment);}} else if (tabId.equalsIgnoreCase("Doctor")) {if (doctorFragment == null) {/** * Create AndroidFragment and adding to fragmenttransaction */ft.add(R.id.realtabcontent, new DoctorFragment(),"Doctor");} else {/** * Bring to the front, if already exists in the * fragmenttransaction */ft.attach(doctorFragment);}}else if (tabId.equalsIgnoreCase("News")) {if (newsFragment == null) {/** * Create AndroidFragment and adding to fragmenttransaction */ft.add(R.id.realtabcontent, new NewsFragment(),"News");} else {/** * Bring to the front, if already exists in the * fragmenttransaction */ft.attach(newsFragment);}}else if (tabId.equalsIgnoreCase("Center")) {if (centerFragment == null) {/** * Create AndroidFragment and adding to fragmenttransaction */ft.add(R.id.realtabcontent, new CenterFragment(),"Center");} else {/** * Bring to the front, if already exists in the * fragmenttransaction */ft.attach(centerFragment);}}else {}ft.commit();}};//@SuppressLint("ShowToast")public void BtnOnClick(View view) {// TODO Auto-generated method stubswitch (view.getId()) {case R.id.button1:case R.id.button2:        default:        Toast.makeText(MainActivity.this, "等待网络数据", Toast.LENGTH_LONG);break;}}

public class AutognosisFragment extends Fragment {private static final String TAG = "Activity";@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// TODO Auto-generated method stubreturn inflater.inflate(R.layout.autognosis, container, false);}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);}public interface onToast{       public void onToast();   }@SuppressLint("ShowToast")public void BtnOnClick(View view) {// TODO Auto-generated method stubonToast ot; switch (view.getId()) {case R.id.button1:case R.id.button2:        default:        Toast.makeText(getActivity(), "等待网络数据", Toast.LENGTH_LONG);break;}}}

public class DummyTabContent implements TabContentFactory{    private Context mContext;         public DummyTabContent(Context context){            mContext = context;    }                         @Override    public View createTabContent(String tag) {            View v = new View(mContext);            return v;    }    public void BtnOnClick(View view) {// TODO Auto-generated method stubswitch (view.getId()) {case R.id.button1:case R.id.button2:        default:        Toast.makeText(mContext, "等待网络数据", Toast.LENGTH_LONG);break;}}}

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/textView1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="快速自诊" />    <Button        android:id="@+id/button1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="BtnOnClick"        android:text="小儿感冒" />    <Button        android:id="@+id/button2"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="BtnOnClick"        android:text="颈椎不适" />    <Button        android:id="@+id/button3"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="BtnOnClick"        android:text="失眠" />    <Button        android:id="@+id/button4"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="BtnOnClick"        android:text="便秘" />    <Button        android:id="@+id/button5"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="BtnOnClick"        android:text="效果评价" /></LinearLayout>

5.也有人使用ActionBart和Fragment,其实本质还是TabHost了,摘自:http://blog.csdn.net/cs_lht/article/details/8090643

开始实现

创建FragmentActivity,总的代码如下:

[java] view plaincopy
  1. package com.example.fragmenttest;  
  2.   
  3. import android.app.ActionBar;  
  4. import android.app.ActionBar.Tab;  
  5. import android.app.ActionBar.TabListener;  
  6. import android.os.Bundle;  
  7. import android.support.v4.app.FragmentActivity;  
  8. import android.support.v4.view.ViewPager;  
  9. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  10. import android.util.Log;  
  11. import android.view.Menu;  
  12.   
  13. public class MainActivity extends FragmentActivity {  
  14.   
  15.     public final static int TAB_INDEX_TAB_1 = 0;  
  16.     public final static int TAB_INDEX_TAB_2 = 1;  
  17.     public final static int TAB_INDEX_TAB_3 = 2;  
  18.     public final static int TAB_INDEX_TAB_4 = 3;  
  19.     public final static int TAB_COUNT = 4;  
  20.   
  21.     private ViewPager mViewPager;  
  22.   
  23.     @Override  
  24.     public void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.activity_main);  
  27.   
  28.         // 创建Tab  
  29.         setupTest1();  
  30.         setupTest2();  
  31.         setupTest3();  
  32.         setupTest4();  
  33.         getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);  
  34.         getActionBar().setDisplayShowTitleEnabled(false);  
  35.         getActionBar().setDisplayShowHomeEnabled(false);  
  36.   
  37.         // 创建 view pager  
  38.         mViewPager = (ViewPager)findViewById(R.id.pager);  
  39.         getFragmentManager();  
  40.   
  41.         mViewPager.setAdapter(new TestViewPagerAdapter(getSupportFragmentManager()));  
  42.         mViewPager.setOnPageChangeListener(new TestPagerListener());  
  43.         mViewPager.setCurrentItem(TAB_INDEX_TAB_2);  
  44.     }  
  45.   
  46.     private void setupTest1(){  
  47.         Tab tab = this.getActionBar().newTab();  
  48.         tab.setContentDescription("Tab 1");  
  49.         tab.setText("Tab 1");  
  50.         tab.setTabListener(mTabListener);  
  51.         getActionBar().addTab(tab);  
  52.     }  
  53.   
  54.     private void setupTest2(){  
  55.         Tab tab = this.getActionBar().newTab();  
  56.         tab.setContentDescription("Tab 2");  
  57.         tab.setText("Tab 2");  
  58.         tab.setTabListener(mTabListener);  
  59.         getActionBar().addTab(tab);  
  60.     }  
  61.   
  62.     private void setupTest3(){  
  63.         Tab tab = this.getActionBar().newTab();  
  64.         tab.setContentDescription("Tab 3");  
  65.         tab.setText("Tab 3");  
  66.         tab.setTabListener(mTabListener);  
  67.         getActionBar().addTab(tab);  
  68.     }  
  69.   
  70.     private void setupTest4(){  
  71.         Tab tab = this.getActionBar().newTab();  
  72.         tab.setContentDescription("Tab 4");  
  73.         tab.setText("Tab 4");  
  74.         tab.setTabListener(mTabListener);  
  75.         getActionBar().addTab(tab);  
  76.     }  
  77.   
  78.     @Override  
  79.     public boolean onCreateOptionsMenu(Menu menu) {  
  80.         getMenuInflater().inflate(R.menu.activity_main, menu);  
  81.         return true;  
  82.     }  
  83.   
  84.     private final TabListener mTabListener = new TabListener() {  
  85.         private final static String TAG = "TabListener";  
  86.         @Override  
  87.         public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {  
  88.             // TODO Auto-generated method stub  
  89.             Log.d(TAG, "onTabReselected");  
  90.         }  
  91.   
  92.         @Override  
  93.         public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {  
  94.             // TODO Auto-generated method stub  
  95.             Log.d(TAG, "onTabSelected()");  
  96.             if (mViewPager != null)  
  97.                 mViewPager.setCurrentItem(tab.getPosition());  
  98.         }  
  99.   
  100.         @Override  
  101.         public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {  
  102.             // TODO Auto-generated method stub  
  103.             Log.d(TAG, "onTabUnselected()");  
  104.         }  
  105.     };  
  106.   
  107.     class TestPagerListener implements OnPageChangeListener{  
  108.         @Override  
  109.         public void onPageScrollStateChanged(int arg0) {  
  110.             // TODO Auto-generated method stub  
  111.         }  
  112.   
  113.         @Override  
  114.         public void onPageScrolled(int arg0, float arg1, int arg2) {  
  115.             // TODO Auto-generated method stub  
  116.         }  
  117.   
  118.         @Override  
  119.         public void onPageSelected(int arg0) {  
  120.             getActionBar().selectTab(getActionBar().getTabAt(arg0));  
  121.         }  
  122.     }  
  123. }  


setupTab*展示了如何获取ActionBar,如何创建和添加Tab组件到ActionBar中。

注意setTabListener这个接口,我们是必须设的,否则要报错,在看一下TabListener的实现,我们只在onTabSelected中写了一句代码,就是要求ViewPager显示出对应位置的Fragment。

oncreate 中的NAVIGATION_MODE_TABS定义了ActionBar的模式,后面两名是隐藏Tilte bar。

 

ViewPager是一个容器,用来放Fragment,我们需要在FragmentActivity中添加它,我加在layout文件中的:

[html] view plaincopy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.     <com.example.fragmenttest.TestViewPage  
  6.         android:id="@+id/pager"  
  7.         android:layout_width="match_parent"  
  8.         android:layout_height="match_parent"  
  9.         />  
  10. </RelativeLayout>  


TestViewPager是ViewPager的一个子类,实现代码如下:

[java] view plaincopy
  1. package com.example.fragmenttest;  
  2.   
  3. import android.content.Context;  
  4. import android.support.v4.view.ViewPager;  
  5. import android.util.AttributeSet;  
  6.   
  7. public class TestViewPage extends ViewPager{  
  8.       
  9.     public TestViewPage(Context context) {  
  10.         super(context);  
  11.     }  
  12.   
  13.     public TestViewPage(Context context, AttributeSet attrs) {  
  14.         super(context, attrs);  
  15.     }  
  16. }  

 

再看一下getFragmentManager()和getSupportFragmentManager()这两个接口,它们的区别是,前者调用Android框架的FragmentManger,后者是获取Android扩展库中的V4的Support FragmentManager,着为独立的APP只能用后者,原因android.jar包中没有前者的实现。

我们再看看TestViewPagerAdapter的代码:

[java] view plaincopy
  1. package com.example.fragmenttest;  
  2.   
  3. import android.support.v4.app.Fragment;  
  4. import android.support.v4.app.FragmentManager;  
  5. import android.support.v4.app.FragmentPagerAdapter;  
  6.   
  7. public class TestViewPagerAdapter extends FragmentPagerAdapter {  
  8.   
  9.     public TestViewPagerAdapter(FragmentManager fm) {  
  10.         super(fm);  
  11.         // TODO Auto-generated constructor stub  
  12.     }  
  13.   
  14.     @Override  
  15.     public Fragment getItem(int arg0) {  
  16.         // TODO Auto-generated method stub  
  17.         switch (arg0) {  
  18.         case MainActivity.TAB_INDEX_TAB_1:  
  19.             return new Tab1Fragment();  
  20.   
  21.         case MainActivity.TAB_INDEX_TAB_2:  
  22.             return new Tab2Fragment();  
  23.   
  24.         case MainActivity.TAB_INDEX_TAB_3:  
  25.             return new Tab3Fragment();  
  26.   
  27.         case MainActivity.TAB_INDEX_TAB_4:  
  28.             return new Tab4Fragment();  
  29.         }  
  30.   
  31.         throw new IllegalStateException("No fragment at position " + arg0);  
  32.     }  
  33.   
  34.     @Override  
  35.     public int getCount() {  
  36.         // TODO Auto-generated method stub  
  37.         return MainActivity.TAB_COUNT;  
  38.     }  
  39. }  


其实这个类就是关联ViewPager和Fragment,注意这些Index。

可能有的同学还是想看一下Fragment的实现:

[java] view plaincopy
  1. package com.example.fragmenttest;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v4.app.Fragment;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8.   
  9. public class Tab1Fragment extends Fragment {  
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         // TODO Auto-generated method stub  
  13.         super.onCreate(savedInstanceState);  
  14.     }  
  15.       
  16.     @Override  
  17.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  18.             Bundle savedInstanceState) {  
  19.         View fragmentView = inflater.inflate(R.layout.tab1_fragment_layout, container, false);  
  20.         return fragmentView;  
  21.     }  
  22. }  

 

android的界面技术还是很丰富的,一个重要的证明就是同一显示效果如果你愿意的话,常常能找到几十种实现的方法,即使是相同的类,相同的逻辑算法,不同的人使用,有时也会出现不同的实现方法。研究这些不同的实现方法,有时可以提升我们界面设计的素养,毕竟从可用,健壮,维护,优美的角度来看,同时考虑到andorid屏幕众多,版本升级频繁,硬件配置的差异,选择最好的界面实现方法也不算是孔已已!


一个需要注意的事实是,tabHost和TabWidget支持自定义布局,这使的他可能因为开发者或者设计师的创意而变的漂亮的不可想象从而让人无法确定他是不是使用了tabHost。选自:http://blog.csdn.net/west8623/article/details/7453814

大家好,今天我为大家分享TabHost中怎样修改TabWidget样式。在很多界面美观的应用中很多都用到了TabHost,但他们要比系统默认的要漂亮得多。先看几张图:


                             京东商城底部菜单栏


                            新浪微博底部菜单栏

   好了,看到这些漂亮的菜单栏是不是很惊讶,你可能会说用Button就可以实现啊 ,可是用Button的话控制显示的内容很麻烦,不如用TabHost控制效率更高。很想知道用TabHost是怎么实现的吧,下面就来研究如何实现这种漂亮的TabHost。先看一下效果图:

 

界面比较简单,要想做得漂亮换几张图片就可以了。

  第一步:先在布局(这里用了main.xml创建时自动生成的)里面放上TabHost ,只要将TabHost控件托至屏幕中就可:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.     <TabHost android:id="@+id/tabhost"   
  3.       android:layout_width="fill_parent"   
  4.       android:layout_height="fill_parent"   
  5.       xmlns:android="http://schemas.android.com/apk/res/android">  
  6.         <LinearLayout android:layout_width="fill_parent"   
  7.           android:id="@+id/linearLayout1"   
  8.           android:layout_height="fill_parent"   
  9.           android:orientation="vertical">  
  10.             <TabWidget android:layout_width="fill_parent"   
  11.               android:layout_height="wrap_content"   
  12.               android:id="@android:id/tabs"></TabWidget>  
  13.             <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@android:id/tabcontent">  
  14.                 <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab1"></LinearLayout>  
  15.                 <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab2"></LinearLayout>  
  16.                 <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/tab3"></LinearLayout>  
  17.             </FrameLayout>  
  18.         </LinearLayout>  
  19.     </TabHost>  


这里我们已经把LinearLayout和TextView去掉了,并将“xmlns:android="……" ”添加大TabHost里了,这里要注意我们将TabHost的id定义为自己定义的id比不用android规定的id="@android:id/tabhost"。

第二步:创建显示此TabWidget的布局tabmini.xml:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="40dp"  
  5.     android:paddingLeft="5dip"  
  6.     android:paddingRight="5dip"  
  7.     android:background="@drawable/head_bg">    
  8.       
  9.     <TextView android:id="@+id/tab_label"    
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:layout_centerInParent="true"  
  13.         android:gravity="center"  
  14.         android:textColor="#000000"  
  15.         android:textStyle="bold"  
  16.         android:background="@drawable/tabmini"/>   
  17. </RelativeLayout>  


第三步:创建一个selector在drawable里面 命名tabmini.xml,用来点击TabHost的一个tab时TextView的变化:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector  
  3.   xmlns:android="http://schemas.android.com/apk/res/android">  
  4.     <item android:state_selected="true"  
  5.         android:drawable="@drawable/add_managebg_down"/>  
  6.     <item android:state_selected="false"  
  7.         android:drawable="@drawable/add_managebg"/>  
  8. </selector>  


第四步:在Activity里实现TabHost:

[java] view plaincopy
  1. package cn.li.tabstyle;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.widget.TabHost;  
  8. import android.widget.TextView;  
  9.   
  10. public class TabHostStyleActivity extends Activity {  
  11.     /** Called when the activity is first created. */  
  12.     @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.main);  
  16.           
  17.         View niTab = (View) LayoutInflater.from(this).inflate(R.layout.tabmini, null);  
  18.         TextView text0 = (TextView) niTab.findViewById(R.id.tab_label);  
  19.         text0.setText("ni");  
  20.           
  21.         View woTab = (View) LayoutInflater.from(this).inflate(R.layout.tabmini, null);  
  22.         TextView text1 = (TextView) woTab.findViewById(R.id.tab_label);  
  23.         text1.setText("wo");  
  24.           
  25.         View taTab = (View) LayoutInflater.from(this).inflate(R.layout.tabmini, null);  
  26.         TextView text2 = (TextView) taTab.findViewById(R.id.tab_label);  
  27.         text2.setText("ta");  
  28.           
  29.         View weTab = (View) LayoutInflater.from(this).inflate(R.layout.tabmini, null);  
  30.         TextView text3 = (TextView) weTab.findViewById(R.id.tab_label);  
  31.         text3.setText("we");  
  32.           
  33.         TabHost tabHost = (TabHost)findViewById(R.id.tabhost);  
  34.         tabHost.setup();   //Call setup() before adding tabs if loading TabHost using findViewById().   
  35.           
  36.         tabHost.addTab(tabHost.newTabSpec("nitab").setIndicator(niTab).setContent(R.id.tab1));  
  37.         tabHost.addTab(tabHost.newTabSpec("wotab").setIndicator(woTab).setContent(R.id.tab2));  
  38.         tabHost.addTab(tabHost.newTabSpec("tatab").setIndicator(taTab).setContent(R.id.tab3));  
  39.         tabHost.addTab(tabHost.newTabSpec("wetab").setIndicator(weTab).setContent(R.id.tab4));  
  40.     }  
  41. }  


这里我们用findViewById创建了TabHost,这样的话我们就需要在添加tab时调用TabHost的setup()方法;这里我们添加内容时添加的是布局,我们完全可以换成自己创建的Activity。

好了,让我们来看看运行效果吧:



好了,我们自定义的TabHost算是结束了。不过看到Activity里的代码很多都是重复的我们可以这样把他们简化:

[java] view plaincopy
  1. package cn.li.tabstyle;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.widget.TabHost;  
  8. import android.widget.TextView;  
  9.   
  10. public class TabHostStyleActivity extends Activity {  
  11.     /** Called when the activity is first created. */  
  12.     String[] title = new String[]{"ni","wo","ta","we"};  
  13.     View userTab,articeTab,feedTab,weTab;  
  14.     View[] tabs = new View[]{userTab,articeTab,feedTab,weTab};  
  15.     int[] tabIds = new int[]{R.id.tab1,R.id.tab2,R.id.tab3,R.id.tab4};  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.           
  21.         TabHost tabHost = (TabHost)findViewById(R.id.tabhost);  
  22.         tabHost.setup();   //Call setup() before adding tabs if loading TabHost using findViewById().   
  23.           
  24.         for(int i=0;i<tabs.length;i++){  
  25.             tabs[i] = (View) LayoutInflater.from(this).inflate(R.layout.tabmini, null);  
  26.             TextView text = (TextView) tabs[i].findViewById(R.id.tab_label);  
  27.             text.setText(title[i]);              
  28.             tabHost.addTab(tabHost.newTabSpec(title[i]).setIndicator(tabs[i]).setContent(tabIds[i]));  
  29.         }  
  30.     }  



0 0
原创粉丝点击