在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作了一个简单的界面,你们应该一看就懂,好了,言归正传。java
ViewPagerCompat.java:这是一个ViewPager的增强类,主要是为了解决滑动冲突的问题。否则的话,在ViewPager内部加入ListView等可滑动控件,二者之间会产生干扰。
android
在这里想多说一下,关于此类问题,解决办法是:重写父控件的onInterceptTouchEvent函数,在move的时候根据须要返回true,好比左右滑动返回true,其余状况均返回false。这样,当左右滑动的时候,因为onInterceptTouchEvent返回了true,父控件就能处理,其余状况,事件将传递到listview中,listview自身能够处理上下滑动。canvas
public class ViewPagerCompat extends ViewPager { //mViewTouchMode表示ViewPager是否全权控制滑动事件,默认为false,即不控制 private boolean mViewTouchMode = false; public ViewPagerCompat(Context context, AttributeSet attrs) { super(context, attrs); } public void setViewTouchMode(boolean b) { if (b && !isFakeDragging()) { //全权控制滑动事件 beginFakeDrag(); } else if (!b && isFakeDragging()) { //终止控制滑动事件 endFakeDrag(); } mViewTouchMode = b; } /** * 在mViewTouchMode为true的时候,ViewPager不拦截点击事件,点击事件将由子View处理 */ @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (mViewTouchMode) { return false; } return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent ev) { try { return super.onTouchEvent(ev); } catch (Exception e) { return false; } } /** * 在mViewTouchMode为true或者滑动方向不是左右的时候,ViewPager将放弃控制点击事件, * 这样作有利于在ViewPager中加入ListView等能够滑动的控件,不然二者之间的滑动将会有冲突 */ @Override public boolean arrowScroll(int direction) { if (mViewTouchMode) return false; if (direction != FOCUS_LEFT && direction != FOCUS_RIGHT) return false; return super.arrowScroll(direction); } }
下面两个文件代码有点多,没有粘出来,后面附有下载地址,你们能够下载下来看看,代码都作了注释的。有什么疑问欢迎交流。ide
TitleIndicator.java:这个一个带滚动条的选项卡,会随着viewpager的滑动而滑动,其实现思想是这样的:每一个选项卡是一个view,根据须要能够add多个view也就是多个选项卡进来,选项卡下部还有一个滚动条,滚动条是用canvas画出来的。全部的invalidate方法均会触发onDraw,当页面滚动的时候,会有一个滚动距离,而后onDraw被触发后,就会在新位置从新画上滚动条(其实就是画线)。
函数
IndicatorFragmentActivity.java:这是IndicatorFragmentActivity的主界面,用于管理上述两个view,对子类提供protected abstract int supplyTabs(List<TabInfo> tabs)接口来生成页面。ui
下面主要介绍下如何使用这个IndicatorFragmentActivity。google
请按以下步骤:spa
public class MainActivity extends IndicatorFragmentActivity { public static final int FRAGMENT_ONE = 0; public static final int FRAGMENT_TWO = 1; public static final int FRAGMENT_THREE = 2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } //在这里提供数据来进行初始化 @Override protected int supplyTabs(List<TabInfo> tabs) { tabs.add(new TabInfo(FRAGMENT_ONE, getString(R.string.fragment_one), FragmentOne.class)); tabs.add(new TabInfo(FRAGMENT_TWO, getString(R.string.fragment_two), FragmentTwo.class)); tabs.add(new TabInfo(FRAGMENT_THREE, getString(R.string.fragment_three), FragmentThree.class)); //返回的下标表示界面初始化的时候所指向的fragment的序号 return FRAGMENT_TWO; } }
最简单的fragment,啥都不作,就加载一个layout而后初始化一个listview。其实个人demo里有3个界面同样的fragment,可是博主为了偷懒,直接写了一个BaseFragment,让它们3个都继承这个BaseFragment,反正界面都同样嘛。.net
public class BaseFragment extends Fragment { protected View mMainView; protected static ArrayList<Map<String, Object>> mlistItems; protected Context mContext; static { mlistItems = new ArrayList<Map<String, Object>>(); for (int i = 0; i < 20; i++) { Map<String, Object> map = new HashMap<String, Object>(); map.put("name", "name#" + i); map.put("sex", i % 2 == 0 ? "male" : "female"); mlistItems.add(map); } } public BaseFragment() { super(); } @Override public void onAttach(Activity activity) { super.onAttach(activity); mContext = activity.getApplicationContext(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mMainView = inflater.inflate(R.layout.fragment_one, container, false); ListView listView = (ListView) mMainView.findViewById(R.id.list); SimpleAdapter adapter = new SimpleAdapter(mContext, mlistItems, R.layout.listview_item, new String[] { "name", "sex" }, new int[] { R.id.name, R.id.download }); listView.setAdapter(adapter); return mMainView; } }
这样就ok了,是否是挺简单的,也就是说,若是你想要这种效果的话,只要导入ui包里面的3个类,而后再按上述2个步骤去作就好了,效果也是很好的。另外就是选项卡的颜色以及滚动条的颜色都是能够调的,并且每一个选项卡上面是支持显示其余标识的,好比一个小红点啥的,就相似于那种有新消息的状态。有什么问题,欢迎你们在下面留言和我交流。code