Tablayout+Viewpager+Fragment+FragmentAdapter实现联动效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lyp13243189027/article/details/81001724

参考连接为:https://www.2cto.com/kf/201802/719334.html

参考连接二为:https://www.jianshu.com/p/d86e31dcc97b


在项目开发中很多场景都会碰到tab栏切换的效果,实现的思路也有很多种,tabhost+fragment,radionbtton+viewpager等方式都可以实现,这里就说下tablayout+viewpager的实现方式;tablayout是android5.0推出来的一个MaterialDesign风格的控件,是专门用来实现tab栏效果的;功能强大,使用方便灵活;

1、引入依赖库

compile 'com.android.support:design:25.3.1'
compile 'com.android.support:support-v4:25.3.1'
  • 1
  • 2

2、xml布局文件中使用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.mdtablayout.MainActivity">
    <android.support.design.widget.TabLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabTextColor="@android:color/black"
        app:tabSelectedTextColor="@color/colorAccent"
        app:tabMode="scrollable"
        app:tabGravity="fill"/>
    <android.support.v4.view.ViewPager
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

tablayout提供了很多的属性可以设置:

app:tabIndicatorColor    指示器颜色
app:tabTextColor         tab栏字体颜色
app:tabSelectedTextColor tab栏字体被选颜色
app:tabIndicatorHeight   指示器高度
app:tabBackground        tab背景颜色
app:tabMaxWidth          tab栏最大宽度
app:tabTextAppearance    tab栏字体样式
app:tabMinWidth          tab栏最小宽度
......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这些属性可以下xml中设置,也可以使用代码进行设置;需要注意这两个属性:

app:tabMode="";有scrollable和fixed两个属性值
scrollable:可滑动;
fixed:不能滑动,平分tabLayout宽度;

app:tabGravity="";center和fill两个属性值
fill:tabs平均填充整个宽度;
center:tab居中显示;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3、设置tablayout和viewpager,并将tablayout和viewpager进行关联 
在设置tablayout和viewpager,并将tablayout和viewpager进行关联有两中方式可以实现: 
方式一: 
3.1、TabLayout和Viewpager关联

tablayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                //tab被选的时候回调
                viewpager.setCurrentItem(tab.getPosition(),true);
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                //tab未被选择的时候回调
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                //tab重新选择的时候回调
            }
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.2、ViewPager滑动关联tabLayout

viewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tablayout));
  • 1

3.3、设置tabLayout的标签来自于PagerAdapter

tablayout.setTabsFromPagerAdapter(tabAdapter);
  • 1

3.4、ViewPager设置适配器

viewpager.setAdapter(tabAdapter);
  • 1

方式二: 
3.1、viewpager设置适配器

viewpager.setAdapter(tabAdapter);
  • 1

3.2、tablayout和viewpager相互关联,并设置tablayout文字

tablayout.setupWithViewPager(viewpager);
  • 1

使用第二种方式需要注意的是setupWithViewPager();方法的调用必须在viewpager设置完适配器后调用,如果在设置适配器之前调用会抛异常,至于为什么会抛异常,后面tablayout的源码会说到;这样tab栏切换效果就实现了: 
这里写图片描述

在上面说到了tablayout的tabMode和tabGravity两个属性,将这个两个属性对应的值做下修改就可以实现一些其他的效果,这里将tablayout对应的值修改为fixed(不可滑动),tabGravity的值修改为center(tab居中显示),将tab栏的数量改为两个;效果如下: 
这里写图片描述

上面这些效果都是用tablayout实现的顶部tab栏切换,tablayout照样可以实现底部tab栏切换的效果;

修改xml布局文件,将tablayout和viewpager的位置互换,并设置viewpager的weight,同时将tablayout的tabIndicatorHeight属性值设为0dp,将指示器隐藏掉,tabMode属性值设置为fixed,tabGravity的属性值设置为fill;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.mdtablayout.MainActivity">
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabTextColor="@android:color/black"
        app:tabSelectedTextColor="@color/colorAccent"
        app:tabMode="fixed"
        app:tabGravity="fill"
        android:background="@android:color/holo_orange_light"
        app:tabIndicatorHeight="0dp"/>
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

其他的文件不用做改动,效果就可以实现了: 
这里写图片描述

如果想在底部tab栏文字上面添加图片实现类似微信那样的效果也是可以的,在tablayout和viewpager关联后,获取tablayout的tab数量,并对数量进行遍历获取到每个tab,给每个tab设置相应的view就可以了;

//获取当前tab数量
int tabCount = tablayout.getTabCount();
//遍历循环tab数量
for(int i=0;i<tabCount;i++){
    //获取每个tab
    TabLayout.Tab tab = tablayout.getTabAt(i);
    //通过相应的布局文件获取view
    View view = View.inflate(this, R.layout.tab_view, null);
    ImageView iv = (ImageView) view.findViewById(R.id.iv);
    TextView tv = (TextView) view.findViewById(R.id.tv);
    //设置tab栏文字
    tv.setText(tabList.get(i));
    //设置tab图片
    iv.setImageResource(R.mipmap.message_icon);
    //给tab设置view
    tab.setCustomView(view);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这样效果就实现了: 
这里写图片描述

源码地址: 

http://download.csdn.net/detail/wangwo1991/9915302



下面讲的是不重复建Fragment 复用一个Fragment的方法



import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.View;

/**
 * Created by dasu on 2016/9/27.
 * https://github.com/woshidasusu/Meizi
 * <p>
 * Viewpager + Fragment情况下,fragment的生命周期因Viewpager的缓存机制而失去了具体意义
 * 该抽象类自定义一个新的回调方法,当fragment可见状态改变时会触发的回调方法,介绍看下面
 *
 * @see #onFragmentVisibleChange(boolean)
 */
public abstract class ViewPagerFragment extends Fragment {

    /**
     * rootView是否初始化标志,防止回调函数在rootView为空的时候触发
     */
    private boolean hasCreateView;

    /**
     * 当前Fragment是否处于可见状态标志,防止因ViewPager的缓存机制而导致回调函数的触发
     */
    private boolean isFragmentVisible;

    /**
     * onCreateView()里返回的view,修饰为protected,所以子类继承该类时,在onCreateView里必须对该变量进行初始化
     */
    protected View rootView;

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        Log.d("LYP11111", "setUserVisibleHint() -> isVisibleToUser: " + isVisibleToUser);
        if (rootView == null) {
            return;
        }
        hasCreateView = true;
        if (isVisibleToUser) {
            onFragmentVisibleChange(true);
            isFragmentVisible = true;
            return;
        }
        if (isFragmentVisible) {
            onFragmentVisibleChange(false);
            isFragmentVisible = false;
        }
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initVariable();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (!hasCreateView && getUserVisibleHint()) {
            onFragmentVisibleChange(true);
            isFragmentVisible = true;
        }
    }

    public void initVariable() {
        hasCreateView = false;
        isFragmentVisible = false;
    }

    /**************************************************************
     *  自定义的回调方法,子类可根据需求重写
     *************************************************************/

    /**
     * 当前fragment可见状态发生变化时会回调该方法
     * 如果当前fragment是第一次加载,等待onCreateView后才会回调该方法,其它情况回调时机跟 {@link #setUserVisibleHint(boolean)}一致
     * 在该回调方法中你可以做一些加载数据操作,甚至是控件的操作,因为配合fragment的view复用机制,你不用担心在对控件操作中会报 null 异常
     *
     * @param isVisible true  不可见 -> 可见
     *                  false 可见  -> 不可见
     */
    protected void onFragmentVisibleChange(boolean isVisible) {
        Log.w("llll", "onFragmentVisibleChange -> isVisible: " + isVisible);
    }

}

package com.example.testlunbo.MyAdapter;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.util.Log;
import android.view.ViewGroup;

import com.example.testlunbo.MyViewPageFragment.TablayoutViewPageFragment;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by ${Yunpan_liu} on 2018/6/29.
 */

public class MyFragmentAdapterTest extends FragmentPagerAdapter {

    private List<String> mWeek = new ArrayList<>();
    private List<String> mDates =new ArrayList<>();
    private Context mContext;

    public MyFragmentAdapterTest(FragmentManager fm, List<String> week, List<String> dates, Context context) {
        super(fm);
        mWeek = week;
        mDates = dates;
        mContext = context;
    }

    @Override
    public Fragment getItem(int position) {
        Fragment mfragment = TablayoutViewPageFragment.getInstance(mDates.get(position),mWeek.get(position));
        return mfragment;
    }



    @Override
    public int getCount() {
        return mWeek.size();
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return mWeek.get(position);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Log.d("LYP ","position == "+position);
        TablayoutViewPageFragment fragment = (TablayoutViewPageFragment) super.instantiateItem(container,position);
        fragment.setDate(mDates.get(position),mWeek.get(position));
        return fragment;
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
/*        Log.d("LYP","setPrimaryItem == "+ position);
        TablayoutViewPageFragment mfragment = (TablayoutViewPageFragment) super.instantiateItem(container,position);
//        TablayoutViewPageFragment mfragment = TablayoutViewPageFragment.getInstance(mDates.get(position),mWeek.get(position));
        mfragment.setDate(mDates.get(position),mWeek.get(position));*/
    }
}

package com.example.testlunbo.Activity;

import android.app.Activity;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;

import com.example.testlunbo.MyAdapter.MyFragmentAdapterTest;
import com.example.testlunbo.R;

import java.util.ArrayList;
import java.util.List;

public class TablayoutActivity extends FragmentActivity {

    private TabLayout tabLayout;
    private ViewPager viewPager;
    private MyFragmentAdapterTest myFragmentAdapterTest;
    private List<String> mweeks;
    private List<String> mDatas;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tablayout);
        initview();
    }

    private void initview() {

        mweeks = new ArrayList<>();
        mDatas = new ArrayList<>();

        mweeks.add("周一");
        mweeks.add("周二");
        mweeks.add("周三");
        mweeks.add("周四");
        mweeks.add("周五");

        mDatas.add("fragment111111111");
        mDatas.add("fragment222222222");
        mDatas.add("fragment333333333");
        mDatas.add("fragment444444444");
        mDatas.add("fragment555555555");

        tabLayout = findViewById(R.id.tablayout_tablayout);
        viewPager = findViewById(R.id.viewpager);

        FragmentManager fm = getSupportFragmentManager();
        myFragmentAdapterTest = new MyFragmentAdapterTest(fm,mweeks,mDatas,this);
        viewPager.setAdapter(myFragmentAdapterTest);

        tabLayout.setupWithViewPager(viewPager);
        tabLayout.setTabMode(TabLayout.MODE_FIXED);

    }
}



阅读更多
换一批

没有更多推荐了,返回首页