編輯:關於Android編程
這篇文章主要介紹多種方式實現主界面的tab,包括:
(1)使用Fragment實現
(2)使用ViewPage實現
(3)使用ViewPage+FragmentPageAdapter
(4)使用框架實現
比較常規的使用方法,需要大家對Fragment有基本了解
相信各位看完之後對Fragment就能有一個比較清楚的了解。
這種方式實現的思路比較簡單:
1、首先在主布局中加入FragmentLayout
2、然後在Java代碼中監聽底部的按鈕,當點擊時,只需讓FragmentLayout加載相應的Fragment即可


可以看到,如果單純地使用Fragment,實際上是不能實現左右滑動的效果,頁面的切換,只能靠點擊底部的Button來實現。
首先是底部的一個布局文件bottom.xml
簡單的線性布局,放置我們的按鈕。

這個布局在後面的栗子中也會使用。
接下來是一個頂部的title
就一個TextView。

為了簡單起見,這裡面的布局只放置一個TextView<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMyBpZD0="java控制代碼">Java控制代碼
TestActivity2
public class TestActivity2 extends Activity implements View.OnClickListener {
private LinearLayout mTabWeixin;
private LinearLayout mTabFrd;
private LinearLayout mTabAddress;
private LinearLayout mTabSetting;
//底部的按鈕
private ImageButton mWeiXin;
private ImageButton mFriend;
private ImageButton mAddress;
private ImageButton mSetting;
//FragmentLayout要加載的四個Fragment
private WeiXinFragment weiXinFragment;
private FriendFragment friendFragment;
private AddressFragment addressFragment;
private SettingFragment settingFragment;
//頂部的標題
private TextView tvTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.test_ac_2);
initView();
initEvents();
setSelect(0);
}
private void initEvents() {
mWeiXin.setOnClickListener(this);
mFriend.setOnClickListener(this);
mAddress.setOnClickListener(this);
mSetting.setOnClickListener(this);
}
private void initView() {
//初始化
mTabWeixin= (LinearLayout) findViewById(R.id.id_tab_weixin);
mTabFrd= (LinearLayout) findViewById(R.id.id_tab_frd);
mTabAddress= (LinearLayout) findViewById(R.id.id_tab_address);
mTabSetting= (LinearLayout) findViewById(R.id.id_tab_setting);
mWeiXin= (ImageButton) findViewById(R.id.id_tab_weixin_img);
mFriend= (ImageButton) findViewById(R.id.id_tab_frd_img);
mAddress= (ImageButton) findViewById(R.id.id_tab_address_img);
mSetting= (ImageButton) findViewById(R.id.id_tab_setting_img);
tvTitle= (TextView) findViewById(R.id.tv_title);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.id_tab_weixin_img:
setSelect(0);
break;
case R.id.id_tab_frd_img:
setSelect(1);
break;
case R.id.id_tab_address_img:
setSelect(2);
break;
case R.id.id_tab_setting_img:
setSelect(3);
break;
}
}
private void hideFragment(FragmentTransaction fragmentTransaction) {
if (weiXinFragment!=null){
fragmentTransaction.hide(weiXinFragment);
}
if (friendFragment!=null){
fragmentTransaction.hide(friendFragment);
}
if (addressFragment!=null){
fragmentTransaction.hide(addressFragment);
}
if (settingFragment!=null){
fragmentTransaction.hide(settingFragment);
}
}
/*
* 重置所有的圖片,讓其恢復到灰色狀態
* */
private void resetImage() {
mSetting.setImageResource(R.drawable.tab_settings_normal);
mWeiXin.setImageResource(R.drawable.tab_weixin_normal);
mAddress.setImageResource(R.drawable.tab_address_normal);
mFriend.setImageResource(R.drawable.tab_find_frd_normal);
}
/*
* 設置某個Fragment
* */
private void setSelect(int i){
FragmentManager fm=getFragmentManager();
FragmentTransaction fragmentTransaction=fm.beginTransaction();
//重置圖片狀態
resetImage();
hideFragment(fragmentTransaction);
switch (i){
case 0:
//設置標題
tvTitle.setText("微信");
if (weiXinFragment==null){
//如果Fragment還沒實例化,實例化,並在fragmentTransaction中添加
weiXinFragment=new WeiXinFragment();
fragmentTransaction.add(R.id.id_content,weiXinFragment);
}else{
//如果已經實例化了,就顯示
fragmentTransaction.show(weiXinFragment);
}
fragmentTransaction.commit();
//改變底部圖標的狀態
mWeiXin.setImageResource(R.drawable.tab_weixin_pressed);
break;
case 1:
tvTitle.setText("朋友");
if (friendFragment==null){
friendFragment=new FriendFragment();
fragmentTransaction.add(R.id.id_content,friendFragment);
}else{
fragmentTransaction.show(friendFragment);
}
fragmentTransaction.commit();
mFriend.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case 2:
tvTitle.setText("通訊錄");
if (addressFragment==null){
addressFragment=new AddressFragment();
fragmentTransaction.add(R.id.id_content,addressFragment);
}else{
fragmentTransaction.show(addressFragment);
}
fragmentTransaction.commit();
mAddress.setImageResource(R.drawable.tab_address_pressed);
break;
case 3:
tvTitle.setText("設置");
if (settingFragment==null){
settingFragment=new SettingFragment();
fragmentTransaction.add(R.id.id_content,settingFragment);
}else{
fragmentTransaction.show(settingFragment);
}
fragmentTransaction.commit();
mSetting.setImageResource(R.drawable.tab_settings_pressed);
break;
}
}
}
代碼邏輯很清楚,中間需要提醒的地方已經用注釋表明,這個小栗子其實就是Fragment的常規使用,涉及到的內容也都是Fragment基礎知識,需要各位小伙伴爛熟於心。
在上一個栗子當中,我們使用的是FragmentLayout來作為填充Fragment的容器。當使用ViewPage,我們需要把布局文件中的Layout替換成ViewPager。這就要求開發者對ViewPager的使用有基本的了解。

可以看到使用了ViewPager之後不僅可以實現左右的滑動,而且還能通過底部的點擊來實現頁面切換的效果
首先是布局文件
非常簡單,就是把中間的FragmentLayout換成了ViewPager。
重點在於接下裡的Java代碼當中,裡面涉及到了ViewPager的基本使用。
public class TestActivity1 extends Activity implements View.OnClickListener {
private ViewPager viewPager;
private PagerAdapter pagerAdapter;
private List mViews =new ArrayList<>();
private FragmentPagerAdapter fragmentPagerAdapter;
private FragmentStatePagerAdapter fragmentStatePagerAdapter;
private LinearLayout mTabWeixin;
private LinearLayout mTabFrd;
private LinearLayout mTabAddress;
private LinearLayout mTabSetting;
private ImageButton mWeiXin;
private ImageButton mFriend;
private ImageButton mAddress;
private ImageButton mSetting;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.test_ac_1);
initView();
initEvents();
}
/*
* 初始化事件
* */
private void initEvents() {
mWeiXin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
viewPager.setCurrentItem(0);
mWeiXin.setImageResource(R.drawable.tab_weixin_pressed);
}
});
mSetting.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
viewPager.setCurrentItem(3);
mSetting.setImageResource(R.drawable.tab_settings_pressed);
}
});
mAddress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
viewPager.setCurrentItem(2);
mAddress.setImageResource(R.drawable.tab_address_pressed);
}
});
mFriend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
viewPager.setCurrentItem(1);
mFriend.setImageResource(R.drawable.tab_find_frd_pressed);
}
});
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int currentItem =viewPager.getCurrentItem();
resetImage();
switch (currentItem){
case 0:
mWeiXin.setImageResource(R.drawable.tab_weixin_pressed);
break;
case 1:
mFriend.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case 2:
mAddress.setImageResource(R.drawable.tab_address_pressed);
break;
case 3:
mSetting.setImageResource(R.drawable.tab_settings_pressed);
break;
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void initView() {
//初始化
viewPager= (ViewPager) findViewById(R.id.id_viewpager);
mTabWeixin= (LinearLayout) findViewById(R.id.id_tab_weixin);
mTabFrd= (LinearLayout) findViewById(R.id.id_tab_frd);
mTabAddress= (LinearLayout) findViewById(R.id.id_tab_address);
mTabSetting= (LinearLayout) findViewById(R.id.id_tab_setting);
mWeiXin= (ImageButton) findViewById(R.id.id_tab_weixin_img);
mFriend= (ImageButton) findViewById(R.id.id_tab_frd_img);
mAddress= (ImageButton) findViewById(R.id.id_tab_address_img);
mSetting= (ImageButton) findViewById(R.id.id_tab_setting_img);
LayoutInflater mLayoutInfater=LayoutInflater.from(this);
View view1=mLayoutInfater.inflate(R.layout.tab01,null);
View view2=mLayoutInfater.inflate(R.layout.tab02,null);
View view3=mLayoutInfater.inflate(R.layout.tab03,null);
View view4=mLayoutInfater.inflate(R.layout.tab04,null);
mViews.add(view1);
mViews.add(view2);
mViews.add(view3);
mViews.add(view4);
pagerAdapter=new PagerAdapter() {
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view=mViews.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mViews.get(position));
}
@Override
public int getCount() {
return mViews.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
};
viewPager.setAdapter(pagerAdapter);
}
@Override
public void onClick(View view) {
Log.d("--tab--","tab click");
//重置所有的圖片
resetImage();
switch (view.getId()){
case R.id.id_tab_weixin:
viewPager.setCurrentItem(0);
mWeiXin.setImageResource(R.drawable.tab_weixin_pressed);
Log.d("--tab--","tab weixin");
break;
case R.id.id_tab_frd:
viewPager.setCurrentItem(1);
mFriend.setImageResource(R.drawable.tab_find_frd_pressed);
Log.d("--tab--","tab friend");
break;
case R.id.id_tab_address:
viewPager.setCurrentItem(2);
mAddress.setImageResource(R.drawable.tab_address_pressed);
Log.d("--tab--","tab address");
break;
case R.id.id_tab_setting:
viewPager.setCurrentItem(3);
mSetting.setImageResource(R.drawable.tab_settings_pressed);
Log.d("--tab--","tab setting");
break;
}
}
/*
* 讓所有的圖片都變暗
* */
private void resetImage() {
mSetting.setImageResource(R.drawable.tab_settings_normal);
mWeiXin.setImageResource(R.drawable.tab_weixin_normal);
mAddress.setImageResource(R.drawable.tab_address_normal);
mFriend.setImageResource(R.drawable.tab_find_frd_normal);
}
}
同ViewPager實現相同
同ViewPager實現相同
既然這種方式使用的思路和效果和直接使用ViewPager的相同,那麼采用FragmenAdapter的方式來實現Tab頁面切換有什麼好處呢?
首先單純使用ViewPager時,裡面的View是通過LayoutInfater裝載進去的,雖然也能夠實現和和采用FragmentPagerAdapter一樣的效果,但是如果這麼做,必然所有的邏輯控制都放在MainActivity當中,對於後期代碼的維護十分不利。
使用FragmentPagerAdapter的好處之一就是能夠使得當前頁面的邏輯處理僅有當前Fragment來承擔,相當於把MainActivity裡面的事件邏輯分派給了Fragment來處理。這個優點,其實在使用Fragment的時候也能體現出來。
所以說,如果僅僅是頁面的展示(如圖片輪播),直接使用ViewPager就好了,但如果ViewPager的每個頁面中包含比較復雜的邏輯,就應該使用ViewPager+FragmentPagerAdapter的方式來完成Tab頁面的切換。
xml與ViewPager實現的相同,不再重復。
Java代碼:
public class TestActivity3 extends FragmentActivity implements View.OnClickListener {
private ViewPager viewPager;
private FragmentPagerAdapter mAdapter;
private List fragments;
private LinearLayout mTabWeixin;
private LinearLayout mTabFrd;
private LinearLayout mTabAddress;
private LinearLayout mTabSetting;
private ImageButton mWeiXin;
private ImageButton mFriend;
private ImageButton mAddress;
private ImageButton mSetting;
private int select;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.test_ac_3);
initView();
initEvent();
}
private void initEvent() {
mWeiXin.setOnClickListener(this);
mFriend.setOnClickListener(this);
mAddress.setOnClickListener(this);
mSetting.setOnClickListener(this);
}
private void initView() {
//初始化
viewPager= (ViewPager) findViewById(R.id.id_viewpager3);
mTabWeixin= (LinearLayout) findViewById(R.id.id_tab_weixin);
mTabFrd= (LinearLayout) findViewById(R.id.id_tab_frd);
mTabAddress= (LinearLayout) findViewById(R.id.id_tab_address);
mTabSetting= (LinearLayout) findViewById(R.id.id_tab_setting);
mWeiXin= (ImageButton) findViewById(R.id.id_tab_weixin_img);
mFriend= (ImageButton) findViewById(R.id.id_tab_frd_img);
mAddress= (ImageButton) findViewById(R.id.id_tab_address_img);
mSetting= (ImageButton) findViewById(R.id.id_tab_setting_img);
fragments=new ArrayList<>();
WeiXinFragment weiXinFragment=new WeiXinFragment();
FriendFragment friendFragment=new FriendFragment();
AddressFragment addressFragment=new AddressFragment();
SettingFragment settingFragment=new SettingFragment();
fragments.add(weiXinFragment);
fragments.add(friendFragment);
fragments.add(addressFragment);
fragments.add(settingFragment);
mAdapter=new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
};
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
resetImage();
switch (position){
case 0:
mWeiXin.setImageResource(R.drawable.tab_weixin_pressed);
viewPager.setCurrentItem(0);
break;
case 1:
mFriend.setImageResource(R.drawable.tab_find_frd_pressed);
viewPager.setCurrentItem(1);
break;
case 2:
mAddress.setImageResource(R.drawable.tab_address_pressed);
viewPager.setCurrentItem(2);
break;
case 3:
mSetting.setImageResource(R.drawable.tab_settings_pressed);
viewPager.setCurrentItem(3);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
@Override
public void onClick(View view) {
resetImage();
switch (view.getId()) {
case R.id.id_tab_weixin_img:
setSelect(0);
break;
case R.id.id_tab_frd_img:
setSelect(1);
break;
case R.id.id_tab_address_img:
setSelect(2);
break;
case R.id.id_tab_setting_img:
setSelect(3);
break;
}
}
public void setSelect(int select) {
switch (select){
case 0:
mWeiXin.setImageResource(R.drawable.tab_weixin_pressed);
viewPager.setCurrentItem(0);
break;
case 1:
mFriend.setImageResource(R.drawable.tab_find_frd_pressed);
viewPager.setCurrentItem(1);
break;
case 2:
mAddress.setImageResource(R.drawable.tab_address_normal);
viewPager.setCurrentItem(2);
break;
case 3:
mSetting.setImageResource(R.drawable.tab_settings_pressed);
viewPager.setCurrentItem(3);
break;
}
}
private void resetImage() {
mSetting.setImageResource(R.drawable.tab_settings_normal);
mWeiXin.setImageResource(R.drawable.tab_weixin_normal);
mAddress.setImageResource(R.drawable.tab_address_normal);
mFriend.setImageResource(R.drawable.tab_find_frd_normal);
}
}
如果每一次在開發的過程當中都去寫一個這樣的Tab頁面,無疑耗時耗力,當然,對於初學者而言,這種“耗時耗力”能夠幫助他們了解效果實現的基本實現原理。
在這裡推薦給大家一款比較不錯的ViewPager框架:
LuckyJayce/ViewPagerIndicator
裡面的介紹比較詳細,這裡就不多講了,對這個框架感興趣的小伙伴可以去github上仔細研讀一下~
最後附上下載的源碼:github
Android studio 插件安裝 plugin
Android studio 插件安裝 plugin android studio 上有很多第三方插件可以極大提高開發效率 安裝插件的入口有兩個地方:
【Android】由淺到深理解AIDL
一、 Binder概述1.1 為什麼要用binder出於安全性、穩定性和內存管理的考慮,Android的應用和系統服務運行在分離的進程中,但是它們之間需要通信和共享數據避
Android獲取和讀取短信驗證碼的實現方法
現如今,驗證碼在Android的客戶端還是非常普遍的.通過手機賬號和驗證碼直接去注冊應用賬戶的信息.很多應用都以這種方式來完成注冊.簡單的介紹一下吧.&nbs
C#程序員學習Android開發系列之按鈕事件的4種寫法
經過前兩篇blog的鋪墊,我們今天熱身一下,做個簡單的例子。目錄結構還是引用上篇blog的截圖。具體實現代碼:public class MainActivity exte