使用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作了一個簡單的界面,你們應該一看就懂,好了,言歸正傳。java

IndicatorFragmentActivity的實現過程

1 新建一個工程,目錄結構以下:


2 實現ui包下的三個文件

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

1 新建一個類繼承IndicatorFragmentActivity,而後實現supplyTabs抽象方法,提供生成選項卡所需的數據

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;
    }

}

2 爲每一個選項卡提供fragment類

最簡單的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



代碼下載:http://download.csdn.net/detail/singwhatiwanna/6680173

相關文章
相關標籤/搜索