【Android】FragmentTabHost实现底部Tab菜单选项

以前实现类似微博底部菜单使用的是TabHost+Activity来实现,但是使用的时候提醒已经被弃用,现在我们可以通过FragmentTabHost+Fragment来实现。下面就是demo:

1.main_activity.xml 主布局文件。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical">  
    
    <FrameLayout   
        android:id="@+id/realtabcontent"  
        android:layout_width="match_parent"  
        android:layout_height="0dip"  
        android:layout_weight="1" />
  
    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content">  
     	 <FrameLayout  
            android:id="@android:id/tabcontent"  
            android:layout_width="0dp"  
            android:layout_height="0dp"  
            android:layout_weight="0" />      
    </android.support.v4.app.FragmentTabHost>

</LinearLayout>

2.fragment_1.xml 这个文件是其中一个fragment的布局文件,有多少个fragment可以分别创建它们的xml文件,这个demo当中的4个fragment布局一样,所以共用一个xml文件

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

    <TextView
        android:id="@+id/fragment_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80sp">
    </TextView>
    
    <EditText
        android:id="@+id/fragment_edit"
        android:layout_width="200dp"
        android:layout_height="wrap_content">
    </EditText>

</LinearLayout>

3.tab_item_view.xml  这个是Tab底部的每一个按钮的布局文件,显示了按钮的图标和对应文字

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:padding="3dp" 
        android:src="@drawable/ic_launcher">
    </ImageView>

    <TextView
        android:id="@+id/textview"       
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="首页"
        android:textSize="12sp">
    </TextView>

</LinearLayout>


4.tab_activity-btn.xml 设置按钮选中和不选中的照片,也是4个xml文件对应4个按钮,每个按钮两种状态,每种状态一张图片。

<?xml version="1.0" encoding="utf-8"?>  
<selector xmlns:android="http://schemas.android.com/apk/res/android">  
  
    <item android:drawable="@drawable/ic_nav_one_sel" android:state_selected="true"/>  
    <item android:drawable="@drawable/ic_nav_one_nor"/>  
  
</selector>


5.FragmentPage1.java,继承Fragment,用来管理其中的一个Tab的内容,demo底部有4个Tab,所以还创建了FragmentPage2.java,.FragmentPage3.java,.FragmentPage4.java

public class FragmentPage1 extends Fragment{  
	private EditText editText;
	private TextView textView;

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {      
    	System.out.println("onCreateView"); 
        return inflater.inflate(R.layout.fragment_1, container, false);
    }  

    @Override
	public void onActivityCreated(Bundle savedInstanceState) {
    	super.onActivityCreated(savedInstanceState);
    	System.out.println("onActivityCreated");
    	editText = (EditText)getActivity().findViewById(R.id.fragment_edit);
    	textView = (TextView)getActivity().findViewById(R.id.fragment_text);
   		textView.setText("1");
    }

}  


6.MainActivity.java,继承了FragmentActivity,用来管理上一步的fragment。

public class MainActivity extends FragmentActivity {
	//定义FragmentTabHost对象  
    private FragmentTabHost mTabHost;  
      
    //定义一个布局  
    private LayoutInflater layoutInflater;  
          
    //定义数组来存放Fragment界面  
    private Class fragmentArray[] = {FragmentPage1.class,FragmentPage2.class,FragmentPage3.class,FragmentPage4.class};  

    //定义数组来存放按钮图片  
    private int mImageViewArray[] = {R.drawable.tab_activity_btn,R.drawable.tab_news_btn,R.drawable.tab_organization_btn,  
                                     R.drawable.tab_more_btn};  
      
    //Tab选项卡的文字  
    private String mTextviewArray[] = {"活动", "资讯", "组织", "更多"};  
    
	 @Override  
	    protected void onCreate(Bundle savedInstanceState) {  
	        super.onCreate(savedInstanceState);  
	        setContentView(R.layout.activity_main);   
	        initView();  
	 }
	 
	    /** 
	     * 初始化组件 
	     */  
	    private void initView(){  
	        //实例化布局对象  
	        layoutInflater = LayoutInflater.from(this);  
	                  
	        //得到TabHost  
	        mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
	        //实例化TabHost对象
	        mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);   
	          
	        //得到fragment的个数  
	        int count = fragmentArray.length;     
	                  
	        //循环添加Tab页
	        for(int i = 0; i < count; i++){    
	            //为每一个Tab按钮设置tag和视图,newTabSpec的参数为tag标记,setIndicator设置Tab的显示视图
	            TabSpec tabSpec = mTabHost.newTabSpec(mTextviewArray[i]).setIndicator(getTabItemView(i));  
	            //将Tab添加进FragmentTabHost中  
	            mTabHost.addTab(tabSpec, fragmentArray[i], null);  
	        }  
	    }  
	    
	    /** 
	     * 给Tab按钮设置图标和文字 
	     */  
	    private View getTabItemView(int index){  
	        View view = layoutInflater.inflate(R.layout.tab_item_view, null);  
	      
	        ImageView imageView = (ImageView) view.findViewById(R.id.imageview);  
	        imageView.setImageResource(mImageViewArray[index]);  
	          
	        TextView textView = (TextView) view.findViewById(R.id.textview);          
	        textView.setText(mTextviewArray[index]);  
	      
	        return view;  
	    }  
	
}


7,优化:当我们在tab间切换时,之前fragment的布局会从新加载,我们看下fragment的生命周期,如下图:




我们在每次切换时,都会执行即将隐藏的fragment的onDestroyView()方法,准备显示的fragment的onCreateView方法。也就是每次切换时候都会从新加载布局,但是定义的全局变量并不会销毁(没有调用onDestroy方法),因此网上介绍的方式是用一个全局变量rootView来保存布局,切换fragment,会执行onCreateView()方法,我们就在里面判断rootView是否为空,不空即返回这个保存了的rootView即可,否则才从xml文件加载布局。添加生命周期打印函数以及优化后的fragment文件如下:

public class FragmentPage1 extends Fragment{  
	private EditText editText;
	private TextView textView;
	private View rootView;
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {      
    	System.out.println("onCreateView");
    	if(rootView == null){
    		rootView=inflater.inflate(R.layout.fragment_1, null);
    	}
    	
    	//缓存的rootView需要判断是否已经被加过parent, 如果有parent需要从parent删除,要不然会发生这个rootview已经有parent的错误。  
        ViewGroup parent = (ViewGroup) rootView.getParent();  
        if (parent != null) {  
            parent.removeView(rootView);  
        }   
        return inflater.inflate(R.layout.fragment_1, container, false);
    }  
    
    @Override
    public void onAttach(Activity activity) {
    	super.onAttach(activity);
    	System.out.println("onAttach");
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	System.out.println("onCreate");
    }
    
    @Override
	public void onActivityCreated(Bundle savedInstanceState) {
    	super.onActivityCreated(savedInstanceState);
    	System.out.println("onActivityCreated");
    	editText = (EditText)getActivity().findViewById(R.id.fragment_edit);
    	textView = (TextView)getActivity().findViewById(R.id.fragment_text);
   		textView.setText("1");
    }
    
    @Override
    public void onStart() {
    	super.onStart();
    	System.out.println("onStart");
    }
    
    @Override
    public void onResume() {
    	super.onResume();
    	System.out.println("onResume");
    }
    
    @Override
    public void onDestroy() {
    	super.onDestroy();
    	System.out.println("onDestroy");
    }
    
    @Override
    public void onDestroyView() {
    	super.onDestroyView();
    	System.out.println("onDestroyView");
    }
    
}  

运行效果如下:


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值