在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