前言:前面我们用了三篇的时间讲述了有关ViewPager的基础知识,到这篇就要进入点实际的了。在第三篇《ViewPager 详解(三)---PagerTabStrip与PagerTitleStrip添加标题栏的异同》中,我们说了,PagerTabStrip和PagerTitleStrip都不适合用在实际用途中,当要在实际运用中,我们就要自己去实现相关的功能。这篇文章中单纯讲述划动指示条的实现方法,而对于交互Tab的实现,就不再讲解,最后给出网上的一段源码,大家可以去研究一下,有关交互Tab的实现原理是一样的,难度不大。

相关文章:

1、《ViewPager 详解(一)---基本入门》

2、《ViewPager 详解(二)---详解四大函数》

3、《ViewPager 详解(三)---PagerTabStrip与PagerTitleStrip添加标题栏的异同》

4、《ViewPager 详解(四)----自主实现滑动指示条》

5、《ViewPager 详解(五)-----使用Fragment实现ViewPager滑动》

先上本篇效果图:

  

一、XML布局

布局代码如下:

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

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

二、JAVA代码

本例代码是根据《ViewPager 详解(一)---基本入门》 更改而来。

先给出全部代码,然后再逐步讲解。

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

从易到难一步步来讲。

1、MyPagerAdapter类

在前几篇中,我们对于适配器的实现总是new一个PageAdapter的实例。我们这里做了一点稍微的更改,将其集合成一个类,内容都没变,只是多了一个构造函数而已。所以针对这个类的具体代码,我就不再细讲,如果对其中的复写的函数为什么要这么写不理解的同学,请看《ViewPager 详解(二)---详解四大函数》

2、initCursorPos()---初始化指示器位置

游标在初始化显示时,我们要根据屏幕宽度来显示游标位置。先看看这部分代码:

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

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

最后对于偏移的方法,可用的很多,这里仿网上的代码用了matrix;当然大家可以用其它的偏移方法,一样。

3、MyPageChangeListener()---页面改变监听器

代码如下 :

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

原理是这样,根据滑动到的页面,把游标滑动找指定位置。
这里可能有难度的地方在于,数学……

我画了一张图,解释从第一个页面到第二个页面时的距离为什么是“游标宽度+offset*2”,其它距离类似。

这篇就到这了,时间比较紧,而且这个难度不太大,讲的可能不太细。

源码中,给大家列出了一个有Tab交互的Demo,图片如下:

  

相关文章:

《Android ViewPager使用详解》

《Android ViewPager多页面滑动切换以及动画效果》

《Android多屏滑动:ViewPager基础使用及PagerTabStrip先天缺陷(附源码)》

源码包含:

1、TestViewPage_scroll_cursor:文中示例源码

2、DWinterTabDemo:带Tab交互的Demo

源码下载地址:http://download.csdn.net/detail/harvic880925/7758941

 

请大家尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/38557517  谢谢

ViewPager 详解(四)----自主实现滑动指示条的更多相关文章

  1. ViewPager 详解(五)-----使用Fragment实现ViewPager滑动

    前言:前几篇文章讲解了ViewPager的普通实现方法,但Android官方最推荐的一种实现方法却是使用fragment,下面我们使用fragment来重新实现一下第一篇<ViewPager 详 ...

  2. ViewPager 详解(二)---详解四大函数

    前言:上篇中我们讲解了如何快速实现了一个滑动页面,但问题在于,PageAdapter必须要重写的四个函数,它们都各有什么意义,在上节的函数内部为什么要这么实现,下面我们就结合Android的API说明 ...

  3. ViewPager 详解(三)---PagerTabStrip与PagerTitleStrip添加标题栏的异同

    前言:在前两篇文章中,我们讲解了滑动页面的的实现方法与四大函数的意义,但有时,仅仅实现页面滑动是不够的,还要有标题栏才会显得更友好.所以在这篇文章中,我将会向大家展示在Android.support. ...

  4. ViewPager 详解(一)---基本入门

    前言:这两天研究研究ViewPager滚动功能,现在很多的app都有用到这个功能,我们的大虾米也有这个模块.要研究就彻底的研究研究,我从不满足于一个功能只是简单的应用,要学就学的彻底,所以我打算将Vi ...

  5. [转]ViewPager 详解(三)---PagerTabStrip与PagerTitleStrip添加标题栏的异同

      目录(?)[-] 一PagerTitleStrip Class Overview XML布局文件 重写适配器的getPageTitle函数 变量 初始化 重写CharSequence getPag ...

  6. Android ViewPager再探:增加滑动指示条

    上一篇:<Android ViewPager初探:让页面滑动起来> ViewPager只是左右滑动有些丑,也不知道当前位于第几页面. 可以在上方加入滑动指示条,来确定当前位置. 只需要修改 ...

  7. .NET DLL 保护措施详解(四)各操作系统运行情况

    我准备了WEB应用程序及WinForm应用程序,分别在WIN SERVER 2012/2008/2003.Win7/10上实测,以下为实测结果截图: 2012 2008 2003 WIN7 WIN10 ...

  8. logback -- 配置详解 -- 四 -- <filter>

    附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...

  9. pika详解(四) channel 通道

    pika详解(四) channel 通道   本文链接:https://blog.csdn.net/comprel/article/details/94662394 版权 ​ channel通道 通道 ...

随机推荐

  1. mac在 aliyun linux ecs实例上安装 jdk tomcat mysql

    用了一个ftp 工具 把 gz rpm 等 传递到ecs 上 -- 用这个Transmit 用ssh远程登录,然后依次安装 jdk tomcat  mysql 到 /usr/local/... 设置环 ...

  2. Java面向对象的概念以及OOP思想的优点

    传统面向过程程序设计的思路: 先设计一组函数用来解决一个问题,然后确定函数中需要处理的数据以及存储位置. 面向对象的设计的思路: 先确定处理的数据,然后确定处理数据的算法,最后将数据和算法封装在一起构 ...

  3. iOS9 集成指纹解锁

    添加依赖库 LocalAuthentication.framework #import <LocalAuthentication/LocalAuthentication.h> // 头文件 ...

  4. qt二维码示例

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://blog.csdn.net/hiwubihe/article/details/38679621,qq:1269122125. 移动终 ...

  5. TCP/IP-入门

    Life is not a rehearsal "人生没有彩排" 参考资料:TCP/IP入门经典 (第五版) TCP/IP详解 卷一:协议 一.什么是TCP/IP TCP/IP是一 ...

  6. Websocket 与代理服务器如何交互? How HTML5 Web Sockets Interact With Proxy Servers

    How HTML5 Web Sockets Interact With Proxy Servers Posted by Peter Lubberson Mar 16, 2010 With the re ...

  7. 修改本地数据库root权限密码

    方法1: 用SET PASSWORD命令 测试成功 首先登录MySQL @1——mysql DOS 窗口中. 格式:mysql> set password for 用户名@localhost = ...

  8. C语言笔记(数组地址一些细节)

     一.数组的a+1和&a+1的区别 先看看测试代码: ]={}; printf(" sizeof(data) = %d.\n", sizeof(data)); printf ...

  9. Solr4.8.0源码分析(14)之SolrCloud索引深入(1)

    Solr4.8.0源码分析(14) 之 SolrCloud索引深入(1) 上一章节<Solr In Action 笔记(4) 之 SolrCloud分布式索引基础>简要学习了SolrClo ...

  10. JavaScript Web Application summary

    Widget/ HTML DOM (CORE) (local dom) DOM, BOM, Event(Framework, UI, Widget) function(closure) DATA (c ...