Android:基于速度的 ViewPager 滚动

2024-01-02

ViewPager 现在的滚动方式是每个手势滚动一个项目。无论是全屏快速滑动还是慢速拖动,它对滑动手势的处理方式都是相同的;在最后一页仅前进一步。

是否有任何项目或示例会添加基于速度的滑动,根据现有滑动的速度滚动多个项目(如果仍在进行中),并且如果滑动手势又宽又快,则进一步滚动?

如果没有这样的事情从哪里开始呢?

附:提供了赏金。请不要引用 Gallery 或 Horizo​​ntalScrollView 的答案


这里的技术是扩展ViewPager并模仿寻呼机在内部执行的大部分操作,并结合来自Gallery小部件。总体思路是监视 fling(以及速度和伴随的滚动),然后将它们作为假拖动事件提供给底层ViewPager。如果您单独执行此操作,则不会起作用(您仍然只能滚动一页)。发生这种情况是因为假拖动在滚动有效的范围上实现了上限。您可以模仿扩展中的计算ViewPager并检测何时会发生这种情况,然后只需翻页并照常继续。使用假拖动的好处意味着您不必处理对齐页面或处理页面边缘的问题ViewPager.

我在动画演示示例上测试了以下代码,可从以下位置下载http://developer.android.com/training/animation/screen-slide.html http://developer.android.com/training/animation/screen-slide.html通过替换 ViewPagerScreenSlideActivity有了这个VelocityViewPager(两者都在布局中activity_screen_slide以及活动中的字段)。

/*
 * Copyright 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 * 
 * Author: Dororo @ StackOverflow
 * An extended ViewPager which implements multiple page flinging.
 * 
 */

package com.example.android.animationsdemo;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.GestureDetector;
import android.widget.Scroller;

public class VelocityViewPager extends ViewPager implements GestureDetector.OnGestureListener {

private GestureDetector mGestureDetector;
private FlingRunnable mFlingRunnable = new FlingRunnable();
private boolean mScrolling = false;

public VelocityViewPager(Context context) {
    super(context);
}

public VelocityViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    mGestureDetector = new GestureDetector(context, this);
}

// We have to intercept this touch event else fakeDrag functions won't work as it will
// be in a real drag when we want to initialise the fake drag.
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // give all the events to the gesture detector. I'm returning true here so the viewpager doesn't
    // get any events at all, I'm sure you could adjust this to make that not true.
    mGestureDetector.onTouchEvent(event);
    return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
    mFlingRunnable.startUsingVelocity((int)velX);
    return false;
}

private void trackMotion(float distX) {

    // The following mimics the underlying calculations in ViewPager
    float scrollX = getScrollX() - distX;
    final int width = getWidth();
    final int widthWithMargin = width + this.getPageMargin();
    final float leftBound = Math.max(0, (this.getCurrentItem() - 1) * widthWithMargin);
    final float rightBound = Math.min(this.getCurrentItem() + 1, this.getAdapter().getCount() - 1) * widthWithMargin;

    if (scrollX < leftBound) {
        scrollX = leftBound;
        // Now we know that we've hit the bound, flip the page
        if (this.getCurrentItem() > 0) {
            this.setCurrentItem(this.getCurrentItem() - 1, false);
        }
    } 
    else if (scrollX > rightBound) {
        scrollX = rightBound;
        // Now we know that we've hit the bound, flip the page
        if (this.getCurrentItem() < (this.getAdapter().getCount() - 1) ) {
            this.setCurrentItem(this.getCurrentItem() + 1, false);
        }
    }

    // Do the fake dragging
    if (mScrolling) {
        this.fakeDragBy(distX);
    }
    else {
        this.beginFakeDrag();
        this.fakeDragBy(distX);
        mScrolling = true;
    }

}

private void endFlingMotion() {
    mScrolling = false;
    this.endFakeDrag();
}

// The fling runnable which moves the view pager and tracks decay
private class FlingRunnable implements Runnable {
    private Scroller mScroller; // use this to store the points which will be used to create the scroll
    private int mLastFlingX;

    private FlingRunnable() {
        mScroller = new Scroller(getContext());
    }

    public void startUsingVelocity(int initialVel) {
        if (initialVel == 0) {
            // there is no velocity to fling!
            return;
        }

        removeCallbacks(this); // stop pending flings

        int initialX = initialVel < 0 ? Integer.MAX_VALUE : 0;
        mLastFlingX = initialX;
        // setup the scroller to calulate the new x positions based on the initial velocity. Impose no cap on the min/max x values.
        mScroller.fling(initialX, 0, initialVel, 0, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);

        post(this);
    }

    private void endFling() {
        mScroller.forceFinished(true);
        endFlingMotion();
    }

    @Override
    public void run() {

        final Scroller scroller = mScroller;
        boolean animationNotFinished = scroller.computeScrollOffset();
        final int x = scroller.getCurrX();
        int delta = x - mLastFlingX;

        trackMotion(delta); 

        if (animationNotFinished) {
            mLastFlingX = x;
            post(this);
        }
        else {
            endFling();
        }

    }
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distX, float distY) {
    trackMotion(-distX);
    return false;
}

    // Unused Gesture Detector functions below

@Override
public boolean onDown(MotionEvent event) {
    return false;
}

@Override
public void onLongPress(MotionEvent event) {
    // we don't want to do anything on a long press, though you should probably feed this to the page being long-pressed.
}

@Override
public void onShowPress(MotionEvent event) {
    // we don't want to show any visual feedback
}

@Override
public boolean onSingleTapUp(MotionEvent event) {
    // we don't want to snap to the next page on a tap so ignore this
    return false;
}

}

这有一些小问题,可以很容易解决,但我会留给你,即如果你滚动(拖动,而不是猛击),你可能会在页面之间结束(你会想要捕捉到) ACTION_UP 事件)。此外,为了执行此操作,触摸事件将被完全覆盖,因此您需要将相关事件提供给底层ViewPager在适当情况下。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:基于速度的 ViewPager 滚动 的相关文章

  • 不同 Android 设备上 box2D 中出现奇怪的“口吃”

    我正在用 C 同时开发引擎和游戏 并使用 box2D 作为物理后端 我正在不同的 Android 设备上进行测试 在三分之二的设备上 游戏运行良好 物理效果也很好 然而 在我的 Galaxy Tab 10 1 上 我偶尔会遇到某种 口吃 的
  • 添加动态数据时 footable 出现问题

    我需要 jQuery Mobile 方面的一些帮助富表 http css tricks com footable a jquery plugin for responsive data tables 我正在表中动态添加数据 HTML tab
  • BluetoothAdapter.getDefaultAdapter() 不返回 null

    这是我的第一篇文章 所以如果我做了一些愚蠢的事情 请告诉我 这个问题可能看起来与其他帖子类似 但或多或 少与我所看到的所有内容相反 关于该项目的事情 我正在开发 android 4 0 4 4 应用程序 我正在使用蓝牙 我正在运行 andr
  • Android Facebook sdk 3.5 分享对话框

    您好 我正在为 android sdk 3 5 实现 facebook 共享对话框 但是我按照指南没有取得任何成功 FacebookDialog shareDialog new FacebookDialog ShareDialogBuild
  • 从 BroadcastReceiver 获取方法来更新 UI

    我正在尝试根据变量的变化更新用户界面BroadcastReceiver 因此 我需要调用一个扩展类的方法 以获取我提到的变量 BroadcastReceiver in MainActivity取决于但我无法以任何方式获得真正的返回值 扩展的
  • 游标索引越界异常

    打开后出现光标索引越界错误 数据库 请任何人告诉我如何打开现有数据库 sqllite Android 我想在数据库上触发一个选择查询 检索一些信息 public void getPatient SQLiteDatabase db Strin
  • Android CursorAdapter、ListView 和后台线程

    我一直在开发的这个应用程序有包含数兆字节数据的数据库可供筛选 许多活动只是列表视图 通过数据库中的各个级别的数据下降 直到到达 文档 即从数据库中提取并显示在手机上的 HTML 我遇到的问题是 其中一些活动需要能够通过捕获击键并重新运行带有
  • Android 8.1 中 Activity 自行旋转并恢复正常

    我的应用程序在所有 Android 版本上运行良好 但我注意到在 Android 8 1 0 Oreo 中 当我将屏幕从纵向活动转到横向活动时 以及当我按后退按钮时 它会显示异常行为 屏幕自动从横向旋转并恢复正常 看起来 Activity
  • Android 谷歌地图 V2 已停止

    我正在尝试构建地图应用程序并关注这个链接 https blog emildesign rhcloud com p 435一步步 我在这里找到了类似的主题 但对我没有帮助 我想显示地图 但是当我运行它时 它返回强制关闭和我的 Android
  • 如何使用 Swipe 视图实现 Android TabLayout 设计支持库

    我将使用 android TabLayout 设计支持库 但我不知道如何使用滑动视图 这是我的代码 XML
  • 如何在android中画一条曲线?

    我是 Android 新手 正在开发一个关于绘制线条的示例项目 我想画一条连接两点的曲线或高架线 x1 y1 and x2 y2 我试过canvas drawArc 方法 但是RectF内的值drawArc方法只是圆的 x y 中心点 它在
  • android 多关键词搜索

    我的应用程序包含搜索功能 它将搜索数据库内的内容 我的搜索的弱点是 我只能使用一个标签进行搜索 例如我只能搜索 猫 它会返回我的数据库中包含 猫 一词的内容 因为我正在使用LIKE在 select 语句期间进行查询 如何使用多个标签进行搜索
  • Android - 多次实例化一个片段?

    我正在创建一个在 ListView 中显示数据的应用程序 数据分为两种类型 热门 收藏夹 我有一个活动和两个片段 片段根据类别显示项目列表 我为此使用了 ListView 然后我有两个fragment layouts 它们在设计上完全相同
  • 如何在Android网格视图中设置单元格大小?

    我正在尝试为应用程序制作一个带有大图标的网格视图 但我找不到任何有关修改 Android 上网格布局上的单元格大小的教程 有人可以给我一个例子或相关链接吗 Thanks 就像另一个一样适配器视图 http developer android
  • 如何更改 Android 12 启动屏幕中的图标形状?

    我想要矩形形状的启动屏幕图标 而不是 android 12 中的圆形形状 我不相信你可以 如果你看这里的第 3 点 https developer android com about versions 12 features splash
  • 从 sqlite 和 mysql 加载数据微调器

    我试试这个tutorial http nielpoenya blogspot com 2012 08 tutorial android spinner dari database html加载Spinner from sqlite and
  • 使用 RecyclerView.Adapter 在 onBindViewHolder() 内设置 onItemClickListener

    我有一个自定义对象 学生班 public class Student private String name private String age public String getName return name public void
  • 动态创建 JSON 对象

    我正在尝试使用以下格式创建 JSON 对象 tableID 1 price 53 payment cash quantity 3 products ID 1 quantity 1 ID 3 quantity 2 我知道如何使用 JSONOb
  • 改造方法调用可能会产生“java.lang.NullPointerException”

    使用 Retrofit 2 3 0 我在 Android Studio 中收到以下消息 有关如何删除此 IDE 错误消息的任何建议 谢谢 来自Response文档 http square github io retrofit 2 x ret
  • Android Espresso - 如果未选中,请单击复选框

    I have onView withId R id check box perform click 但我只想在尚未选中该复选框时执行此操作 我怎样才能在浓缩咖啡中做到这一点 我还想根据其之前的状态来切换复选框 开关 起初 我尝试用此方法打开

随机推荐

  • 从 jsr-303 自定义验证器访问数据库

    我将基于 Spring 的验证与 Hibernate 验证器结合使用 该验证器由我的应用程序上下文中的以下内容启用
  • PyInstaller - ImportError:没有名为 _bootlocale 的模块

    每次我尝试在 PyInstaller 中编译 python 文件时 它都会返回很多错误 这些是编译错误 Traceback most recent call last File c users Person appdata local pr
  • 为什么python中会出现这个AttributeError?

    有件事我不明白 为什么会这样 import scipy happens with several other modules too I took scipy as an example now matrix scipy sparse co
  • Google 我的商家 API 的测试/沙盒环境

    我刚刚开始使用 Google My Business API 并且能够执行获取操作只是为了验证我的 Oauth 设置是否正确 现在 我想使用 GMB 添加位置 API 的 post 方法添加位置 但在将代码推送到生产环境之前 我想测试此请求
  • 从给定的链表在 C++ 中创建反向链表

    我在从给定的链接列表以相反的顺序创建链接列表时遇到一些问题 我有java背景 刚刚开始做一些C 你能检查一下我的代码并看看有什么问题吗 我猜我只是在操纵指针而不是创建任何新内容 this is a method of linkedlist
  • 如何在 C# 中解析/反序列化从 Rest 服务返回的 JSON

    我从结构如下的 URL 获取字符串格式的 JSON 但无法解析它 它抛出异常 知道如何解析它吗 结构如下 pathway patients patient patientid 7703176 name Abbot Bud status In
  • Magento 自定义管理模块为空

    我创建了一个自定义管理模块 但我无法在其中添加内容 它始终是空白的 我正在尝试使用简单的代码进行测试 但似乎没有任何效果 public function indexAction this gt loadLayout this gt addC
  • 即使关闭页面后脚本还会继续运行吗?

    如果我通过 jquery ajax 调用一个 php 文件 其中包含一个脚本来执行一些需要一段时间的操作 例如上传一个大视频 然后我关闭页面 php 脚本是否继续加载视频 看这里 http php net manual en functio
  • 在 Turtle - Python 3.4 中不设置动画?

    下面的代码创建一棵分形树 我想尽可能快地绘制它 我不希望发生任何动画 否则绘制需要很长时间 在Python的早期版本中 这是通过turtle speed 0 实现的 如下所示 这在 python 3 4 中不起作用 import turtl
  • 如果元素的 proptype 是默认值?

    如果我尝试将 proptype 设置为PropTypes element 不是必需的 正确的默认值是什么 static propTypes expandable PropTypes bool popover PropTypes elemen
  • 许多等待异步方法,还是单个等待包装 Task.Run?

    假设我们必须通过异步流程在数据库中写入包含 1000 个元素的列表 是等待 1000 次异步插入语句更好 还是将所有 1000 次插入包装在封装到一个同步方法中 Task Run声明 等待一次 例如 SqlCommand每种方法都与他的方法
  • 空引用检查的良好做法是什么? [复制]

    这个问题在这里已经有答案了 检查对象上的空引用的最有效方法是什么 我见过各种代码示例 它们具有不同的检查方式 因此以下哪一种是最有效的 或者哪一种被认为是最佳实践 Object ReferenceEquals item null item
  • 无法使用 StringLiteralConvertible 类型的参数列表调用“init”

    当我尝试运行下面的代码时 出现此错误 Cannot invoke init with argument list of type id StringLiteralConvertible host Contact target Contact
  • 我如何从 C++ 的子 c-tor 中初始化超类参数?

    观看以下示例 class A public A int param1 int param2 int param3 class B public A public B m param1 1 m param 2 m param 3 A m pa
  • Rails 5.1,图表显示多种货币的总和

    我遇到了一个关于图表踢的小问题 我有一个铁路应用程序 您可以在其中创建不同的货币 然后 您可以创建包含标题 金额的费用 并从列表和 user id 中选择货币 这种关系已经建立并且正在发挥作用 我的用户控制器中有这样的东西 user spe
  • 具有多个参数的 JPA Criteria API

    我需要创建一个使用带有多个参数的 JPA Criteria API 的搜索方法 现在的问题是并不是每个参数都是必需的 因此有些可能为空 并且它们不应包含在查询中 我已经用 CriteriaBuilder 尝试过此操作 但我不知道如何使其工作
  • 针对匿名对象的 System.Text.Json 序列化

    我正在开发一个 ASP Net Core 3 1 应用程序 使用 2 2 从另一个应用程序移植部分代码 到目前为止 我想从 NewtonSoft JSON 序列化库切换到新的 System Text Json 但遇到了一些麻烦 考虑一个使用
  • 将控制台输出定向到 Windows 窗体中的文本框的好方法是什么?

    在 C 中 将控制台输出定向到 Windows 窗体中的文本框的好方法是什么 如果我有一个包含 console WriteLine 的现有程序 我是否需要重载 Windows 窗体文本框中的函数 创建一个写入文本框的文本编写器 public
  • 描述符可以分配给实例属性而不是类属性吗?

    我正在研究 Python 描述符 到目前为止 我在 Google 上找到的所有示例都仅分配描述符对象的类属性 是否应该始终将描述符分配给类属性 描述符可以分配给实例属性吗 如果是这样 有什么例子或用例吗 例如 所有的例子都是这样的 gt g
  • Android:基于速度的 ViewPager 滚动

    ViewPager 现在的滚动方式是每个手势滚动一个项目 无论是全屏快速滑动还是慢速拖动 它对滑动手势的处理方式都是相同的 在最后一页仅前进一步 是否有任何项目或示例会添加基于速度的滑动 根据现有滑动的速度滚动多个项目 如果仍在进行中 并且