程序员人生 网站导航

viewpager+fragment的懒加载实现微信点击和滑动切换功能(切换效果)

栏目:综合技术时间:2016-06-30 13:00:07

前言

1.从上1片文章以后已半年没有写文章了,那篇文章以后公司进入疯狂的加班,1直到放年假。年后回来以后换了1家创业公司以后,然后又进入疯狂的加班(≧﹏ ≦) …所以1直都没有写文章(其实这都是借口⊙﹏⊙)。现在公司没有那末忙了,也该把文章捡起来了,这毕竟是百利有1害的事(1害:费时间)。

2.这半年里除对代码的热忱更加高涨(虽然它总是虐我千百遍(≧﹏ ≦) ),还深深的中了爬山的毒,对年轻的我来讲,爬山让我明白了许多、晓得了许多,也锻炼了我的身体。对程序员来讲身体是非常重要的,大家在周末的时候可以爬爬山、跑跑步或打打球之类的,运动运动,给大家献上几张端五假期去蒙古草原拍的几张照片:

这里写图片描述

这里写图片描述

这里写图片描述

正文

进入正题,这篇博客主要讲授viewpager+fragment实现微信滑动切换页面的功能,并且附带切换效果,功能其实其实不难,只是需要把知识点关联起来

应为使用模拟器原因,出现模糊背景,手机上面是没有的

1.分析用到的知识点

(1). fragment的懒加载
(2). viewpager的滑动监听事件
(3). 控件alpha的设置、fragment切换的效果

2.功能实现

2.1.fragment的懒加载

这里写图片描述

这里写图片描述

当viewpager加载第1个fragment的时候会预加载第2个fragment,当加载第2个fragment的时候,会预加载第3个fragment,同时会进行数据加载,这类做法肯定不好,当第几个fragment显示的时候才应当加载数据,这里就用到了懒加载(参考:http://blog.csdn.net/maosidiaoxian/article/details/38300627):

public abstract class LazyFragment extends Fragment{ //用于标记视图是不是初始化 protected boolean isVisible; //在onCreate方法之前调用,用来判断Fragment的UI是不是是可见的 @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if(getUserVisibleHint()) { isVisible = true; onVisible(); } else { isVisible = false; onInvisible(); } } /** * 视图可见 * */ protected void onVisible(){ lazyLoad(); } /** * 自定义抽象加载数据方法 * */ protected abstract void lazyLoad(); /** * 视图不可见 * */ protected void onInvisible(){} }

自定义LazyFragment类只需要继承Fragment,实现setUserVisibleHint方法来判断fragment视图是不是可见,定义3个方法,当视图可见的时候,isVisible = true,调用lazyLoad方法,其它fragment只需要继承该fragment便可:

public class OneFragment extends LazyFragment { // 标志fragment是不是初始化完成 private boolean isPrepared; private View view; @Override public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) { if(view == null){ view = inflater.inflate(R.layout.fragment_one , container , false); ButterKnife.inject(this, view); KLog.e("TAG" , "oneFragment--onCreateView"); isPrepared = true; lazyLoad(); } return view; } @Override protected void lazyLoad() { if(!isPrepared || !isVisible) { return; } KLog.e("TAG" , "oneFragment--lazyLoad"); } }

由于setUserVisibleHint方法在onCreateView方法之前调用,所以定义字段isPrepared 来判断fragment是不是初始化完成,避免报nullpointerexception,只有当视图可见并且fragment初始化完成履行lazyLoad方法,可以理解成绩是onStart方法,再进行数据加载,这也就是懒加载。

注:
a.由于每次加载fragment都会重新履行onCreateView方法,所以我用view来判断fragment是不是初始化过,初始化过就不在初始化,固然要是想每次都初始化就没必要判断
b.每次fragment视图可见的时候lazyLoad方法都会被调用,若是只想加载1次可自定义字段判断是不是加载过数据

这里写图片描述

这里写图片描述

2.2.viewpager的滑动监听事件

首先设置viewpager的适配器,FragmentPagerAdapter的子类只要实现 getItem(int) 和 getCount()方法:

public class FragmentAdapter extends FragmentPagerAdapter{ //fragment 集合 private List<Fragment> mFragmentList = new ArrayList<>(); public FragmentAdapter(FragmentManager fm , List<Fragment> list) { super(fm); this.mFragmentList = list; } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } }

其次设置viewpager监听事件:

//viewpager滑动监听 mMainViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { changAlpha(position, positionOffset); } @Override public void onPageSelected(int position) { changAlpha(position); } @Override public void onPageScrollStateChanged(int state) {} });

onPageScrolled方法的表示viewpager正在滑动:

position当向右滑动的时候表示当前页面的下标,向左滑动的时候表示左侧页面的下标;
positionOffset是当前页面滑动比例,如果页面向右翻动,这个值不断变大,最后在趋近1的情况后突变成0。如果页面向左翻动,这个值不断变小,最后变成0;
positionOffsetPixels是当前页面滑动像素,变化情况和positionOffset1致。

参数的变化随方向的相反正好相反,下面我们写tab的色彩渐变就不需要判断方向了

根据该方法的positionOffset和position这两个参数就能够实现tab滑动色彩渐变的效果,先看1下布局:

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white" android:orientation="horizontal" android:paddingTop="5dp"> <FrameLayout android:id="@+id/m_main_fw_lay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <Button android:id="@+id/m_main_fw_btn_false" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_false" android:drawableTop="@mipmap/bottom1_tab_false" android:text="服务"/> <Button android:id="@+id/m_main_fw_btn_true" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_true" android:drawableTop="@mipmap/bottom1_tab_true" android:text="服务"/> </FrameLayout> <FrameLayout android:id="@+id/m_main_sj_lay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <Button android:id="@+id/m_main_sj_btn_false" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_false" android:drawableTop="@mipmap/bottom2_tab_false" android:text="社交"/> <Button android:id="@+id/m_main_sj_btn_true" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_true" android:drawableTop="@mipmap/bottom2_tab_true" android:text="社交"/> </FrameLayout> <FrameLayout android:id="@+id/m_main_gz_lay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <Button android:id="@+id/m_main_gz_btn_false" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_false" android:drawableTop="@mipmap/bottom3_tab_false" android:text="工作"/> <Button android:id="@+id/m_main_gz_btn_true" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_true" android:drawableTop="@mipmap/bottom3_tab_true" android:text="工作"/> </FrameLayout> <FrameLayout android:id="@+id/m_main_lxr_lay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <Button android:id="@+id/m_main_lxr_btn_false" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_false" android:drawableTop="@mipmap/bottom4_tab_false" android:text="联系人"/> <Button android:id="@+id/m_main_lxr_btn_true" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_true" android:drawableTop="@mipmap/bottom4_tab_true" android:text="联系人"/> </FrameLayout> <FrameLayout android:id="@+id/m_main_wd_lay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <Button android:id="@+id/m_main_wd_btn_false" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_false" android:drawableTop="@mipmap/bottom5_tab_false" android:text="我的"/> <Button android:id="@+id/m_main_wd_btn_true" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/fragment_tab_item_true" android:drawableTop="@mipmap/bottom5_tab_true" android:text="我的"/> </FrameLayout> </LinearLayout>

每一个tab我是使用的2个button,1个默许色彩,1个选中色彩,我们只需要根据滑动比例来改变选中色彩button的alpha便可:

/** * 根据滑动设置透明度 */ private void changAlpha(int pos, float posOffset) { int nextIndex = pos + 1; if(posOffset > 0){ //设置tab的色彩渐变效果 mButtonList.get(nextIndex).setAlpha(posOffset); mButtonList.get(pos).setAlpha(1 - posOffset); //设置fragment的色彩渐变效果 mFragmentList.get(nextIndex).getView().setAlpha(posOffset); mFragmentList.get(pos).getView().setAlpha(1 - posOffset); //设置fragment滑动视图由大到小,由小到大的效果 mFragmentList.get(nextIndex).getView().setScaleX(0.5F + posOffset/2); mFragmentList.get(nextIndex).getView().setScaleY(0.5F + posOffset/2); mFragmentList.get(pos).getView().setScaleX(1-(posOffset/2)); mFragmentList.get(pos).getView().setScaleY(1-(posOffset/2)); } }

当posOffset > 0 ,说明viewpager在滑动;前面说了onPageScrolled方法参数随滑动方向的变化是相反的所以这里只需要写1个方法即可实现两个方向滑动色彩渐变的效果,道理就是改变两个button的Alpha值便可实现渐变效果,是否是挺简单;
关于fragemnt的色彩渐变和伸缩效果,在上面也已贴出了代码,就不详细解释了,相信大家都能看懂;

onPageSelected方法表示滑动抬起手指那1刻所履行的方法,参数position代表的是当前页面的下标,所以当滑动结束以后,我们把当前页面的tab、fragment.getView()的Alpha设置为1.0f,其它tab设置为0.0f ; fragment的x、y轴设置为1.0f(需要判断fragment.getView()是不是为null,避免报nullpointerexception),其他的0.0f便可:

/** * 1开始运行、滑动和点击tab结束后设置tab的透明度,fragment的透明度和大小 */ private void changAlpha(int postion) { for (int i = 0; i < mButtonList.size(); i++) { if (i == postion) { mButtonList.get(i).setAlpha(1.0f); if(null != mFragmentList.get(i).getView()){ mFragmentList.get(i).getView().setAlpha(1.0f); mFragmentList.get(i).getView().setScaleX(1.0f); mFragmentList.get(i).getView().setScaleY(1.0f); } } else { mButtonList.get(i).setAlpha(0.0f); if(null != mFragmentList.get(i).getView()){ mFragmentList.get(i).getView().setAlpha(0.0f); mFragmentList.get(i).getView().setScaleX(0.0f); mFragmentList.get(i).getView().setScaleY(0.0f); } } } }

把所有fragemnt放入集合中遍历判断便可;

主要代码就这些,有不解的地方请看Demo

源码下载

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐