App引導介面,可以這麼玩
什麼是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控制項哦,如下:
然後是在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); }}
其中方法:
@Override public Object instantiateItem(View container, int position) { ((ViewPager) container).addView(views.get(position)); return views.get(position); }
就好比我們的ListViewAdapter的getView方法。功能就是獲得一個view,即可。
如果不需要在圖片上添加效果的話,這樣其實就已經是搞定了,我們可以測試一下效果,發現這個小案例已經是可行的了。
ViewPager添加一些效果
所謂添加效果,就是添加上幾個小圓點,比如我們滑動View的時候下面會出現的一些小亮點和小暗點等,其目的是為了顯示我們確實滑動了ViewPager,也為了美觀嘛。那麼我們要怎麼實現呢?答案就是使用ImageView就可以了,但是切記只需要在ViewPager所在的介面進行添加就可以了,而不需要為其他的XML檔案進行添加。然後我們在ViewPager的OnPageChangeListener處理事件中進行相關的設定就可以了。如下:
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介面方法結束}
測試後發現,成了!這樣就已經是完整的實現了我們需要的功能了。
深入的思考
雖然我們已經完成了ViewPager的使用了,但是仔細的想一想,我們真的完成了嗎?
其實並不是的,因為這樣的話,我們每一次開啟這個APP,就會出現一個引導介面,這樣是不符合事實的,因為我們並不希望每一次都看到這個引導介面,所以我們現在要完成的就是如何?只在第一次的時候才顯示引導介面。
實現的思路:使用一個變數,放置到檔案的儲存中,每次開啟APP的時候檢驗這個值,如果是第一次使用,就跳轉到引導介面,如果不是,就跳轉到主介面,所以我們現在就要實現這個中介層的介面了。實現的效果就是開啟APP的時候顯示這個中介層的介面,然後在跳轉到其他的引導介面或者主介面。
XML代碼如下:
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(); }}
Welcome.java 深入剖析:
由於我們設定了在歡迎介面的等待時間,所以就最好是使用handler來實現介面的更新,這樣符合“在主線程更新UI”原則。於是使用了SharedPreferences來實現了值得記錄。
最佳化思路,其實我覺得在initValue方法中初始化的方式也不是特別的好,如果在靜態代碼中進行的話,效果會更好。
handler的使用是至關重要的一個知識點,我們要記得在主線程中進行UI介面的更新,所以要在主線程中對其他線程傳遞過來的,msg.what進行處理。
測試結果
點擊運行完程式之後,我們會發現只有在第一次使用APP的時候才會出現引導介面,一旦我們進入過了主介面,引導介面就不會再出現了。除非你重新安裝了,(^__^) 嘻嘻……
知識點回顧
這個小項目的主要的流程是這樣的,
* 先是瞭解了什麼是ViewPager,
* 然後學會了ViewPagerAdapter適配器的使用,
* 再然後就是對PageChange事件的處理
* 學會了如何使用handler配合UI的更新
* 再就是添加了常量值的配合實現了“一次性計劃”
* 接下來就真的完成了,雖然介面不好看,但是核心的思想卻是都在這裡了。