編輯:關於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 ListmViews =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 Listfragments; 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 上有很多第三方插件可以極大提高開發效率 安裝插件的入口有兩個地方:
一、 Binder概述1.1 為什麼要用binder出於安全性、穩定性和內存管理的考慮,Android的應用和系統服務運行在分離的進程中,但是它們之間需要通信和共享數據避
現如今,驗證碼在Android的客戶端還是非常普遍的.通過手機賬號和驗證碼直接去注冊應用賬戶的信息.很多應用都以這種方式來完成注冊.簡單的介紹一下吧.&nbs
經過前兩篇blog的鋪墊,我們今天熱身一下,做個簡單的例子。目錄結構還是引用上篇blog的截圖。具體實現代碼:public class MainActivity exte