總體思路圖
總體設計思路
- Fragment:存放不同選項的頁面內容
- FragmentTabHost:點擊切換選項卡
- ViewPager:實現頁面的左右滑動效果
概念介紹
FragmentTabHost
用於實現點擊選項進行切換選項卡的自定義效果
使用FragmentTabHost,就是先用TabHost“裝着”Fragment,然後放進MainActivity裏面
ViewPager
- 定義
ViewPager是android擴展包v4包中的類
android.support.v4.view.ViewPager
- 作用
左右切換當前的view,實現滑動切換的效果
注:
1.ViewPager類直接繼承了ViewGroup類,和LinearLayout等佈局一樣,都是一個容器,需要在裏面添加我們想要顯示的內容。
2.ViewPager類需要PagerAdapter適配器類提供數據,與ListView類似
3.Google官方建議ViewPager配合Fragment使用
Fragment
- 定義
Fragment是activity的界面中的一部分或一種行爲
1.把Fragment認爲模塊化的一段activity
2.它具有自己的生命週期,接收它自己的事件,並可以在activity運行時被添加或刪除
3.Fragment不能獨立存在,它必須嵌入到activity中,而且Fragment的生命週期直接受所在的activity的影響。例如:當activity暫停時,它擁有的所有的Fragment們都暫停了,當activity銷燬時,它擁有的所有Fragment們都被銷燬。
- 作用
主要是爲了支持更動態、更靈活的界面設計(從3.0開始引入)
實現步驟
- 在主xml佈局裏面定義一個FragmentTabHost控件
- 定義底部菜單欄佈局
- 定義每個Fragment佈局
- 定義每個Fragment的Java類
- 定義適配器以關聯頁卡和ViewPage
- 定義MainActivity(具體實現請看註釋)
具體實現實例
步驟1:在主xml佈局裏面定義一個FragmentTabHost控件
主xml佈局:Main_tab_layout.xml
<?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:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" /><!--裝4個Fragment-->
<FrameLayout
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<!--定義FragmentTabHost控件-->
<android.support.v4.app.FragmentTabHost
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/black" ><!--裝4個Fragment-->
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" /><!--裝Tab的內容-->
</android.support.v4.app.FragmentTabHost>
</RelativeLayout>
步驟2:定義底部菜單欄佈局
tab_content.xml
一般是圖片在上,文字在下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:background="#ffffff">
<ImageView
android:id="@+id/tab_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tab_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="@drawable/selector_text_background" />
</LinearLayout>
步驟3:定義Fragment佈局
fragment_item1.xml&fragment_item2.xml
這裏使用兩個選項,由於fragment_item1.xml與fragment_item2.xml相同,這裏只貼出一個
fragment_item1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fragment1"
android:textSize="20sp"/>
</LinearLayout>
步驟4: 定義每個Fragment的Java類
1.這裏使用兩個選項:Fragment1.java&fragmen2.java
2.由於Fragment1.java&fragmen2.java相同,這裏只貼出一個
Fragment1.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment1 extends Fragment
{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item1, null);
return view;
}
}
步驟5: 定義適配器關聯頁卡和ViewPage
MyFragmentAdapter.java
package com.example.carson_ho.tab_menu_demo;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.List;
public class MyFragmentAdapter extends FragmentPagerAdapter{
List<Fragment> list;
public MyFragmentAdapter(FragmentManager fm,List<Fragment> list) {
super(fm);
this.list=list;
}//寫構造方法,方便賦值調用
@Override
public Fragment getItem(int arg0) {
return list.get(arg0);
}//根據Item的位置返回對應位置的Fragment,綁定item和Fragment
@Override
public int getCount() {
return list.size();
}//設置Item的數量
}
步驟6: 定義MainActivity
具體實現看註釋
MainActivity.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends FragmentActivity implements
ViewPager.OnPageChangeListener, TabHost.OnTabChangeListener {
private FragmentTabHost mTabHost;
private LayoutInflater layoutInflater;
private Class fragmentArray[] = { Fragment1.class, Fragment2.class };
private int imageViewArray[] = { R.drawable.tab_home_btn, R.drawable.tab_view_btn };
private String textViewArray[] = { "首頁", "分類"};
private List<Fragment> list = new ArrayList<Fragment>();
private ViewPager vp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化控件
initPage();//初始化頁面
}
// 控件初始化控件
private void initView() {
vp = (ViewPager) findViewById(R.id.pager);
/*實現OnPageChangeListener接口,目的是監聽Tab選項卡的變化,然後通知ViewPager適配器切換界面*/
/*簡單來說,是爲了讓ViewPager滑動的時候能夠帶着底部菜單聯動*/
vp.addOnPageChangeListener(this);//設置頁面切換時的監聽器
layoutInflater = LayoutInflater.from(this);//加載佈局管理器
/*實例化FragmentTabHost對象並進行綁定*/
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);//綁定tahost
mTabHost.setup(this, getSupportFragmentManager(), R.id.pager);//綁定viewpager
/*實現setOnTabChangedListener接口,目的是爲監聽界面切換),然後實現TabHost裏面圖片文字的選中狀態切換*/
/*簡單來說,是爲了當點擊下面菜單時,上面的ViewPager能滑動到對應的Fragment*/
mTabHost.setOnTabChangedListener(this);
int count = textViewArray.length;
/*新建Tabspec選項卡並設置Tab菜單欄的內容和綁定對應的Fragment*/
for (int i = 0; i < count; i++) {
// 給每個Tab按鈕設置標籤、圖標和文字
TabHost.TabSpec tabSpec = mTabHost.newTabSpec(textViewArray[i])
.setIndicator(getTabItemView(i));
// 將Tab按鈕添加進Tab選項卡中,並綁定Fragment
mTabHost.addTab(tabSpec, fragmentArray[i], null);
mTabHost.setTag(i);
mTabHost.getTabWidget().getChildAt(i)
.setBackgroundResource(R.drawable.selector_tab_background);//設置Tab被選中的時候顏色改變
}
}
/*初始化Fragment*/
private void initPage() {
Fragment1 fragment1 = new Fragment1();
Fragment2 fragment2 = new Fragment2();
list.add(fragment1);
list.add(fragment2);
//綁定Fragment適配器
vp.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(), list));
mTabHost.getTabWidget().setDividerDrawable(null);
}
private View getTabItemView(int i) {
//將xml佈局轉換爲view對象
View view = layoutInflater.inflate(R.layout.tab_content, null);
//利用view對象,找到佈局中的組件,並設置內容,然後返回視圖
ImageView mImageView = (ImageView) view
.findViewById(R.id.tab_imageview);
TextView mTextView = (TextView) view.findViewById(R.id.tab_textview);
mImageView.setBackgroundResource(imageViewArray[i]);
mTextView.setText(textViewArray[i]);
return view;
}
@Override
public void onPageScrollStateChanged(int arg0) {
}//arg0 ==1的時候表示正在滑動,arg0==2的時候表示滑動完畢了,arg0==0的時候表示什麼都沒做,就是停在那。
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}//表示在前一個頁面滑動到後一個頁面的時候,在前一個頁面滑動前調用的方法
@Override
public void onPageSelected(int arg0) {//arg0是表示你當前選中的頁面位置Postion,這事件是在你頁面跳轉完畢的時候調用的。
TabWidget widget = mTabHost.getTabWidget();
int oldFocusability = widget.getDescendantFocusability();
widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);//設置View覆蓋子類控件而直接獲得焦點
mTabHost.setCurrentTab(arg0);//根據位置Postion設置當前的Tab
widget.setDescendantFocusability(oldFocusability);//設置取消分割線
}
@Override
public void onTabChanged(String tabId) {//Tab改變的時候調用
int position = mTabHost.getCurrentTab();
vp.setCurrentItem(position);//把選中的Tab的位置賦給適配器,讓它控制頁面切換
}
}
效果圖: