当筵意气临九霄,星离雨散不终朝。这篇文章主要讲述android-多种方式实现主界面的Tab相关的知识,希望能为你提供帮助。
本人水平有限,文章中如果出现什么不正确或者模糊的地方,还请各位小伙伴留下评论,多多指教 : )
- 前言
- 使用Fragment实现
- 思路
- 效果
- 具体讲解
- 底部布局
- 顶部布局
- Fragment的布局
- Java控制代码
- 使用ViewPager实现
- 思路
- 效果
- 具体实现
- 使用ViewPagerFragmentPagerAdapter方法实现
- 思路
- 效果
- 补充
- 具体代码
- 使用框架
前言这篇文章主要介绍多种方式实现主界面的tab,包括:
(1)使用Fragment实现
(2)使用ViewPage实现
(3)使用ViewPage+FragmentPageAdapter
(4)使用框架实现
在线的视频课程来自慕课网——多种多样的App主界面Tab实现方法。觉得文字不好理解的小伙伴可以去看视频,然后再回头自己敲一遍。
使用Fragment实现比较常规的使用方法,需要大家对Fragment有基本了解,这里推荐hongyang大神的几篇博文:
Android Fragment 真正的完全解析(上)
Android Fragment 真正的完全解析(下)
相信各位看完之后对Fragment就能有一个比较清楚的了解。
思路这种方式实现的思路比较简单:
1、首先在主布局中加入FragmentLayout
2、然后在java代码中监听底部的按钮,当点击时,只需让FragmentLayout加载相应的Fragment即可
文章图片
效果
文章图片
可以看到,如果单纯地使用Fragment,实际上是不能实现左右滑动的效果,页面的切换,只能靠点击底部的Button来实现。
具体讲解底部布局
首先是底部的一个布局文件bottom.xml
<
?xml version="1.0" encoding="utf-8"?>
<
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="65dp"
android:background="@drawable/bottom_bar">
<
LinearLayout
android:id="@+id/id_tab_weixin"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<
ImageButton
android:id="@+id/id_tab_weixin_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="https://www.songbingjia.com/android/@drawable/tab_weixin_pressed"
android:background="#0000"/>
<
TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:text="微信"/>
<
/LinearLayout>
<
LinearLayout
android:id="@+id/id_tab_frd"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<
ImageButton
android:id="@+id/id_tab_frd_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="https://www.songbingjia.com/android/@drawable/tab_find_frd_normal"
android:background="#0000"/>
<
TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:text="朋友"/>
<
/LinearLayout>
<
LinearLayout
android:id="@+id/id_tab_address"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<
ImageButton
android:id="@+id/id_tab_address_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="https://www.songbingjia.com/android/@drawable/tab_address_normal"
android:background="#0000"/>
<
TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:text="通讯录"/>
<
/LinearLayout>
<
LinearLayout
android:id="@+id/id_tab_setting"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<
ImageButton
android:id="@+id/id_tab_setting_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="https://www.songbingjia.com/android/@drawable/tab_settings_normal"
android:background="#0000"/>
<
TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:text="设置"/>
<
/LinearLayout>
<
/LinearLayout>
简单的线性布局,放置我们的按钮。
文章图片
这个布局在后面的栗子中也会使用。
顶部布局
接下来是一个顶部的title
<
?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="45dp"
android:gravity="center"
android:background="@drawable/title_bar">
<
TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="微信"
android:textColor="#ffffff"
android:textSize="20sp"
android:textStyle="bold"
android:layout_gravity="center"/>
<
/LinearLayout>
就一个TextView。
Fragment的布局
文章图片
【android-多种方式实现主界面的Tab】为了简单起见,这里面的布局只放置一个TextView
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基础知识,需要各位小伙伴烂熟于心。
使用ViewPager实现思路在上一个栗子当中,我们使用的是FragmentLayout来作为填充Fragment的容器。当使用ViewPage,我们需要把布局文件中的Layout替换成ViewPager。这就要求开发者对ViewPager的使用有基本的了解。
效果
文章图片
可以看到使用了ViewPager之后不仅可以实现左右的滑动,而且还能通过底部的点击来实现页面切换的效果
具体实现首先是布局文件
<
?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">
<
include
layout="@layout/top"/>
<
android.support.v4.view.ViewPager
android:id="@+id/id_viewpager"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<
/android.support.v4.view.ViewPager>
<
include
layout="@layout/bottom"/>
<
/LinearLayout>
非常简单,就是把中间的FragmentLayout换成了ViewPager。
重点在于接下里的Java代码当中,里面涉及到了ViewPager的基本使用。
public class TestActivity1 extends Activity implements View.OnClickListener {
private ViewPager viewPager;
private PagerAdapter pagerAdapter;
private List<
View>
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+FragmentPagerAdapter方法实现思路同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<
Fragment>
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上仔细研读一下~
推荐阅读
- Android开发 SDK NDK下载
- Android App 开发技能图谱
- Android Service demo例子使用详解
- android国际化
- 《Java4Android》视频学习笔记——包和访问权限
- Android 通过adb shell am broadcast发送广播
- android studio 引入第三方类库jar包
- Android Edittext 显示光标 获取焦点 监听焦点
- 自定义ANDROID中EDITTEXT中的HINT文本的大小