使用ViewPager+Fragment来实现带滚动条的多屏滑动-IndicatorFragmentActivity

转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17201587

介绍

在android应用中,多屏滑动是一种很常见的风格,博主之前也写过一些多屏滑动的demo,比如滚动banner(http://blog.csdn.net/singwhatiwanna/article/details/8875241)和仿tabhost的控件。这次给大家介绍一种效果更好的风格:带滚动条的多屏滑动,类似于google play里面的风格。如果你看过我之前写的banner,你就会发现那个banner是原生的,没有采用viewpager啥的,所以代码很长,如果采用ViewPager,代码就会短很多,但是使用ViewPager也有弊端:需要导入android-support-v4.jar、细节无法控制。不过现在情况已经不一样了,android-support-v4中提供了很多实用的功能,以至于现在新建一个android工程默认都会导入这个jar包。那我们就也采用viewpager来做滑动吧。另外一个概念就是Fragment和FragmentActivity,Fragment是一个特殊的类,有着和activity一致的生命周期和view一致的界面,也就是Fragment就等于具有生命周期的View,但是,要注意的是:Fragment并不是View,它和View没有继承关系。使用Fragment的好处是:Fragment可以重用,而且每个Fragment可以在内部处理自己的业务就像activity一样,这样模块间耦合较低,比把所有的业务都写在一个activity内部逻辑要清晰很多。还有就是,由于每个模块的业务都在Fragment内部来实现,这样activity只要管理好几个Fragment就行了,不需要做和业务相关的事情,最后,Fragment可以用来做不同分辨率机型的适配。Fragment在sdk(android
3.0及更高)和android-support-v4里面都有,但是由于兼容性的问题,我们只能使用android-support-v4里面的Fragment,除非你想你的apk只跑在3.0以后的android手机上,FragmentActivity的情况和Fragment类似。关于Fragment和FragmentActivity,其实有一些基本的用法需要了解一下,但是考虑到Fragment不是本文的重点,所以这里就不介绍了,另外,本文只用Fragment做了一个简单的界面,大家应该一看就懂,好了,言归正传。

IndicatorFragmentActivity的实现过程

1 新建一个工程,目录结构如下:

2 实现ui包下的三个文件

ViewPagerCompat.java:这是一个ViewPager的加强类,主要是为了解决滑动冲突的问题。不然的话,在ViewPager内部加入ListView等可滑动控件,两者之间会产生干扰。

在这里想多说一下,关于此类问题,解决办法是:重写父控件的onInterceptTouchEvent函数,在move的时候根据需要返回true,比如左右滑动返回true,其他情况均返回false。这样,当左右滑动的时候,由于onInterceptTouchEvent返回了true,父控件就能处理,其他情况,事件将传递到listview中,listview自身可以处理上下滑动。

[java] view
plain
copy

  1. public class ViewPagerCompat extends ViewPager {  
  2.   
  3.     //mViewTouchMode表示ViewPager是否全权控制滑动事件,默认为false,即不控制  
  4.     private boolean mViewTouchMode = false;  
  5.   
  6.     public ViewPagerCompat(Context context, AttributeSet attrs) {  
  7.         super(context, attrs);  
  8.     }  
  9.   
  10.     public void setViewTouchMode(boolean b) {  
  11.         if (b && !isFakeDragging()) {  
  12.             //全权控制滑动事件  
  13.             beginFakeDrag();  
  14.         } else if (!b && isFakeDragging()) {  
  15.             //终止控制滑动事件  
  16.             endFakeDrag();  
  17.         }  
  18.         mViewTouchMode = b;  
  19.     }  
  20.   
  21.     /** 
  22.      * 在mViewTouchMode为true的时候,ViewPager不拦截点击事件,点击事件将由子View处理 
  23.      */  
  24.     @Override  
  25.     public boolean onInterceptTouchEvent(MotionEvent event) {  
  26.         if (mViewTouchMode) {  
  27.             return false;  
  28.         }  
  29.         return super.onInterceptTouchEvent(event);  
  30.     }  
  31.   
  32.     @Override  
  33.     public boolean onTouchEvent(MotionEvent ev) {  
  34.         try {  
  35.             return super.onTouchEvent(ev);  
  36.         } catch (Exception e) {  
  37.             return false;  
  38.         }  
  39.     }  
  40.   
  41.     /** 
  42.      * 在mViewTouchMode为true或者滑动方向不是左右的时候,ViewPager将放弃控制点击事件, 
  43.      * 这样做有利于在ViewPager中加入ListView等可以滑动的控件,否则两者之间的滑动将会有冲突 
  44.      */  
  45.     @Override  
  46.     public boolean arrowScroll(int direction) {  
  47.         if (mViewTouchMode) return false;  
  48.         if (direction != FOCUS_LEFT && direction != FOCUS_RIGHT) return false;  
  49.         return super.arrowScroll(direction);  
  50.     }  
  51.   
  52. }  

下面两个文件代码有点多,没有粘出来,后面附有下载地址,大家可以下载下来看看,代码都做了注释的。有什么疑问欢迎交流。

TitleIndicator.java:这个一个带滚动条的选项卡,会随着viewpager的滑动而滑动,其实现思想是这样的:每个选项卡是一个view,根据需要可以add多个view也就是多个选项卡进来,选项卡下部还有一个滚动条,滚动条是用canvas画出来的。所有的invalidate方法均会触发onDraw,当页面滚动的时候,会有一个滚动距离,然后onDraw被触发后,就会在新位置重新画上滚动条(其实就是画线)。

IndicatorFragmentActivity.java:这是IndicatorFragmentActivity的主界面,用于管理上述两个view,对子类提供protected abstract int supplyTabs(List<TabInfo> tabs)接口来生成页面。

下面主要介绍下如何使用这个IndicatorFragmentActivity。

如何使用?

请按如下步骤:

1 新建一个类继承IndicatorFragmentActivity,然后实现supplyTabs抽象方法,提供生成选项卡所需的数据

[java] view
plain
copy

  1. public class MainActivity extends IndicatorFragmentActivity {  
  2.   
  3.     public static final int FRAGMENT_ONE = 0;  
  4.     public static final int FRAGMENT_TWO = 1;  
  5.     public static final int FRAGMENT_THREE = 2;  
  6.   
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.     }  
  11.   
  12.     //在这里提供数据来进行初始化  
  13.     @Override  
  14.     protected int supplyTabs(List<TabInfo> tabs) {  
  15.         tabs.add(new TabInfo(FRAGMENT_ONE, getString(R.string.fragment_one),  
  16.                 FragmentOne.class));  
  17.         tabs.add(new TabInfo(FRAGMENT_TWO, getString(R.string.fragment_two),  
  18.                 FragmentTwo.class));  
  19.         tabs.add(new TabInfo(FRAGMENT_THREE, getString(R.string.fragment_three),  
  20.                 FragmentThree.class));  
  21.   
  22.         //返回的下标表示界面初始化的时候所指向的fragment的序号  
  23.         return FRAGMENT_TWO;  
  24.     }  
  25.   
  26. }  

2 为每个选项卡提供fragment类

最简单的fragment,啥都不做,就加载一个layout然后初始化一个listview。其实我的demo里有3个界面一样的fragment,但是博主为了偷懒,直接写了一个BaseFragment,让它们3个都继承这个BaseFragment,反正界面都一样嘛。

[java] view
plain
copy

  1. public class BaseFragment extends Fragment {  
  2.     protected View mMainView;  
  3.     protected static ArrayList<Map<String, Object>> mlistItems;  
  4.     protected Context mContext;  
  5.   
  6.     static {  
  7.         mlistItems = new ArrayList<Map<String, Object>>();  
  8.         for (int i = 0; i < 20; i++) {  
  9.             Map<String, Object> map = new HashMap<String, Object>();  
  10.             map.put("name", "name#" + i);  
  11.             map.put("sex", i % 2 == 0 ? "male" : "female");  
  12.             mlistItems.add(map);  
  13.         }  
  14.     }  
  15.   
  16.     public BaseFragment() {  
  17.         super();  
  18.     }  
  19.   
  20.     @Override  
  21.     public void onAttach(Activity activity) {  
  22.         super.onAttach(activity);  
  23.         mContext = activity.getApplicationContext();  
  24.     }  
  25.   
  26.     @Override  
  27.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  28.         mMainView = inflater.inflate(R.layout.fragment_one, container, false);  
  29.         ListView listView = (ListView) mMainView.findViewById(R.id.list);  
  30.         SimpleAdapter adapter = new SimpleAdapter(mContext, mlistItems,  
  31.                 R.layout.listview_item, new String[] {  
  32.                         "name", "sex"  
  33.                 }, new int[] {  
  34.                         R.id.name, R.id.download  
  35.                 });  
  36.         listView.setAdapter(adapter);  
  37.         return mMainView;  
  38.     }  
  39.   
  40. }  

这样就ok了,是不是挺简单的,也就是说,如果你想要这种效果的话,只要导入ui包里面的3个类,然后再按上述2个步骤去做就行了,效果也是很好的。另外就是选项卡的颜色以及滚动条的颜色都是可以调的,而且每个选项卡上面是支持显示其他标识的,比如一个小红点啥的,就类似于那种有新消息的状态。有什么问题,欢迎大家在下面留言和我交流。

代码下载:http://download.csdn.net/detail/singwhatiwanna/6680173

时间: 2024-10-02 16:01:02

使用ViewPager+Fragment来实现带滚动条的多屏滑动-IndicatorFragmentActivity的相关文章

Android 开发之BottomBar+ViewPager+Fragment实现炫酷的底部导航效果_Android

BottomBar BottomBar是Github上的一个开源框架,因为从1.3.3开始不支持fragments了,要自己配置,弄了很久,不管是app的fragment还是V4 的程序总是总是闪退.于是就用这种方式实现了,效果还不错.github有详细说明,多余的就不说了. 这个roughike是这个项目的所有者(大神致敬). 我用的是Android studio开发,fragment全部导的V4的包(以为最开始就支持的是v4的,后面也支持了app.fragment). 首先是dependen

android-在做viewpager+fragment时遇到的不知道问题在哪啊

问题描述 在做viewpager+fragment时遇到的不知道问题在哪啊 异常的log 02-26 19:43:27.231: E/AndroidRuntime(9848): FATAL EXCEPTION: main 02-26 19:43:27.231: E/AndroidRuntime(9848): java.lang.IllegalStateException: Must measure with an exact width 02-26 19:43:27.231: E/Android

android ViewPager+Fragment之懒加载

说说写这篇博客的背景吧,前两天去面试,问到一个问题说的是:比如我们首页,是有3个fragment构成的,并且要是实现作用可以滑,那么这个最好的选择就是ViewPager+fragment了,但是我们知道ViewPager+fragment是做预加载的,然而这种方法有一个坏处,当前页面和预加载页面都有大量的网络请求,可能就会比较慢,这样就会造成不好打体验.其实我们忽略的一个问题,Android的fragment里面已经帮我们提供了一个方法setUserVisibleHint.setUserVisi

仿百度壁纸客户端(一)——主框架搭建,自定义Tab+ViewPager+Fragment

仿百度壁纸客户端(一)--主框架搭建,自定义Tab+ViewPager+Fragment 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度壁纸客户端(二)--主页自定义ViewPager广告定时轮播图 仿百度壁纸客户端(三)--首页单向,双向事件冲突处理,壁纸列表的实现 仿百度壁纸客户端(四)--自定义上拉加载实现精选壁纸墙 仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 仿百

Android中在ViewPager+Fragment中有两个Fragment

问题描述 Android中在ViewPager+Fragment中有两个Fragment 一个有ListView,一个有dialogdialog中有个edittext,然后edittext获取到焦点是,第一个Fragment中的getVIew会运行,为什么 解决方案 android中 Fragment中的viewpagerAndroid:fragment中嵌套viewpager,vierpager中有多个fragment 解决方案二: http://www.cnblogs.com/android

viewpager+fragment,其中一个fragment是googlemap

问题描述 viewpager+fragment,其中一个fragment是googlemap Exception when sending the token request. android.os.DeadObjectException at android.os.BinderProxy.transact(Native Method) at maps.bw.a$a$a.a(Unknown Source) at maps.cz.b$1.a(Unknown Source) at maps.cz.b

ViewPager+Fragment取消预加载(延迟加载)

在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragment有个不好或者太好的地方. 例如你在ViewPager中添加了三个Fragment,当加载ViewPager中第一个Fragment时,它会默认帮你预先加载了第二个Fragment,当你加载第二个Fragment时,它会帮你加载第三个Fragment. 这样虽然有时很好,但是用户只需看一个Fragment时,我们就做了一些多余工作加载了第二个Fragment.在这只需要取消Fragmen

界面-android viewpager+Fragment切换问题

问题描述 android viewpager+Fragment切换问题 2C 我切换用的是add方法,已经可以却换过去,那边的测试代码都会自动执行(比如弹框),但是界面却没有过去,还是停留在原页面只上,请问大神应该怎么解决呢. public void switchContent(Fragment from Fragment to) { if (mContent != to) { mContent = to; FragmentTransaction transaction = getFragmen

viewpager + fragment 滑动后fragment显示空白

问题描述 viewpager + fragment 滑动后fragment显示空白 如题,但是点击tab切换可以正常显示,只出现在滑动的情况,而且Android5.0以下正常,请教大神是怎么回事 解决方案 ViewPager + Fragment 滑动ViewPager + Fragment实现滑动标签页ViewPager + Fragment实现滑动标签页 解决方案二: Fragment是v4包的吗? 解决方案三: activity继承v4包中的FragmentActivity试试