編輯:關於android開發
什麼是ViewPager,剛一聽到這個詞,我們可能感覺很奇怪,但是我相信我們大部分人都曾見到過這些界面的。其實它就是我們在安裝好一個app之後第一次使用時的那些引導界面的效果。這就是通過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,即可。
如果不需要在圖片上添加效果的話,這樣其實就已經是搞定了,我們可以測試一下效果,發現這個小案例已經是可行的了。
所謂添加效果,就是添加上幾個小圓點,比如我們滑動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();
}
}
由於我們設置了在歡迎界面的等待時間,所以就最好是使用handler來實現界面的更新,這樣符合“在主線程更新UI”原則。於是使用了SharedPreferences來實現了值得記錄。
優化思路,其實我覺得在initValue方法中初始化的方式也不是特別的好,如果在靜態代碼中進行的話,效果會更好。
handler的使用是至關重要的一個知識點,我們要記得在主線程中進行UI界面的更新,所以要在主線程中對其他線程傳遞過來的,msg.what進行處理。
點擊運行完程序之後,我們會發現只有在第一次使用APP的時候才會出現引導界面,一旦我們進入過了主界面,引導界面就不會再出現了。除非你重新安裝了,(^__^) 嘻嘻……
這個小項目的主要的流程是這樣的,
* 先是了解了什麼是ViewPager,
* 然後學會了ViewPagerAdapter適配器的使用,
* 再然後就是對PageChange事件的處理
* 學會了如何使用handler配合UI的更新
* 再就是添加了常量值的配合實現了“一次性計劃”
* 接下來就真的完成了,雖然界面不好看,但是核心的思想卻是都在這裡了。
Android開源項目分類匯總(六)工具庫 主要包括那些不錯的開發庫,包括依賴注入框架、圖片緩存、網絡相關、數據庫ORM建模、Android公共庫、Android 高版本
android WindowManager解析與騙取QQ密碼案例分析 最近在網上看見一個人在烏雲上提了一個漏洞,應用可以開啟一個後台Service,檢測當前頂部應用
安卓開源項目周報0117,安卓開源項目0117由OpenDigg 出品的安卓開源項目周報第六期來啦。我們的安卓開源周報集合了OpenDigg一周來新收錄的優質的
Android View體系(一)視圖坐標系 前言 Android View體系是界面編程的核心,他的重要性不亞於Android四大組件,在這個系列中我會陸續講到Vi