Android中 Fragment + ViewPager 做出更具现代感的交互

hushuo
发布于 2021-3-24 11:30
浏览
0收藏

Fragment + ViewPager 初试探
下面是一些关于 Fragment 和 ViewPager 的总结。至于 Fragment 和 ViewPager 是什么就不说了,通常情况下两者是结合一起使用的,可以实现类似QQ或者微信的左右滑动,请看下面的 GIF。

Android中 Fragment + ViewPager 做出更具现代感的交互-鸿蒙开发者社区

好吧,现在来开始讲一下是如何使用它们的。

Fragment
我们自定义一个 RecommendFragment 类,该类继承 Fragment,代码如下:

public class MyFragment extends Fragment {
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  return inflater.inflate(R.layout.fragement_recommend, container, false);
 }
}


onCreateView 是用来加载 Fragment 视图的,再来看 RecommendFragment 对应的 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"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recommend_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFF4F4F4"
        android:overScrollMode="never" />

</RelativeLayout>


关于 Fragment ,可以使用简单工厂模式来进行创建,代码如下:

/**
 * @author JonesYang
 * @Data 2020-10-17
 * @Function 创建Fragment
 */
public class FragmentCreator {
 //代表这不同的工厂类型
    public static final int INDEX_RECOMMEND = 0;
    public static final int INDEX_SUBSCRIPTION = 1;
    public static final int INDEX_HISTORY = 2;
    // Fragment 的数量
    public static final int PAGE_COUNT = 3;
    //使用一个 Map 集合把 Fragment 缓存起来
    private static Map<Integer, BaseFragment> sCache = new HashMap<>();
    //获取 Fragment 的方法
    public static BaseFragment getFragment(int index) {
        //先在缓存中查找,如果缓存中存在就返回对应的 Fragment
        BaseFragment fragment = sCache.get(index);
        if (fragment != null) {
            return fragment;
        }

        //如果缓存不存在相应的 Fragment
        switch (index) {
            case INDEX_RECOMMEND:
                fragment = new RecommendFragment();
                break;
            case INDEX_SUBSCRIPTION:
                fragment = new SubscriptionFragment();
                break;
            case INDEX_HISTORY:
                fragment = new HistoryFragment();
                break;
        }
        //把创建的 Fragment 加入到 Map 缓存中
        sCache.put(index, fragment);
        return fragment;
    }
}


ViewPager
ViewPager 的作用如下:

ViewPager主要用来左右滑动。(类似图片轮播)
ViewPager要用适配器来连接“视图”和“数据”。(大家可以联想下listview的使用方法,原理是类似的)
官方推荐ViewPager与Fragment一起使用,并且有专门的适配器。
ViewPager 需要使用适配器,适配器的话这边就用 Fragment + ViewPager 的适配器来举例,接下来讲 Fragment + ViewPager 的组合使用。

Fragment + ViewPager
首先, 使用 单 Activity 加多 Fragment ,这个 Activity 必须继承 FragmentActivity 类,重点看一下适配器,适配器必须继承 FragmentPagerAdapter:

/**
 * @author JonesYang
 * @Data 2020-10-17
 * @Function  ViewPager + Fragment 的适配器
 */
public class MainContentAdapter extends FragmentPagerAdapter {

    public MainContentAdapter(FragmentManager manager) {
        super(manager);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        //返回 获取到的 Fragment
        return FragmentCreator.getFragment(position);
    }

    @Override
    public int getCount() {
        //返回 Fragment 的数量
        return FragmentCreator.PAGE_COUNT;
    }
}


Activity 对应的 XML 文件里,存在这样的 ViewPager 控件:

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/content_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/magic_indicator"
        android:overScrollMode="never" />


在继承了 FragmentActivity 类的 Activity 里面,是这样使用适配器的:

 //获取 ViewPager 控件的 ID
        viewPager = findViewById(R.id.content_pager);
     // 获取 FragmentManager
        FragmentManager fragmentManager = getSupportFragmentManager();
     //定义适配器,参数为 FragmentManager
        MainContentAdapter contentAdapter = new MainContentAdapter(manager);
        // 为 ViewPager 设置适配器
        viewPager.setAdapter(contentAdapter);


以上就是 Fragment + ViewPager 的使用了,通过上面的操作,我们可以实现多个 Fragment 左右滑动。实际上我们的需求并不止如此,正如同 GIF 图所示,我们需要实现一下两个功能:

点击上面的标题,下面的 ViewPager 的中的 Fragment 会发生改变。
左右滑动界面,上面的 Table 栏的标题会跟着滑动。
对于第一个功能,我们找到 title 控件,设置点击事件就可以了,只需要下面一行代码:

 viewPager.setCurrentItem(int position); //只需要把 Fragment 的 position 传进来


对于第二个功能,我们需要实现 onPageScrollStateChanged 这个接口才行,它的源码如下:

    public interface OnPageChangeListener {

        /**
         * This method will be invoked when the current page is scrolled, either as part
         * of a programmatically initiated smooth scroll or a user initiated touch scroll.
         *
         * @param position Position index of the first page currently being displayed.
         *                 Page position+1 will be visible if positionOffset is nonzero.
         * @param positionOffset Value from [0, 1) indicating the offset from the page at position.
         * @param positionOffsetPixels Value in pixels indicating the offset from position.
         */
        void onPageScrolled(int position, float positionOffset, @Px int positionOffsetPixels);

        /**
         * This method will be invoked when a new page becomes selected. Animation is not
         * necessarily complete.
         *
         * @param position Position index of the new selected page.
         */
        void onPageSelected(int position);

        /**
         * Called when the scroll state changes. Useful for discovering when the user
         * begins dragging, when the pager is automatically settling to the current page,
         * or when it is fully stopped/idle.
         *
         * @param state The new scroll state.
         * @see ViewPager#SCROLL_STATE_IDLE
         * @see ViewPager#SCROLL_STATE_DRAGGING
         * @see ViewPager#SCROLL_STATE_SETTLING
         */
        void onPageScrollStateChanged(int state);
    }


下面简单说一下。

  • onPageScrollStateChanged(int state): 有三种状态,SCROLL_STATE_IDLE、SCROLL_STATE_DRAGGING、SCROLL_STATE_SETTLING,分别表示滑动还没开始、正在滑动、滑动完成。
  • void onPageScrolled(int position, float positionOffset, @Px int positionOffsetPixels): 在滑动的过程中不停触发这个方法。
  • void onPageSelected(int position): 表示滑动已经完成,position 指的是当前位置。
    我们只需要重写上面三个方法,就可以实现上诉第二个功能。

分类
收藏
回复
举报
回复