ViewPager类主要被用来实现可滑动的视图功能,这里我们就来共同学习Android中ViewPager实现滑动条及与Fragment结合的实例教程,需要的朋友可以参考下

自主实现滑动指示条
先上一个基本效果图:

1.XML布局
布局代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context="com.example.testviewpage_2.MainActivity" >
   
  <ImageView
  android:id="@+id/cursor"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:scaleType="matrix"
  android:src="@drawable/a" />
  
 <android.support.v4.view.ViewPager
  android:id="@+id/viewpager"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center"/>
  
</LinearLayout>

采用线性垂直布局,在滑动页面的上方添加一个小水平条。

2.JAVA代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
public class MainActivity extends Activity {
  
 private View view1, view2, view3;
 private List<View> viewList;// view数组
 private ViewPager viewPager; // 对应的viewPager
  
 private ImageView cursor;
 private int bmpw = 0; // 游标宽度
 private int offset = 0;// // 动画图片偏移量
 private int currIndex = 0;// 当前页卡编号
  
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  viewPager = (ViewPager) findViewById(R.id.viewpager);
  LayoutInflater inflater = getLayoutInflater();
  view1 = inflater.inflate(R.layout.layout1, null);
  view2 = inflater.inflate(R.layout.layout2, null);
  view3 = inflater.inflate(R.layout.layout3, null);
  
  viewList = new ArrayList<View>();// 将要分页显示的View装入数组中
  viewList.add(view1);
  viewList.add(view2);
  viewList.add(view3);
  
  //初始化指示器位置
  initCursorPos();
    
  viewPager.setAdapter(new MyPagerAdapter(viewList));
  viewPager.setOnPageChangeListener(new MyPageChangeListener());
  
 }
   
 //初始化指示器位置
 public void initCursorPos() {
  // 初始化动画
  cursor = (ImageView) findViewById(R.id.cursor);
  bmpw = BitmapFactory.decodeResource(getResources(), R.drawable.a)
    .getWidth();// 获取图片宽度
  
  DisplayMetrics dm = new DisplayMetrics();
  getWindowManager().getDefaultDisplay().getMetrics(dm);
  int screenW = dm.widthPixels;// 获取分辨率宽度
  offset = (screenW / viewList.size() - bmpw) / 2;// 计算偏移量
  
  Matrix matrix = new Matrix();
  matrix.postTranslate(offset, 0);
  cursor.setImageMatrix(matrix);// 设置动画初始位置
 }
   
  
 //页面改变监听器
 public class MyPageChangeListener implements OnPageChangeListener {
  
  int one = offset * 2 + bmpw;// 页卡1 -> 页卡2 偏移量
  int two = one * 2;// 页卡1 -> 页卡3 偏移量
  
  @Override
  public void onPageSelected(int arg0) {
   Animation animation = null;
   switch (arg0) {
   case 0:
    if (currIndex == 1) {
     animation = new TranslateAnimation(one, 0, 0, 0);
    } else if (currIndex == 2) {
     animation = new TranslateAnimation(two, 0, 0, 0);
    }
    break;
   case 1:
    if (currIndex == 0) {
     animation = new TranslateAnimation(offset, one, 0, 0);
    } else if (currIndex == 2) {
     animation = new TranslateAnimation(two, one, 0, 0);
    }
    break;
   case 2:
    if (currIndex == 0) {
     animation = new TranslateAnimation(offset, two, 0, 0);
    } else if (currIndex == 1) {
     animation = new TranslateAnimation(one, two, 0, 0);
    }
    break;
   }
   currIndex = arg0;
   animation.setFillAfter(true);// True:图片停在动画结束位置
   animation.setDuration(300);
   cursor.startAnimation(animation);
  }
  
  @Override
  public void onPageScrolled(int arg0, float arg1, int arg2) {
  }
  
  @Override
  public void onPageScrollStateChanged(int arg0) {
  }
 }
 
 /**
  * ViewPager适配器
  */
 public class MyPagerAdapter extends PagerAdapter {
  public List<View> mListViews;
  
  public MyPagerAdapter(List<View> mListViews) {
   this.mListViews = mListViews;
  }
  
  @Override
  public boolean isViewFromObject(View arg0, Object arg1) {
   // TODO Auto-generated method stub
   return arg0 == arg1;
  }
  
  @Override
  public int getCount() {
   // TODO Auto-generated method stub
   return mListViews.size();
  }
  
  @Override
  public void destroyItem(ViewGroup container, int position, Object object) {
   // TODO Auto-generated method stub
   container.removeView(mListViews.get(position));
  }
  
  @Override
  public Object instantiateItem(ViewGroup container, int position) {
   // TODO Auto-generated method stub
   container.addView(mListViews.get(position));
  
   return mListViews.get(position);
  }
 }
  
}

3.重点解析
从易到难一步步来讲。
(1)initCursorPos()---初始化指示器位置
游标在初始化显示时,我们要根据屏幕宽度来显示游标位置。先看看这部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//初始化指示器位置
public void initCursorPos() {
 // 初始化动画
 cursor = (ImageView) findViewById(R.id.cursor);
 bmpw = BitmapFactory.decodeResource(getResources(), R.drawable.a)
   .getWidth();// 获取图片宽度
  
 DisplayMetrics dm = new DisplayMetrics();
 getWindowManager().getDefaultDisplay().getMetrics(dm);
 int screenW = dm.widthPixels;// 获取分辨率宽度
 offset = (screenW / viewList.size() - bmpw) / 2;// 计算偏移量
  
 Matrix matrix = new Matrix();
 matrix.postTranslate(offset, 0);
 cursor.setImageMatrix(matrix);// 设置动画初始位置
}

可能有些同学不明白的位置在于,初始化位置的偏移量为什么这么算,下面,我画了张图,看下就应该明白了。

最后对于偏移的方法,可用的很多,这里仿网上的代码用了matrix;当然大家可以用其它的偏移方法,一样。
(2)MyPageChangeListener()---页面改变监听器
代码如下 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class MyPageChangeListener implements OnPageChangeListener {
  
 int one = offset * 2 + bmpw;// 页卡1 -> 页卡2 偏移量
 int two = one * 2;// 页卡1 -> 页卡3 偏移量
  
 @Override
 public void onPageSelected(int arg0) {
  Animation animation = null;
  switch (arg0) {
  case 0:
   if (currIndex == 1) {
    animation = new TranslateAnimation(one, 0, 0, 0);
   } else if (currIndex == 2) {
    animation = new TranslateAnimation(two, 0, 0, 0);
   }
   break;
  case 1:
   if (currIndex == 0) {
    animation = new TranslateAnimation(offset, one, 0, 0);
   } else if (currIndex == 2) {
    animation = new TranslateAnimation(two, one, 0, 0);
   }
   break;
  case 2:
   if (currIndex == 0) {
    animation = new TranslateAnimation(offset, two, 0, 0);
   } else if (currIndex == 1) {
    animation = new TranslateAnimation(one, two, 0, 0);
   }
   break;
  }
  currIndex = arg0;
  animation.setFillAfter(true);// True:图片停在动画结束位置
  animation.setDuration(300);
  cursor.startAnimation(animation);
 }

原理是这样,根据滑动到的页面,把游标滑动找指定位置。
这里可能有难度的地方在于,数学……
我画了一张图,解释从第一个页面到第二个页面时的距离为什么是“游标宽度+offset*2”,其它距离类似。

使用Fragment实现ViewPager滑动
效果图:

在第一个页面加一个Btn

第一页面向第二页面滑动

第二页面向第三个页面滑动
一些说明:
FragmentPagerAdapter派生自PagerAdapter,它是用来呈现Fragment页面的,这些Fragment页面会一直保存在fragment manager中,以便用户可以随时取用。
这个适配器最好用于有限个静态fragment页面的管理。尽管不可见的视图有时会被销毁,但用户所有访问过的fragment都会被保存在内存中。因此fragment实例会保存大量的各种状态,这就造成了很大的内存开销。所以如果要处理大量的页面切换,建议使用FragmentStatePagerAdapter.
每一个使用FragmentPagerAdapter的ViewPager都要有一个有效的ID集合,有效ID的集合就是Fragment的集合(感谢夫诸同学的提示)
对于FragmentPagerAdapter的派生类,只需要重写getItem(int)和getCount()就可以了。
具体实现:
1、适配器实现——FragmentPagerAdapter
先看完整代码,再细讲:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class FragAdapter extends FragmentPagerAdapter {
  
 private List<Fragment> mFragments;
   
 public FragAdapter(FragmentManager fm,List<Fragment> fragments) {
  super(fm);
  // TODO Auto-generated constructor stub
  mFragments=fragments;
 }
  
 @Override
 public Fragment getItem(int arg0) {
  // TODO Auto-generated method stub
  return mFragments.get(arg0);
 }
  
 @Override
 public int getCount() {
  // TODO Auto-generated method stub
  return mFragments.size();
 }
  
}

这里有三个函数,根据第一部分的官方文档,可知,对于FragmentPagerAdapter的派生类,只重写getItem(int)和getCount()就可以了。
对于构造函数,这里申请了一个Fragment的List对象,用于保存用于滑动的Fragment对象,并在创造函数中初始化:

1
2
3
4
5
public FragAdapter(FragmentManager fm,List<Fragment> fragments) {
 super(fm);
 // TODO Auto-generated constructor stub
 mFragments=fragments;
}

然后在getItem(int arg0)中,根据传来的参数arg0,来返回当前要显示的fragment。

最后,getCount()返回用于滑动的fragment总数;

从构造函数所以看出,我们要构造Fragment的集合才行,所以下面我们就先产生我们所需要的Fragment类;
2、三个Fragment类
第一个Fragment类:

XML:(layout1.xml)

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#ffffff"
 android:orientation="vertical" >
   
 <Button android:id="@+id/fragment1_btn"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="show toast"
  />
</LinearLayout>

在其中加入了一个Btn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Fragment1 extends Fragment {
   
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  View view= inflater.inflate(R.layout.layout1, container, false);
    
  //对View中控件的操作方法
  Button btn = (Button)view.findViewById(R.id.fragment1_btn);
  btn.setOnClickListener(new View.OnClickListener() {
     
   @Override
   public void onClick(View v) {
    // TODO Auto-generated method stub
    Toast.makeText(getActivity(), "点击了第一个fragment的BTN", Toast.LENGTH_SHORT).show();
   }
  });
  return view;
 }
}

在onCreateView()中返回要显示的View,上面这段代码简单演示了如何对视图里的控件进行操作,难度不大,不再细讲,如果对Fragment不太熟悉的同学,先看看这篇文章:《Android Fragment完全解析,关于碎片你所需知道的一切》

第二个Fragment类:

XML代码:(layout2.xml)原生代码,没有做任何更改

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#ffff00"
 android:orientation="vertical" >
   
  
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
public class Fragment2 extends Fragment {
   
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  View view=inflater.inflate(R.layout.layout2, container, false);
  return view;
 }
  
}

第三个Fragment类:
XML代码:(layout3.xml)同样,原生代码,没做任何更改

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#ff00ff"
 android:orientation="vertical" >
   
  
</LinearLayout>

java代码:

1
2
3
4
5
6
7
8
9
10
11
public class Fragment3 extends Fragment {
   
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  View view=inflater.inflate(R.layout.layout3, container, false);
  return view;
 }
  
}

3、主activity实现
核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MainActivity extends FragmentActivity {
  
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  //构造适配器
  List<Fragment> fragments=new ArrayList<Fragment>();
  fragments.add(new Fragment1());
  fragments.add(new Fragment2());
  fragments.add(new Fragment3());
  FragAdapter adapter = new FragAdapter(getSupportFragmentManager(), fragments);
    
  //设定适配器
  ViewPager vp = (ViewPager)findViewById(R.id.viewpager);
  vp.setAdapter(adapter);
 }
  
}

首先有一个最值得注意的地方:Activity派生自FragmentActivity,其实这是有关Fragment的基础知识,只有FragmentActivity才能内嵌fragment页面,普通Activity是不行的。

这段代码主要分为两步,第一步:构造适配器;第二步:设定适配器。
先看构造适配器的过程:

1
2
3
4
5
6
//构造适配器
List<Fragment> fragments=new ArrayList<Fragment>();
fragments.add(new Fragment1());
fragments.add(new Fragment2());
fragments.add(new Fragment3());
FragAdapter adapter = new FragAdapter(getSupportFragmentManager(), fragments);

构造一个fragment列表,然后将上面的三个Fragment类对应的实例添加进去,最后生成FragAdapter实例。
至于第二步,设定适配器,没什么好讲的。

Android中ViewPager实现滑动条及与Fragment结合的实例教程的更多相关文章

  1. Android中viewPager的一两点使用

    Android中viewPager的一两点使用 viewPager是谷歌官方提供的一种方便实现页面滑动效果的控件,可以直接使用也可以和fragment联合使用.这里只简单说下直接使用. 使用viewP ...

  2. Android中ViewPager+Fragment取消(禁止)预加载延迟加载(懒加载)问题解决方案

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53205878本文出自[DylanAndroid的博客] Android中Vie ...

  3. android中无限循环滑动的gallery实例

    android中无限循环滑动的gallery实例 1.点击图片有变暗的效果,使用imageview.setAlpha(),并且添加ontouchListener public void init() ...

  4. android中SeekBar拖动进度条的使用及事件监听

    下面和大家分享一下android中SeekBar拖动进度条的使用,以及事件监听.拖动进度条的事件监听需要实现SeekBar.OnSeekBarChangeListener接口,调用SeekBar的se ...

  5. Android 禁止ViewPager左右滑动的功能实现

    来来来,各位看官~ Look here!!! Android    禁止ViewPager左右滑动的功能实现!! I think it`s so easy,无需重写ViewPager!!! JUST ...

  6. Android模仿三星手机系统滑动条滑动时滑块变大的特效

    使用三星手机的过程中发现三星手机系统自带的滑动条有一个特效.比方调节亮度的滑动条.在滑动滑块的过程中,滑块会变大.功能非常小可是体验却非常好,于是决定做一个这种效果出来.好了废话不多说了,以下開始实现 ...

  7. 【Android】5.8 滑动条(SeekBar)

    分类:C#.Android.VS2015: 创建日期:2016-02-07 一.简介 滑动条也叫拖动条(用户可拖动改变滑动条的值),比如可让用户调节音量大小.调节屏幕亮度.调节歌曲或视频当前播放的位置 ...

  8. 详解实现Android中实现View滑动的几种方式

    注: 本文提到的所有三种滑动方式的完整demo:ScrollDemo 1. 关于View我们需要知道的 (1)什么是View? Android中的View类是所有UI控件的基类(Base class) ...

  9. android之ViewPager修改滑动速度

    在android中,使用过viewpager的人都清楚,我们如果使用viewpager进行滑动时,如果通过手指滑动来进行的话,可以根据手指滑动的距离来实现,但是如果通过setCurrentItem函数 ...

随机推荐

  1. myeclipse集成jdk、tomcat8、maven、svn

    今天一个同学要回家了.回家之前叫我帮他配置一下开发环境.然后在家里面自己研究一下.敲下代码. 帮他配置好之后自己回来把这个过程写下来.别让自己把这个东西给忘了. myeclipse安装 myeclip ...

  2. 轻量级分布式文件系统FastDFS使用安装说明手册(新手入门级)

    轻量级分布式文件系统FastDFS使用安装说明手册(新手入门级) 实验室所在的课题组以研究云计算为主,但所有的研究都是在基于理论的凭空想像,缺少分布式环境的平台的实践,云计算神马的都是浮云了.因此,我 ...

  3. JavaScript编程(终极篇)

    JavaScript 实现是由以下 3 个不同部分组成的:    核心(ECMAScript)    文档对象模型(DOM)    浏览器对象模型(BOM) 1.数据类型 typeof 运算符 对变量 ...

  4. ZH奶酪:哈工大LTP云平台标记含义及性能

    从官网搬过来的 囧rz 哈工大讯飞语言云 由哈工大 和科大讯飞 联合研发的中文自然语言处理云服务平台.结合了哈工大“语言技术平台——LTP” 高效.精准的自然语言处理核心技术和讯飞公司在全国性大规模云 ...

  5. linux2.6.30.4内核移植(7)——插入hello world驱动模块

    详细步骤参考自:http://www.cnblogs.com/wanyao/archive/2011/11/21/2257628.html 过程比较顺利,结果截图如下: 这里需要注意的是:http:/ ...

  6. js模板 arttemplate 让数据与html分离

    js模板引擎 前后交互过程中最麻烦的就是如何将json数据展示到页面中,循环拼接html的方法实在是太low了,饱受其苦,BAT同样会遇到这样的问题,于是乎就有个各自的js模板引擎,目的只有一个:让数 ...

  7. XAMPP phpmyadmin MYSQL的配置

    1\xampp phpmyadmin的配置 1.打开“路径/phpmyadmin/libraries/config.default.php”,查找相关项并修改为以下内容: $cfg['PmaAbsol ...

  8. Git之第三方托管oschina

    一.git 简介 1.Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. 2.Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. ...

  9. Android学习笔记一:项目目录结构

    一:Android目录 主要内容有: app目录下: manifests目录: AndroidManifest.xml:APP的配置 java目录:主要为源代码和测试代码 res目录:主要是资源文件, ...

  10. java 浮点运算

      CreateTime--2017年12月1日11:35:00 Author:Marydon java 浮点类型(float.double)间的运算工具类 /** * 进行BigDecimal对象的 ...