ViewPager的两种特殊扩展及其他

竖向滑动

### 1.监听ViewPager的touch事件,交换touch的x和y坐标

private MotionEvent swapTouchEvent(MotionEvent event) {
    float width = getWidth();
    float height = getHeight();

    float swappedX = (event.getY() / height) * width;
    float swappedY = (event.getX() / width) * height;

    event.setLocation(swappedX, swappedY);

    return event;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    boolean intercept = super.onInterceptTouchEvent(swapTouchEvent(ev));
    swapTouchEvent(ev);
    return intercept;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapTouchEvent(ev));

}

###2.给ViewPager设置PageTransformer

public class VerticalTransformer implements ViewPager.PageTransformer {
    private float yPosition;

    @Override
    public void transformPage(View view, float position) {
        view.setTranslationX(view.getWidth() * -position);
        yPosition = position * view.getHeight();
        view.setTranslationY(yPosition);
    }
}

###3.Done and enjoy

============================

一屏内显示多页

一屏内显示多页的实现方式有两种,通过给ViewPager设置setPageMargin实现和通过覆写PagerAdapter的getPageWidth实现。

1.setPageMargin

#### 实现方法 通过viewpager.setPageMargin(int marginPixels),给ViewPager的每页设置一个负数的margin,然后在每一页的View留足够的空白给这个负值,来达到一屏显示多页的目的。
#### 原理 如图,此时的ViewPager是满屏的大小,通过给ViewPager设置负的PageMargin,使得下一页的内容和上一页有了一个重叠区域,而PageContainer是一个透明的View,作用是留出足够的空白给PageMargin这个值做重叠,为什么说足够的空白,因为还需要考虑到设置PageMargin之后的两页之间的间隔。

ViewPager
+--------------------------------------------------------+
| +---------------------------------------------------+  |
| |PageContainer          |重|   PageContainer        |  |
| |                       |  |                        |  |
| |   +-----------------+ |叠| +-----------------+    |  |
| |   |Actual View      | |  | |                 |    |  |
| |   |                 | |  | |                 |    |  |
| |   |                 | |区| |                 |    |  |
| |   |                 | |  | |                 |    |  |
| |   +-----------------+ |  | +-----------------+    |  |
| |                       |域|                        |  |
| |                       |  |                        |  |
| +---------------------------------------------------+  |
+--------------------------------------------------------+

带来的问题

使用这个方法会带来一个的体验上的问题(ViewPager本身的滑动是有一个判断的,拖动某一页过了一个定值,大概是一页PageContainer的一半,松手会滑到下一页)向右翻了几页后,向左翻页这个定值会异常,这个值会接近一个PageContainer的大小,带来的实际体验上的问题是,本来向左稍微滑动可以达到的翻页效果,现在几乎要把这一页完全翻过才能达到,体验上会有一点奇怪。

2.getPageWidth

#### 实现方法 通过重写PagerAdapter的getPageWidth方法,此方法返回的是ViewPager中每一页占实际ViewPager的宽度百分比,默认是1,即100%:

/**
 * Returns the proportional width of a given page as a percentage of the
 * ViewPager's measured width from (0.f-1.f]
 *
 * @param position The position of the page requested
 * @return Proportional width for the given page position
 */
public float getPageWidth(int position) {
    return 1.f;
}

带来的问题

相较上一种setPageMargin的方法来说,也许不算个问题,只是和原始ViewPager体验上的不一样。通过getPageWidth实现的ViewPager,滑动时会始终保持focus的页居左,如图:

ViewPager
+----------------------------------------------------+
|                                                    |
+----------------------------+ +---------------------+
||Page                       | |Page                 |
||                           | |                     |
||                           | |                     |
||                           | |                     |
||                           | |                     |
||                           | |                     |
||                           | |                     |
+----------------------------+ +---------------------+
|                                                    |
+----------------------------------------------------+

而滑动到最后一页时,会有如下图效果,即focus是最后一页时,最后一页不会保持居左,而是会在保证最后一页完全显示的情况下向左滑动一定值,效果及体验见天猫客户端首页。

 ViewPager
+------------------------------------------------------+
|                                                      |
+---------------------+ +----------------------------+ |
|Page                 | |Page                        | |
|                     | |                            | |
|                     | |                            | |
|                     | |                            | |
|                     | |                            | |
|                     | |                            | |
|                     | |                            | |
|                     | |                            | |
+---------------------+ +----------------------------+ |
|                                                      |
+------------------------------------------------------+

========================

ViewPager作为轮播Banner时需要注意的点

这里提到的场景比较特殊,一是轮播Banner,轮播Banner的特点是有一个timer计时器用于计算何时翻到下一页,二是用在了有复用和回收的地方,如ListView和RecyclerView。
常见的优化是,在ViewPager滑出屏幕时需要停止timer,再次滑入屏幕时需要启动timer;需要覆写ViewPager里的一些方法实现,但是不一定能都覆盖到,集思广益,先说我暂时收集到的:

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    startTimer();
}

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    stopTimer();
}

@Override
protected void onVisibilityChanged(View changedView, int visibility) {
    super.onVisibilityChanged(changedView, visibility);
    if (visibility == VISIBLE) {
        startTimer();
    } else {
        stopTimer();
    }
}

@Override
public void onStartTemporaryDetach() {
    super.onStartTemporaryDetach();
    stopTimer();
}

@Override
public void onFinishTemporaryDetach() {
    super.onFinishTemporaryDetach();
    startTimer();
}

这里比较常见的是前三个方法,即在被附加和从Window上移除时,可见性发生改变时;
关于后两个方法,先贴源码(取自View.java):

```java /** * This is called when a container is going to temporarily detach a child, with * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. * It will either be followed by {@link #onFinishTemporaryDetach()} or * {@link #onDetachedFromWindow()} when the container is done. */ public void onStartTemporaryDetach() { removeUnsetPressCallback(); mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; }

/** * Called after {@link #onStartTemporaryDetach} when the container is done * changing the view. */ public void onFinishTemporaryDetach() { } ``` 
onStartTemporaryDetach和onFinishTemporaryDetach是成对出现的方法,在Parent需要对此View作出调整的时候会触发onStartTemporaryDetach,同时结束后调用onFinishTemporaryDetach。

时间: 2024-08-29 10:54:46

ViewPager的两种特殊扩展及其他的相关文章

扩展Linux swap分区 两种方法

先来查询一下系统的swap [root@localhost ~]# free -m total used free shared buffers cached Mem: 375 369 6 0 7 83 -/+ buffers/cache: 278 97 Swap: 1027 128 899 [root@localhost ~]# 现在系统中swap是1024M 扩展是swap分区有两种方法, (1) 利用磁盘的剩余空间来扩展swap 首先分区并改变分区的类型 [root@localhost ~

用批处理一键安装两种扩展名的Windows系统补丁_DOS/BAT

每个人都可能重装过操作系统.可每次安装好操作系统后花费时间最长的就是下载补丁安装补丁了,往往下载补丁安装补丁都花去了大半天的事情,在Vista以后,微软发布的补丁大都是msu的,当然也有少部份还是以前的exe.下面介绍一种针对这两种扩展名的系统补丁快速安装的办法. 借助软件下载最新的系统补丁并保存在spacks文件夹,在该文件夹内新建一文本文件,输入以下代码 @Echo Off Title Install Windows Update pack Echo 正在安装Windows系统补丁,请稍等.

ThinkPHP中Widget扩展的两种写法及调用方法详解

本文实例讲述了ThinkPHP中Widget扩展的两种写法及调用方法.分享给大家供大家参考,具体如下: Widget扩展一般用于页面组件的扩展,在页面根据需要输出不同的内容,下面介绍一下ThinkPHP中Widget的两种写法及调用 写法一: ArticlWidget.class.php文件: class ArticleWidget extends Widget { /** * * @param array $data * @return type * 调用方法:{:W('ArticleList

JavaBean实现多文件上传的两种方法

上传 摘要:本文介绍了JavaBean实现多个文件上传的两种方法,分别是使用http协议和ftp协议实现.首先讲述了http协议传送多个文件的基本格式和实现上传的详细过程,之后简单介绍了使用ftpclient 类实现了ftp方式的上传,最后对这两种方法进行了比较. 关键字:JavaBean .http .ftp .ftpclient JavaBean是一种基于Java的软件组件.JSP对于在Web 应用中集成JavaBean组件提供了完善的支持.这种支持不仅能缩短开发时间(可以直接利用经测试和可

Ajax中解析Json的两种方法对比分析

  这里给大家介绍的是Ajax中解析Json的两种方法对比分析,十分的实用,本文为学习笔记,属新手文章,欢迎指教! eval(); //此方法不推荐 JSON.parse(); //推荐方法 一.两种方法的区别 我们先初始化一个json格式的对象: ? 1 2 3 4 5 var jsonDate = '{ "name":"周星驰","age":23 }'   var jsonObj = eval( '(' + jsonDate + ')' );

微软SQL Server数据库的两种请求游标

[IT168 技术]游标(cursor)是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果.每个游标区都有一个名字.用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理. 关系数据库中的操作会对整个行集起作用.由 SELECT 语句返回的行集包括满足该语句的 WHERE 子句中条件的所有行.这种由语句返回的完整行集称为结果集.应用程序,特别是交互式联机应用程序,并不总能将整个结果集作为一个单元来有效地处理.这些应用程序需要一种机制以便每次处理一行或一部分行.游标就

AJAX 开发的两种不同的方法

ajax     最近几年Ajax应用程序开发出现了两种截然不同的方法,每一种方法都对以前的结构模型进行扩展.由于两种方法性质看起来是不同的,所以在实际应用程序的开发中应选择其中一种.     当我们第一次听到Ajax这个术语的时候,我们的第一反应可能就是其较高的Web页面交互性.至少在JavaScript中的Web应用程序部分必要的代码提供交互性,虽然在Ajax应用程序意义方面都有一致的意见,但对于开发者如何与JavaScript进行交互或者如何在客户端与服务器之间分配显示逻辑有一些分歧.  

Struts VS Spring 两种MVC框架比较

比较 基于Web的MVC framework在J2EE的世界内已是空前繁荣.TTS网站上几乎每隔一两个星期就会有新的MVC框架发布.目前比较好的MVC,老牌的有Struts.Webwork.新兴的MVC 框架有Spring MVC.Tapestry.JSF等.这些大多是著名团队的作品,另外还有一些边缘团队的作品,也相当出色,如Dinamica.VRaptor等.这些框架都提供了较好的层次分隔能力.在实现良好的MVC 分隔的基础上,通过提供一些现成的辅助类库,同时也促进了生产效率的提高. 如何选择

对于Struts和Spring两种MVC框架的比较

比较 基于Web的MVC framework在J2EE的世界内已是空前繁荣.TTS网站上几乎每隔一两个星期就会有新的MVC框架发布.目前比较好的MVC,老牌的有Struts.Webwork.新兴的MVC框架有Spring MVC.Tapestry.JSF等.这些大多是著名团队的作品,另外还有一些边缘团队的作品,也相当出色,如Dinamica.VRaptor等.这些框架都提供了较好的层次分隔能力.在实现良好的MVC 分隔的基础上,通过提供一些现成的辅助类库,同时也促进了生产效率的提高. 如何选择一