Android中 Fragment + ViewPager 做出更具现代感的交互
Fragment + ViewPager 初试探
下面是一些关于 Fragment 和 ViewPager 的总结。至于 Fragment 和 ViewPager 是什么就不说了,通常情况下两者是结合一起使用的,可以实现类似QQ或者微信的左右滑动,请看下面的 GIF。
好吧,现在来开始讲一下是如何使用它们的。
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 指的是当前位置。
我们只需要重写上面三个方法,就可以实现上诉第二个功能。