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 滚动 的相关文章

  • 使用 google Directions API 的地图视图绘制方向 - 解码折线

    我正在尝试使用 Google 方向 API 在我的地图视图上显示方向 但我在从 JSON 响应获取数据时遇到困难 我可以获得 级别 和 点 字符串 但无法弄清楚如何将它们解码为地图上的点 任何帮助将非常感激 我有一个类可以为您解码它们 添加
  • Manifest Merger工具:替换失败

    我正在使用一个使用自己的 android theme 的库 因此在构建时收到以下错误 错误 55 9 任务 contacit processDebugManifest 执行失败 清单合并失败 AndroidManifest xml 中的属性
  • 带有一、二和三个按钮的 Android 警报对话框

    我不经常发出警报 但每次发出警报时 我都会花一些时间来阅读文档 https developer android com guide topics ui dialogs html并弄清楚如何去做 由于我现在不得不这样做几次 所以我将在下面写一
  • 安卓定位不准确

    我正在尝试获取当前用户的位置 我试图重构我的代码以获得更好的结果 但我只是不断得到关于准确度的荒谬位置 它在 900 600 米之间 如何才能得到更好的结果 使其精度达到50m以内 这是我的代码 package com agam mapsl
  • Android在排序列表时忽略大小写

    我有一个名为路径的列表 我目前正在使用以下代码对字符串进行排序 java util Collections sort path 这工作正常 它对我的 列表进行排序 但是它以不同的方式处理第一个字母的情况 即它用大写字母对列表进行排序 然后用
  • 如何为发布而不是调试创建密钥库?扑

    我按照使用此网站部署 flutter 的步骤进行操作https flutter io android release https flutter io android release 当我运行 flutter build apk 时出现此错
  • Camera.open()返回NULL Android开发

    我正在按照构建相机应用程序的教程进行操作http developer android com tools device html http developer android com tools device html我对 Camera o
  • 使用 gradlew assembleRelease 从 React Native 创建发布 apk 时出现错误

    我想发布 apk 但我收到错误 文件已存在 mkdir D mobile 它在 d 驱动器中生成名为 mobile 的文件 删除文件后 再次执行 gradlew assembleRelease 创建该文件并抛出错误 任务 app bundl
  • 菜单在片段的 onCreateOptionsMenu 处多次膨胀调用

    我使用 Fragments 当我切换到嵌套 Fragment 时 它实现了public void onCreateOptionsMenu Menu menu MenuInflater inflater 当我到达该嵌套片段时 我的菜单会多次膨
  • Android:滚动 Horizo​​ntalScrollView 时如何禁用 ScrollView 的垂直滚动?

    我正在开发一个带有带有 ScrollView 的 Activity 的 Android 应用程序 其中包含 Horizo ntalScrollView 等内容 当我触摸 Horizo ntalScrollView 时 我想禁用外部 Scro
  • 在 React Native 中调试应用程序崩溃

    我是 React Native 新手 我正在尝试安装 React Native Facebook SDK 以便我可以使用我的应用程序进行 Facebook 登录 我按照此处列出的步骤操作 https tylermcginnis com in
  • 有关 ListView 自定义行布局项目上的 onClick() 事件的帮助

    我有一个 ListView 其行由我格式化 每行都有 ImageView 和 TextView 的混合 我还实现了自己的适配器 并且能够通过它绘制每一行 现在 我想要这样的东西 用户单击 ImageView 不是行上的其他任何位置 但只有此
  • 如何修改 Skobbler 注释而不重新添加它

    我必须修改 SKAnnotation 的图像 注释生成器代码 private SKAnnotation getAnnotationFromView int id int minZoomLvl View view SKAnnotation a
  • java.lang.NumberFormatException: Invalid int: "3546504756",这个错误是什么意思?

    我正在创建一个 Android 应用程序 并且正在从文本文件中读取一些坐标 我在用着Integer parseInt xCoordinateStringFromFile 将 X 坐标转换为整数 Y 坐标的转换方法相同 当我运行该应用程序时
  • 如何在android asynctask中使用inputstream作为参数?

    我正在制作一个 Android 应用程序来跟踪股票详细信息 我将通过 csv 雅虎财经 检索数据 据我所知 在android 4 0中 网络连接无法在主线程上完成 因此 我将使用 asynctask 来建立连接 但是 我在参数方面遇到了一些
  • 模块中的类无法加载

    我正在开发一个 2D Unity android 游戏 其中我最近添加了 Firebase Beta SDK 但添加后FirebaseAnalytics unitypackage我面临的错误是 无法加载模块中的类 当我删除文件夹时Fireb
  • Android:RecyclerView 不显示片段中的列表项

    有人可以帮我尝试让我的 RecyclerView 出现吗 如果我不在片段中实现它 就会出现这种情况 然而 当我尝试将其实现到片段中时 CarFront 中的其他 XML 代码与 RecyclerView 分开显示 我的日志中收到此错误 E
  • Android 中循环事件的星期几和时间选择器

    我想创建一个控件 允许用户在我的 Android 活动中选择一周中的某一天 星期一 和一天中的某个时间 下午 1 00 找不到任何关于此的好帖子 好吧 我想我已经明白了 我只是不喜欢这个解决方案 因为我在一周中的某一天使用的微调器与时间选择
  • 使用 JobScheduler API 进行位置更新

    下面是我使用 FireBaseJobDispatcher 启动作业的演示代码 public class MainActivity extends AppCompatActivity Override protected void onCre
  • 如何在片段中实现 onBackPressed() 和意图?

    我知道 onBackPressed 是活动中的一种方法 但是 我想在片段中使用该功能 以便当按下后退按钮时 它会通过 Intent 重定向到另一个活动 有什么办法解决这个问题吗 public class News Events fragme

随机推荐

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