【Android進階】實現各種各樣的Tab切換效果
阿新 • • 發佈:2019-01-03
一、View + ViewPager
使用ViewPager和View實現切換效果,效果如下:
主佈局介面:
top.xml<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include layout="@layout/top"/> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_weight="1" android:layout_height="0dp" /> <include layout="@layout/bottom"/> </LinearLayout>
bottom.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="45dp" android:gravity="center" android:background="@drawable/title_bar" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="微信" android:textColor="#ffffff" android:gravity="center" android:textSize="20sp"/> </LinearLayout>
我們在這裡給LinearLayout設定了點選監聽,但是它的子元素ImageButton會攔截掉這個點選事件,但是ImageButton並沒有處理點選事件,所以點選ImageButton時沒有效果,所以這裡把clickable設定為false<?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="55dp" android:background="@drawable/bottom_bar" android:orientation="horizontal" > <LinearLayout android:id="@+id/id_tab_chat" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center"> <ImageButton android:id="@+id/id_tab_chat_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:src="@drawable/tab_weixin_pressed" android:background="#00000000"/> <TextView android:text="微信" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff"/> </LinearLayout> <LinearLayout android:id="@+id/id_tab_friend" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center"> <ImageButton android:id="@+id/id_tab_friend_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:src="@drawable/tab_find_frd_normal" android:background="#00000000"/> <TextView android:text="朋友" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff"/> </LinearLayout> <LinearLayout android:id="@+id/id_tab_address" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center"> <ImageButton android:id="@+id/id_tab_address_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:src="@drawable/tab_address_normal" android:background="#00000000"/> <TextView android:text="通訊錄" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff"/> </LinearLayout> <LinearLayout android:id="@+id/id_tab_settings" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:gravity="center"> <ImageButton android:id="@+id/id_tab_settings_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:src="@drawable/tab_settings_normal" android:background="#00000000"/> <TextView android:text="設定" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff"/> </LinearLayout> </LinearLayout>
MainActivity.java
/**
* ViewPager實現主介面製作,使用View
*/
public class MainActivity extends Activity implements OnClickListener{
private ViewPager viewPager;
private PagerAdapter adapter;
private List<View> mViews = new ArrayList<View>();
private LinearLayout mTabWeixin;
private LinearLayout mTabFriends;
private LinearLayout mTabAddress;
private LinearLayout mTabSettings;
private ImageButton mWeixinImg;
private ImageButton mFriendsImg;
private ImageButton mAddressImg;
private ImageButton mSettingsImg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
initEvent();
}
private void initEvent() {
// 設定事件
mTabAddress.setOnClickListener(this);
mTabFriends.setOnClickListener(this);
mTabSettings.setOnClickListener(this);
mTabWeixin.setOnClickListener(this);
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
//ViewPager 改變時改變圖示的顏色
@Override
public void onPageSelected(int arg0) {
int currentItem = viewPager.getCurrentItem();
resetImg();
switch (currentItem) {
case 0:
mWeixinImg.setImageResource(R.drawable.tab_weixin_pressed);
break;
case 1:
mFriendsImg.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case 2:
mAddressImg.setImageResource(R.drawable.tab_address_pressed);
break;
case 3:
mSettingsImg.setImageResource(R.drawable.tab_settings_pressed);
break;
default:
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
private void initView() {
viewPager = (ViewPager)findViewById(R.id.viewpager);
mTabWeixin = (LinearLayout)findViewById(R.id.id_tab_chat);
mTabAddress = (LinearLayout)findViewById(R.id.id_tab_address);
mTabFriends = (LinearLayout)findViewById(R.id.id_tab_friend);
mTabSettings = (LinearLayout)findViewById(R.id.id_tab_settings);
mWeixinImg = (ImageButton)findViewById(R.id.id_tab_chat_btn);
mFriendsImg = (ImageButton)findViewById(R.id.id_tab_friend_btn);
mAddressImg = (ImageButton)findViewById(R.id.id_tab_address_btn);
mSettingsImg = (ImageButton)findViewById(R.id.id_tab_settings_btn);
LayoutInflater inflater = LayoutInflater.from(this);
View tab01 = inflater.inflate(R.layout.tab01, null);
View tab02 = inflater.inflate(R.layout.tab02, null);
View tab03 = inflater.inflate(R.layout.tab03, null);
View tab04 = inflater.inflate(R.layout.tab04, null);
mViews.add(tab01);
mViews.add(tab02);
mViews.add(tab03);
mViews.add(tab04);
//建立ViewPager的 PageAdapter
adapter = new PagerAdapter() {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// 銷燬View
container.removeView(mViews.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 初始化View
View view = mViews.get(position);
container.addView(view);
return view;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getCount() {
return mViews.size();
}
};
viewPager.setAdapter(adapter);
}
@Override
public void onClick(View v) {
// 點選底部按鈕時切換頁面並改變圖示顏色
switch (v.getId()) {
case R.id.id_tab_chat:
viewPager.setCurrentItem(0);
mWeixinImg.setImageResource(R.drawable.tab_weixin_pressed);
break;
case R.id.id_tab_friend:
viewPager.setCurrentItem(1);
mFriendsImg.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case R.id.id_tab_address:
viewPager.setCurrentItem(2);
mAddressImg.setImageResource(R.drawable.tab_address_pressed);
break;
case R.id.id_tab_settings:
viewPager.setCurrentItem(3);
mSettingsImg.setImageResource(R.drawable.tab_settings_pressed);
break;
default:
break;
}
}
//將所有的圖片都變暗
private void resetImg(){
mWeixinImg.setImageResource(R.drawable.tab_weixin_normal);
mAddressImg.setImageResource(R.drawable.tab_address_normal);
mFriendsImg.setImageResource(R.drawable.tab_find_frd_normal);
mSettingsImg.setImageResource(R.drawable.tab_settings_normal);
}
}
View 比較簡單,就是一個TextView,這裡不貼程式碼了。
二、FragmentManager + Fragment
使用FragmentManager來 切換Fragment,通過 add hide show 方法來新增顯示和隱藏Fragment,沒有直接使用replace方法,每次銷燬建立會比較浪費資源。效果如下,只可以點選切換,不可以滑動切換:
介面佈局和上面大體一樣,不過View換成了Fragment
主佈局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/top"/>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</FrameLayout>
<include layout="@layout/bottom"/>
</LinearLayout>
Fragment 佈局介面:
<?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:orientation="vertical"
android:gravity="center">
<TextView
android:text="this is first tab"
android:textSize="24dp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Fragment 程式碼
public class WeixinFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.tab01, container,false);
}
}
其他Fragment類似,就是名字不一樣
MainActivity.java
public class MainActivity extends FragmentActivity implements OnClickListener{
private LinearLayout mTabWeixin;
private LinearLayout mTabFriends;
private LinearLayout mTabAddress;
private LinearLayout mTabSettings;
private ImageButton mWeixinImg;
private ImageButton mFriendsImg;
private ImageButton mAddressImg;
private ImageButton mSettingsImg;
private Fragment tab001;
private Fragment tab002;
private Fragment tab003;
private Fragment tab004;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
initEvent();
}
private void initView() {
mTabWeixin = (LinearLayout)findViewById(R.id.id_tab_chat);
mTabAddress = (LinearLayout)findViewById(R.id.id_tab_address);
mTabFriends = (LinearLayout)findViewById(R.id.id_tab_friend);
mTabSettings = (LinearLayout)findViewById(R.id.id_tab_settings);
mWeixinImg = (ImageButton)findViewById(R.id.id_tab_chat_btn);
mFriendsImg = (ImageButton)findViewById(R.id.id_tab_friend_btn);
mAddressImg = (ImageButton)findViewById(R.id.id_tab_address_btn);
mSettingsImg = (ImageButton)findViewById(R.id.id_tab_settings_btn);
//設定預設選中第0頁
setSelect(0);
}
private void initEvent() {
// 設定事件
mTabAddress.setOnClickListener(this);
mTabFriends.setOnClickListener(this);
mTabSettings.setOnClickListener(this);
mTabWeixin.setOnClickListener(this);
}
@Override
public void onClick(View v) {
//點選是預設所有圖片都變暗
resetImg();
switch (v.getId()) {
case R.id.id_tab_chat:
setSelect(0);
break;
case R.id.id_tab_friend:
setSelect(1);
break;
case R.id.id_tab_address:
setSelect(2);
break;
case R.id.id_tab_settings:
setSelect(3);
break;
default:
break;
}
}
//設定選中第幾頁,使用FragmentManager進行控制
private void setSelect(int i){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
hideFragment(transaction);
//改變內容區域,把圖片設定為亮的
switch (i) {
case 0:
if(tab001 == null){
tab001 = new WeixinFragment();
//新增Fragment到 container
transaction.add(R.id.container, tab001);
}else{
//顯示Fragment
transaction.show(tab001);
}
//更改圖片
mWeixinImg.setImageResource(R.drawable.tab_weixin_pressed);
break;
case 1:
if(tab002 == null){
tab002 = new FriendsFragment();
transaction.add(R.id.container, tab002);
}else{
transaction.show(tab002);
}
mFriendsImg.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case 2:
if(tab003 == null){
tab003 = new AddressFragment();
transaction.add(R.id.container, tab003);
}else{
transaction.show(tab003);
}
mAddressImg.setImageResource(R.drawable.tab_address_pressed);
break;
case 3:
if(tab004 == null){
tab004 = new SettingsFragment();
transaction.add(R.id.container, tab004);
}else{
transaction.show(tab004);
}
mSettingsImg.setImageResource(R.drawable.tab_settings_pressed);
break;
default:
break;
}
//提交事務
transaction.commit();
}
//隱藏所有的Fragment
private void hideFragment(FragmentTransaction transaction) {
if(tab001 != null){
transaction.hide(tab001);
}
if(tab002 != null){
transaction.hide(tab002);
}
if(tab003 != null){
transaction.hide(tab003);
}
if(tab004 != null){
transaction.hide(tab004);
}
}
//將所有的圖片都變暗
private void resetImg(){
mWeixinImg.setImageResource(R.drawable.tab_weixin_normal);
mAddressImg.setImageResource(R.drawable.tab_address_normal);
mFriendsImg.setImageResource(R.drawable.tab_find_frd_normal);
mSettingsImg.setImageResource(R.drawable.tab_settings_normal);
}
}
三、ViewPager + Fragment
使用ViewPager + Fragment 來進行Tab頁的製作,不但可以點選,也可以進行滑動切換,這也是最常用的模式,最推薦使用的模式。效果:
佈局檔案和上面類似,主佈局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/top"/>
<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<include layout="@layout/bottom"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends FragmentActivity implements OnClickListener{
private ViewPager viewPager;
private FragmentPagerAdapter mAdapter;
private List<Fragment> mFragments = new ArrayList<Fragment>();
private LinearLayout mTabWeixin;
private LinearLayout mTabFriends;
private LinearLayout mTabAddress;
private LinearLayout mTabSettings;
private ImageButton mWeixinImg;
private ImageButton mFriendsImg;
private ImageButton mAddressImg;
private ImageButton mSettingsImg;
Fragment tab001;
Fragment tab002;
Fragment tab003;
Fragment tab004;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
initEvent();
}
private void initView() {
viewPager = (ViewPager)findViewById(R.id.container);
mTabWeixin = (LinearLayout)findViewById(R.id.id_tab_chat);
mTabAddress = (LinearLayout)findViewById(R.id.id_tab_address);
mTabFriends = (LinearLayout)findViewById(R.id.id_tab_friend);
mTabSettings = (LinearLayout)findViewById(R.id.id_tab_settings);
mWeixinImg = (ImageButton)findViewById(R.id.id_tab_chat_btn);
mFriendsImg = (ImageButton)findViewById(R.id.id_tab_friend_btn);
mAddressImg = (ImageButton)findViewById(R.id.id_tab_address_btn);
mSettingsImg = (ImageButton)findViewById(R.id.id_tab_settings_btn);
tab001 = new WeixinFragment();
tab002 = new FriendsFragment();
tab003 = new AddressFragment();
tab004 = new SettingsFragment();
mFragments.add(tab001);
mFragments.add(tab002);
mFragments.add(tab003);
mFragments.add(tab004);
mAdapter = new FragmentPagerAdapter( getSupportFragmentManager()) {
@Override
public int getCount() {
return mFragments.size();
}
@Override
public Fragment getItem(int arg0) {
return mFragments.get(arg0);
}
};
viewPager.setAdapter(mAdapter);
}
private void initEvent() {
// 設定事件
mTabAddress.setOnClickListener(this);
mTabFriends.setOnClickListener(this);
mTabSettings.setOnClickListener(this);
mTabWeixin.setOnClickListener(this);
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
//當前選中的Fragment 下標
int currentItem = viewPager.getCurrentItem();
//把圖片全設定為暗的
resetImg();
switch (currentItem) {
case 0:
mWeixinImg.setImageResource(R.drawable.tab_weixin_pressed);
break;
case 1:
mFriendsImg.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case 2:
mAddressImg.setImageResource(R.drawable.tab_address_pressed);
break;
case 3:
mSettingsImg.setImageResource(R.drawable.tab_settings_pressed);
break;
default:
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
@Override
public void onClick(View v) {
resetImg();
switch (v.getId()) {
case R.id.id_tab_chat:
setSelect(0);
break;
case R.id.id_tab_friend:
setSelect(1);
break;
case R.id.id_tab_address:
setSelect(2);
break;
case R.id.id_tab_settings:
setSelect(3);
break;
default:
break;
}
}
private void setSelect(int i){
//改變內容區域,把圖片設定為亮的
switch (i) {
case 0:
mWeixinImg.setImageResource(R.drawable.tab_weixin_pressed);
break;
case 1:
mFriendsImg.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case 2:
mAddressImg.setImageResource(R.drawable.tab_address_pressed);
break;
case 3:
mSettingsImg.setImageResource(R.drawable.tab_settings_pressed);
break;
default:
break;
}
//切換Fragment
viewPager.setCurrentItem(i);
}
//將所有的圖片都變暗
private void resetImg(){
mWeixinImg.setImageResource(R.drawable.tab_weixin_normal);
mAddressImg.setImageResource(R.drawable.tab_address_normal);
mFriendsImg.setImageResource(R.drawable.tab_find_frd_normal);
mSettingsImg.setImageResource(R.drawable.tab_settings_normal);
}
}
四、ViewPager + Fragment + 第三方指示器 viewPagerLibrary
使用第三方庫 viewPagerLibrary 來實現指示器切換效果,效果如下:主佈局介面:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<include layout="@layout/top"/>
<com.viewpagerindicator.TabPageIndicator
android:id="@+id/id_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
</com.viewpagerindicator.TabPageIndicator>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
top.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="wrap_content"
android:gravity="center_vertical"
android:background="#58ACED"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/idx_logo"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="慕課網"
android:textColor="#ffffff"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginLeft="3dp"
/>
</LinearLayout>
Fragment 佈局 frag.xml
<?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:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello world"
android:layout_centerInParent="true"/>
</RelativeLayout>
MainActivity.java
public class MainActivity extends FragmentActivity {
private ViewPager mViewPager;
//設定指示器
private TabPageIndicator indicator;
//ViewPager 介面卡
private TabAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mViewPager = (ViewPager)findViewById(R.id.viewpager);
indicator = (TabPageIndicator)findViewById(R.id.id_indicator);
//建立介面卡
mAdapter = new TabAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mAdapter);
//給ViewPager設定指示器
indicator.setViewPager(mViewPager,0);
}
}
這裡建立了介面卡並設定介面卡,並且把ViewPager和指示器進行了繫結。
Fragment 程式碼
public class TabFragment extends Fragment{
int pos;
public TabFragment(int pos){
this.pos = pos;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag, container,false);
TextView tView = (TextView) view.findViewById(R.id.tv);
tView.setText(TabAdapter.TITLES[pos]);
return view;
}
}
TabAdapter.java 介面卡程式碼
public class TabAdapter extends FragmentPagerAdapter{
public static String[] TITLES = new String[] { "課程", "問答", "求課", "學習", "計劃" };
public TabAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int arg0) {
TabFragment fragment = new TabFragment(arg0);
return fragment;
}
@Override
public int getCount() {
return TITLES.length;
}
//設定標題
@Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
}
TabAdapter中我們設定了標題的名字,重寫了CharSequence getPageTitle 方法,指示器通過這裡去獲取標題的名字,同時在 getItem中 建立了 TITLES長度個數的Fragment,並設定了一個引數 arg0 ,Fragment建構函式中接收這個值並把值設定為TextView以作Fragment顯示時的區分。