ViewPager+fragment實現相似微信5.0帶滾動條的多屏滑動效果

  

  

  轉載請註明出處。java

 

  在本人開發第一個安卓應用的時候就想到多屏滑動的界面(相似於微信5.0的滑動界面,已經流行了很長一段時間),鑑於知識有限,變依靠Tabhos實現了這種效果。思路是:監聽並計算滑動距離,切換Tabhost。你可能已經想到了,沒錯,效果特別差,Tabhost切換僅僅是刷了一下頁面而已,什麼也沒作。後來在網上搜到,導入(如今新建項目都是默認導入)android-support-v4.jar實現裏面的ViewPager就好了。android

  在Activity裏面創建一個ViewPager,而後將咱們須要的視圖添加到裏面就好了。固然最好的方法是ViewPager+Fragment去實現。Fragment相似於Activity,有本身的生命週期。canvas

Fragment(想要具體瞭解就去谷歌查詢API文檔)微信

  

  

 

  如下爲正文:佈局

項目文件:this

  

    PagerScrollerActivity和TitleIndicator爲此項目的核心功能。spa

PagerScrollerActivity是就是一個繼承了FragmentActivity抽象的類,實現了項目具體功能(管理TitleIndicator).net

  關鍵代碼:blog

    private void initView() throws IndexOutOfBoundsException, NullPointerException {
        setTabsAndAdapter();    //抽象方法,用於實例化Fragment頁面以及標題欄

        viewPager = (ViewPager) findViewById(R.id.vPager);
        // 設置viewpager內部頁面之間的間距
        viewPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.fragment_viewpager_margin));
        // 設置viewpager內部頁面間距的drawable
        viewPager.setPageMarginDrawable(color.myblue);
        
        viewPager.setAdapter(adapter);
        
        //必須讓viewPager設置此OnPageChangeListener的實現類,才能對滑動和頁面狀態監聽
        viewPager.setOnPageChangeListener(this);

        title = (TitleIndicator) findViewById(R.id.title);
        title.init(tabs, viewPager);
        }

    }

 PagerScrollerActivity實現 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)用於監聽滾動過程,以實現標題欄的實時滾動。繼承

    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    //title 爲 TitleIndicator的實例 title.onScroll((viewPager.getWidth() + viewPager.getPageMargin()) * position + positionOffsetPixels);       
     //讀者可在紙上畫出多個頁面的示意圖,本身進行計算便能得出這個結果(將座標想象成全部頁面以及變局的總和) }

 

  

TitleIndicator是標題欄,數據來自List<TabInfo> tabs,實現實時滾動遊標以及點擊子標題切換到頁面

先貼上TabInfo的關鍵代碼

public class TabInfo {
  
  //用於獲取到子標題的佈局內容,須要的話能夠添加ImageView. public View getTab(LayoutInflater inflater, ViewGroup root) { tab = inflater.inflate(R.layout.tab_item, root, false); tv = (TextView) tab.findViewById(R.id.tab_name); tv.setText(name); tab.setId(id); return tab; } }

 TitleIndicator的初始化操做

  public void init(List<TabInfo> tabs, ViewPager viewPager) {
        this.viewPager = viewPager;
        setWillNotDraw(false);// 調用invalidate()時強制調用onDraw()方法
        
    totalTabs = tabs.size(); // 設置標題的每個Tab的位置屬性 for (int i = 0; i < totalTabs; i++) { View view = tabs.get(i).getTab(inflater, this); LinearLayout.LayoutParams lP = (LinearLayout.LayoutParams) view.getLayoutParams(); lP.gravity = Gravity.CENTER_VERTICAL; view.setOnClickListener(this); addView(view); } setCurrentTab(currentTab); }

  TitleIndicator的關鍵代碼,用於重繪遊標

    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);

        if (!initialize) {
            initTab(canvas);
        }

        float scroll_x = 0;
        if (totalTabs != 0) {
            // 計算滾動條實際滾動距離
            scroll_x = (currentLocationlX - ((currentTab) * (mWidth + viewPager.getPageMargin()))) / totalTabs;
        } else {
            scroll_x = currentLocationlX;
        }

        cursorPath.rewind();// 清楚以前的路徑狀態

        float left_x = currentTab * cursorWidth + scroll_x;
        float right_x = (currentTab + 1) * cursorWidth + scroll_x;
        float top_y = mHeight - cursorHeight - 2;
        float bottom_y = mHeight - 2;

        cursorPath.moveTo(left_x, top_y); // 移動到基點到左上角
        cursorPath.lineTo(right_x, top_y); // 畫線:基點到右上角
        cursorPath.lineTo(right_x, bottom_y);// 基點到右下角
        cursorPath.lineTo(left_x, bottom_y);// 基點到左下角
        cursorPath.close();
        canvas.drawPath(cursorPath, paint);
        initialize = true;
    }

  設置當前顯示的頁面

    public void setCurrentTab(int i) {
        // 清除舊Tab的文字狀態
        View view = getChildAt(currentTab);
        view.setSelected(false);

        currentTab = i;
        // 設置新Tab的文字狀態
        view = getChildAt(currentTab);
        view.setSelected(true);
        invalidate();

        if (viewPager.getCurrentItem() != i) viewPager.setCurrentItem(i);

    }

 源代碼下載

  注:轉載請註明出處。  

  大神就不要看這麼渣的文章了,新手看看就還行。

  本人在網上找了許多demo。後來發現幾乎都是同一個大神的文章(http://blog.csdn.net/singwhatiwanna/article/details/17201587),這位大神的demo功能實現很是完善,但本人徹底是安卓(java)新手,裏面核心代碼可以看懂,可是許多細節的不是很清楚。在讀懂這個demo的代碼後,本身嘗試着寫一個相似的demo(幾乎是同樣的,只是功能簡單些,對於我這種安卓新手來講比較容易讀懂的)。

相關文章
相關標籤/搜索