Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android app : ViewPager

Android app : ViewPager

編輯:關於Android編程

什麼是ViewPager,剛一聽到這個詞,我們可能感覺很奇怪,但是我相信我們大部分人都曾見到過這些界面的。其實它就是我們在安裝好一個app之後第一次使用時的那些引導界面的效果。這就是通過ViewPager來完成滴。今天,就讓我們一起走進ViewPager的世界吧。


理論基礎


其實說是理論基礎,也只不過是一些小知識點罷了,所以不要緊張咯。ViewPager在ADT開發時使用到了android.support.v4.view.ViewPager控件,我們需要知道這點就可以了。 我們可以把ViewPager看作是一個ListView樣式的控件,然後按照對待ListView的眼光來看待ViewPager,就會很輕松了。 ListView需要一個適配器,而ViewPager同樣也是如此;ListView需要注冊Item的事件偵聽,ViewPager同樣如此。至於底層的細節我們稍後再說。

了解了上面的這些,相信我們心中都有了一個大致的了解了吧。那我們就正式開始咯。

ViewPager怎麼使用?


首先我們需要在XML文件中進行聲明,注意我們引用的是android.support.v4.view.ViewPager控件哦,如下:

 
  • 12345678

然後是在Java代碼中findViewById一下,免得出現NullPointerExcetion.
了解到了ViewPager是一個View的容器,那麼我們當然要有View才行了,所以我們在layout文件夾下創建幾個用於呈現的view。由於比較相似,我這裡就僅僅寫出一個XML文件吧。




    

    

現在萬事俱備,只欠東風了。所以我們就需要創建一個適配器了,這裡需要注意的是適配器要繼承自PagerAdapter ,具體的代碼如下:

package com.mark.viewpagerdemo;

import java.util.List;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;

/**
 * 這個類的作用就是對於ViewPager的Activity(View)的切換的
 * 時候需要的一個適配器的作用,其實ViewPager的原理就可以看作是一個ListView就行了
 * @author lhdn
 *
 */
public class ViewPageAdapter extends PagerAdapter{

    //list是為了存儲容器中的view,context的作用就是上下文
    private List views;
    private Context context;

    public ViewPageAdapter(List mViews , Context mContext) {
        this.context = mContext;
        this.views = mViews;
    }

    /**
     * 將不需要呈現的view及時的銷毀
     */
    @Override
    public void destroyItem(View container, int position, Object object) {
        ((ViewPager) container).removeView(views.get(position));
    }

    /**
     * 該方法的作用類似於ListViewAdapter的那個getView的作用
     */
    @Override
    public Object instantiateItem(View container, int position) {
        ((ViewPager) container).addView(views.get(position));
        return views.get(position);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return views.size();
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        // 判斷當前獲得的view是不是我們想要得到的view
        return (arg0 == arg1);
    }

}
  • 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657

其中方法:

@Override
    public Object instantiateItem(View container, int position) {
        ((ViewPager) container).addView(views.get(position));
        return views.get(position);
    }
  • 12345

就好比我們的ListViewAdapter的getView方法。功能就是獲得一個view,即可。

如果不需要在圖片上添加效果的話,這樣其實就已經是搞定了,我們可以測試一下效果,發現這個小案例已經是可行的了。


ViewPager添加一些效果


所謂添加效果,就是添加上幾個小圓點,比如我們滑動View的時候下面會出現的一些小亮點和小暗點等,其目的是為了顯示我們確實滑動了ViewPager,也為了美觀嘛。那麼我們要怎麼實現呢?答案就是使用ImageView就可以了,但是切記只需要在ViewPager所在的界面進行添加就可以了,而不需要為其他的XML文件進行添加。然後我們在ViewPager的OnPageChangeListener處理事件中進行相關的設置就可以了。如下:





    
    

    

        

        

        
    


  • 1234567891011121314151617181920212223242526272829303132333435363738394041424344
package com.mark.viewpagerdemo;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class Guide extends Activity implements OnPageChangeListener {

    private ViewPager vp;
    // 因為viewpager的使用要街注意一個適配器,所以要創建一個適配器的對象
    private ViewPageAdapter vpAdapter;
    // 創建一些視圖View,用於放置到我們的ViewPager容器中
    private List views;
    // 存儲圖像的小點
    private ImageView[] dots;
    // 圖片小點的ID值
    int[] ids = new int[] { R.id.iv1, R.id.iv2, R.id.iv3 };

    private Button enter ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.guide);
        initViews();
        initDots();
    }

    /**
     * 初始化ViewPager機器內部的view視圖
     */
    public void initViews() {
        views = new ArrayList();
        LayoutInflater inflater = LayoutInflater.from(this);
        // 向ViewPager中添加view
        views.add(inflater.inflate(R.layout.one, null));
        views.add(inflater.inflate(R.layout.two, null));
        views.add(inflater.inflate(R.layout.three, null));

        // 為進入主界面的按鈕申請資源,由於button的值在第三個view中,而這裡是Guide的
        // 所以,要先得到第三個view之後,才能使用findViewById()方法
        enter = (Button) views.get(2).findViewById(R.id.start_btn);
        enter.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent = new Intent(Guide.this, MainActivity.class);
                startActivity(intent);
                finish();
            }
        });

        // 創建ViewPager以及添加適配器
        vp = (ViewPager) findViewById(R.id.viewpager);
        vpAdapter = new ViewPageAdapter(views, this);
        vp.setAdapter(vpAdapter);
        // 為ViewPager 注冊監聽事件
        vp.setOnPageChangeListener(this);

    }

    /**
     * 初始化需要的點的資源
     */
    public void initDots() {
        dots = new ImageView[views.size()];
        for (int i = 0; i < dots.length; i++) {
            dots[i] = (ImageView) findViewById(ids[i]);
        }
    }

    // ///////////////////////////////////////////onViewPagerChangeListener接口的方法開始

    @Override
    public void onPageScrollStateChanged(int arg0) {
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
    }

    @Override
    public void onPageSelected(int arg0) {
        for (int i = 0; i < ids.length; i++) {
            if (arg0 == i) {
                dots[i].setImageResource(R.drawable.login_point_selected);
            } else {
                dots[i].setImageResource(R.drawable.login_point);
            }
        }

    }
    // ///////////////////////////////////////////onViewPagerChangeListener接口方法結束

}
  • 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107

測試後發現,成了!這樣就已經是完整的實現了我們需要的功能了。


深入的思考


雖然我們已經完成了ViewPager的使用了,但是仔細的想一想,我們真的完成了嗎?
其實並不是的,因為這樣的話,我們每一次打開這個APP,就會出現一個引導界面,這樣是不符合事實的,因為我們並不希望每一次都看到這個引導界面,所以我們現在要完成的就是如何實現只在第一次的時候才顯示引導界面。

實現的思路:使用一個變量,放置到文件的存儲中,每次打開APP的時候檢驗這個值,如果是第一次使用,就跳轉到引導界面,如果不是,就跳轉到主界面,所以我們現在就要實現這個中間層的界面了。實現的效果就是打開APP的時候顯示這個中間層的界面,然後在跳轉到其他的引導界面或者主界面。


XML代碼如下:




    

  • 12345678910111213
package com.mark.viewpagerdemo;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.Handler;

public class Welcome extends Activity {

    //設置一個延遲時間,為界面的跳轉來爭取時間
    private static final int TIME = 2000;
    private static final int GO_HOME = 1000;
    private static final int GO_GUIDE = 1001;

    //設置一個參數,實現只為第一次進入的時候顯示guide界面,這個參數要存儲進本地的一個參數,
    //見下面的initValue方法
    private boolean isFirstIn = true;
    private void initValue(){
        SharedPreferences sp = getSharedPreferences("ViewPagerDemo",MODE_PRIVATE);
        isFirstIn = sp.getBoolean("isFirstIn", true);
        if(isFirstIn) {
            mHandler.sendEmptyMessageDelayed(GO_GUIDE,TIME);
            Editor editor = sp.edit();
            editor.putBoolean("isFirstIn", false);
            editor.commit();
        }else{
            mHandler.sendEmptyMessageDelayed(GO_HOME,TIME);
        }
    }


    //等待時間不能在主進程,所以使用handler
    private Handler mHandler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch(msg.what){
            case GO_HOME:
                goHome();
                break;
            case GO_GUIDE:
                goGuide();
                break;
            }
        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setContentView(R.layout.welcome);
        initValue();
    }

    private void goHome(){
        Intent i = new Intent(Welcome.this,MainActivity.class);
        startActivity(i);
        finish();
    }
    private void goGuide(){
        Intent i = new Intent(Welcome.this,Guide.class);
        startActivity(i);
        finish();
    }

}
  • 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869

Welcome.java 深入剖析:


由於我們設置了在歡迎界面的等待時間,所以就最好是使用handler來實現界面的更新,這樣符合“在主線程更新UI”原則。於是使用了SharedPreferences來實現了值得記錄。

優化思路,其實我覺得在initValue方法中初始化的方式也不是特別的好,如果在靜態代碼中進行的話,效果會更好。

handler的使用是至關重要的一個知識點,我們要記得在主線程中進行UI界面的更新,所以要在主線程中對其他線程傳遞過來的,msg.what進行處理。


測試結果


點擊運行完程序之後,我們會發現只有在第一次使用APP的時候才會出現引導界面,一旦我們進入過了主界面,引導界面就不會再出現了。除非你重新安裝了,(^__^) 嘻嘻……


知識點回顧


這個小項目的主要的流程是這樣的,
* 先是了解了什麼是ViewPager,
* 然後學會了ViewPagerAdapter適配器的使用,
* 再然後就是對PageChange事件的處理
* 學會了如何使用handler配合UI的更新
* 再就是添加了常量值的配合實現了“一次性計劃”
* 接下來就真的完成了,雖然界面不好看,但是核心的思想卻是都在這裡了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved