ViewPager的运用

ViewPager

一般来说在Android开发中ViewPager的运用还算比较常见,比如说Android手机微信的界面之前的左右滑动的功能,还有比如说淘宝上广告图片的轮播效果。都是可以用ViewPager来实现和完成。
ViewPager继承自ViewGroup,也就是ViewPager是一个容器类,可以包含其他的View类。�是一个允许使用者左右滑动数据页面的布局管理器。你可以通过一个适配器(PagerAdapter)来管理要显示的页面。
PagerAdapter是用于“将多个页面填充到ViewPager”的适配器的一个基类,大多数情况下,你们可能更倾向于使用一个实现了PagerAdapter并且更加具体的适配器

要通过自己写的一个适配器来继承PagerAdapter的,其中有四个方法是必须重写的。

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

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        // TODO Auto-generated method stub
        return arg0 == arg1;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // TODO Auto-generated method stub
        container.addView(list.get(position));
        return list.get(position);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // TODO Auto-generated method stub
        container.removeView(list.get(position));
    }

1,getCount() // 获取要滑动的控件的数量。�
2,isViewFromObject(View, Object) // 来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可

接下来的两个方法是需要手动来添加到适配器中的。

3,instantiateItem(ViewGroup, int) // 当要显示的图片可以进行缓存的时候,会调用这个方法进行显示图片的初始化,我们将要显示的ImageView加入到ViewGroup中,然后作为返回值返回即可
4,destroyItem(ViewGroup, int, Object) // PagerAdapter只缓存三张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁

在创建适配器的同时也要在适配器创建一个构造方法(构造方法的参数是根据要传的数据内容来给定的)
然后在你的Activity中调用适配器就OK了。


viewpager不直接处理每一个视图而是将各个视图与一个键联系起来。这个键用来跟踪且唯一代表一个页面,不仅如此,该键还独立于这个页面所在adapter的位置。当pageradapter将要改变的时候他会调用startUpdate函数,接下来会调用一次或多次的instantiateItem或者destroyItem。最后在更新的后期会调用finishUpdate。当finishUpdate返回时 instantiateItem返回的对象应该添加到父ViewGroup destroyItem返回的对象应该被ViewGroup删除。
isViewFromObject(View, Object)代表了当前的页面是否与给定的键相关联。
isViewFromObject
功能:该函数用来判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是代表的同一个视图(即它俩是否是对应的,对应的表示同一个View)
返回值:如果对应的是同一个View,返回True,否则返回False。


还有没有结束,这才刚刚开始,接下来处理ViewPager滑动的事件;
给ViewPager设置监听的接口是OnPageChangeListener。当去实现这个接口的时候回重写其中的一下方法:

public void onPageScrollStateChanged(int arg0) {

    // TODO Auto-generated method stub

}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
    // TODO Auto-generated method stub

}

@Override
public void onPageSelected(int arg0) {
    // TODO Auto-generated method stub
    
}

现在我们是做简单的微信滑动的功能的话,只需要在onPageSelected()中添加滑动事件就可以。


简单说一下上述三种方法的作用
onPageScrollStateChanged(int arg0) ,此方法是在状态改变的时候调用,其中arg0这个参数
有三种状态(0,1,2)。arg0 ==1的正在滑动,arg0==2的滑动完毕了,arg0==0的什么都没做。
当页面开始滑动的时候,三种状态的变化顺序为(1,2,0)

onPageScrolled(int arg0,float arg1,int arg2) ,当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到
调用。其中三个参数的含义分别为:
arg0 :当前页面,及你点击滑动的页面
arg1:当前页面偏移的百分比
arg2:当前页面偏移的像素位置

onPageSelected(int arg0) : 此方法是页面跳转完后得到调用,arg0是你当前选中的页面的Position(位置编号)。


ViewPager更多的时候会与Fragment一起使用。Android提供了一些专门的适配器来让ViewPager与Fragment一起工作,也就是FragmentPagerAdapter与FragmentStatePagerAdapter。他们基本上可以满足大部分常见的需求�
在大部分时候,项目中的ViewPager会和Fragment同时出现,每一个ViewPager的页面就是一个Fragment(微信主页)�Android提供了一些专门的适配器来让ViewPager与Fragment一起工作,也就是FragmentPagerAdapter与FragmentStatePagerAdapter。

FragmentPagerAdapter继承自PagerAdapter ,主要用来展示多个Fragment页面,并且每一个Fragment都会被保存在fragment manager中。
FragmentPagerAdapter最适用于那种少量且相对静态的页面,例如几个tab页。每一个用户访问过的fragment都会被保存在内存中对于较多的页面集合,更推荐使用FragmentStatePagerAdapter。

FragmentStatePagerAdapter继承自PagerAdapter,主要使用Fragment来管理每个页面。这个类同样用来保存和恢复fragment页面的状态。
FragmentStatePagerAdapter更多用于大量页面,例如视图列表。当某个页面对用户不再可见时,他们的整个fragment就会被销毁,仅保留fragment状态。相比于FragmentPagerAdapter,这样做的好处是在访问各个页面时能节约大量的内存开销,但代价是在页面切换时会增加非常多的开销。
FragmentPagerAdapter与FragmentStatePagerAdapter存在着大量相似之处,用法也差不多,他们之间最大的不同在于:用户访问过的页面不可见之后是否会保留在内存中,而这个区别也构成了他们使用场景的不同。


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

public class SplashActivity extends Activity {
boolean isFirstIn = false;

private static final int GO_HOME = 1000;  
private static final int GO_GUIDE = 1001;  
// 延迟3秒  
private static final long SPLASH_DELAY_MILLIS = 3000;  

private static final String SHAREDPREFERENCES_NAME = "first_pref";  

/** 
 * Handler:跳转到不同界面 
 */  
private Handler mHandler = new Handler() {  

    @Override  
    public void handleMessage(Message msg) {  
        switch (msg.what) {  
        case GO_HOME:  
            goHome();  
            break;  
        case GO_GUIDE:  
            goGuide();  
            break;  
        }  
        super.handleMessage(msg);  
    }  
};  

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.splash);  

    init();  
}  

private void init() {  
    // 读取SharedPreferences中需要的数据  
    // 使用SharedPreferences来记录程序的使用次数  
    SharedPreferences preferences = getSharedPreferences(  
            SHAREDPREFERENCES_NAME, MODE_PRIVATE);  

    // 取得相应的值,如果没有该值,说明还未写入,用true作为默认值  
    isFirstIn = preferences.getBoolean("isFirstIn", true);  

    // 判断程序与第几次运行,如果是第一次运行则跳转到引导界面,否则跳转到主界面  
    if (!isFirstIn) {  
        // 使用Handler的postDelayed方法,3秒后执行跳转到MainActivity  
        mHandler.sendEmptyMessageDelayed(GO_HOME, SPLASH_DELAY_MILLIS);  
    } else {  
        mHandler.sendEmptyMessageDelayed(GO_GUIDE, SPLASH_DELAY_MILLIS);  
    }  

}  

private void goHome() {  
    Intent intent = new Intent(SplashActivity.this, MainActivity.class);  
    SplashActivity.this.startActivity(intent);  
    SplashActivity.this.finish();  
}  

private void goGuide() {  
    Intent intent = new Intent(SplashActivity.this, GuideActivity.class);  
    SplashActivity.this.startActivity(intent);  
    SplashActivity.this.finish();  
}  

}
GuideActivity.java引导界面


import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
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.widget.ImageView;
import android.widget.LinearLayout;
import cn.eoe.leigo.splash.adapter.ViewPagerAdapter;

public class GuideActivity extends Activity implements OnPageChangeListener {

private ViewPager vp;  
private ViewPagerAdapter vpAdapter;  
private List<View> views;  

// 底部小点图片  
private ImageView[] dots;  

// 记录当前选中位置  
private int currentIndex;  

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.guide);  

    // 初始化页面  
    initViews();  

    // 初始化底部小点  
    initDots();  
}  

private void initViews() {  
    LayoutInflater inflater = LayoutInflater.from(this);  

    views = new ArrayList<View>();  
    // 初始化引导图片列表  
    views.add(inflater.inflate(R.layout.what_new_one, null));  
    views.add(inflater.inflate(R.layout.what_new_two, null));  
    views.add(inflater.inflate(R.layout.what_new_three, null));  
    views.add(inflater.inflate(R.layout.what_new_four, null));  

    // 初始化Adapter  
    vpAdapter = new ViewPagerAdapter(views, this);  
      
    vp = (ViewPager) findViewById(R.id.viewpager);  
    vp.setAdapter(vpAdapter);  
    // 绑定回调  
    vp.setOnPageChangeListener(this);  
}  

private void initDots() {  
    LinearLayout ll = (LinearLayout) findViewById(R.id.ll);  

    dots = new ImageView[views.size()];  

    // 循环取得小点图片  
    for (int i = 0; i < views.size(); i++) {  
        dots[i] = (ImageView) ll.getChildAt(i);  
        dots[i].setEnabled(true);// 都设为灰色  
    }  

    currentIndex = 0;  
    dots[currentIndex].setEnabled(false);// 设置为白色,即选中状态  
}  

private void setCurrentDot(int position) {  
    if (position < 0 || position > views.size() - 1  
            || currentIndex == position) {  
        return;  
    }  

    dots[position].setEnabled(false);  
    dots[currentIndex].setEnabled(true);  

    currentIndex = position;  
}  

// 当滑动状态改变时调用  
@Override  
public void onPageScrollStateChanged(int arg0) {  
}  

// 当当前页面被滑动时调用  
@Override  
public void onPageScrolled(int arg0, float arg1, int arg2) {  
}  

// 当新的页面被选中时调用  
@Override  
public void onPageSelected(int arg0) {  
    // 设置底部小点选中状态  
    setCurrentDot(arg0);  
}  

}
ViewPagerAdapter.java。ViewPager的适配器


import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import cn.eoe.leigo.splash.MainActivity;
import cn.eoe.leigo.splash.R;

/**
*/
public class ViewPagerAdapter extends PagerAdapter {

// 界面列表  
private List<View> views;  
private Activity activity;  
private static final String SHAREDPREFERENCES_NAME = "first_pref";  
public ViewPagerAdapter(List<View> views, Activity activity) {  
    this.views = views;  
    this.activity = activity;  
}  

// 销毁arg1位置的界面  
@Override  
public void destroyItem(View arg0, int arg1, Object arg2) {  
    ((ViewPager) arg0).removeView(views.get(arg1));  
}  

@Override  
public void finishUpdate(View arg0) {  
}  

// 获得当前界面数  
@Override  
public int getCount() {  
    if (views != null) {  
        return views.size();  
    }  
    return 0;  
}  

// 初始化arg1位置的界面  
@Override  
public Object instantiateItem(View arg0, int arg1) {  
    ((ViewPager) arg0).addView(views.get(arg1), 0);  
    if (arg1 == views.size() - 1) {  
        ImageView mStartWeiboImageButton = (ImageView) arg0  
                .findViewById(R.id.iv_start_weibo);  
        mStartWeiboImageButton.setOnClickListener(new OnClickListener() {  

            @Override  
            public void onClick(View v) {  
                // 设置已经引导  
                setGuided();  
                goHome();  

            }  

        });  
    }  
    return views.get(arg1);  
}  

private void goHome() {  
    // 跳转  
    Intent intent = new Intent(activity, MainActivity.class);  
    activity.startActivity(intent);  
    activity.finish();  
}  
/** 
 *  
 * method desc:设置已经引导过了,下次启动不用再次引导 
 */  
private void setGuided() {  
    SharedPreferences preferences = activity.getSharedPreferences(  
            SHAREDPREFERENCES_NAME, Context.MODE_PRIVATE);  
    Editor editor = preferences.edit();  
    // 存入数据  
    editor.putBoolean("isFirstIn", false);  
    // 提交修改  
    editor.commit();  
}  

// 判断是否由对象生成界面  
@Override  
public boolean isViewFromObject(View arg0, Object arg1) {  
    return (arg0 == arg1);  
}  

@Override  
public void restoreState(Parcelable arg0, ClassLoader arg1) {  
}  

@Override  
public Parcelable saveState() {  
    return null;  
}  

@Override  
public void startUpdate(View arg0) {  
}  

}
至于MainActivity随便了。
效果就是如下图片

Paste_Image.png

Paste_Image.png

Paste_Image.png

Paste_Image.png

所以总结一下,我们可以使用ViewPager做什么:
1.程序使用导航,外加底部圆点的效果,这个在微信示例里介绍了
2.页卡滑动,加上菜单的效果,不管是之前的支持手势也支持底部图标点击的微信,还是今天的微博。


相互学习,共同努力!
微信号:romance-l

博客地址:http://my.csdn.net/?ref=toolbar

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容