【问题标题】:VelocityTracker giving random seeming resultsVelocityTracker 给出随机的看似结果
【发布时间】:2013-03-31 00:42:48
【问题描述】:

为了更好地了解视图的工作原理,我正在尝试制作一个RelativeLayout,我可以拖动它并扔掉它。这个想法是捕获onTouch事件,在ACTION_MOVE期间设置RelativeLayout的布局参数,然后使用Scroller来“投掷”ACTION_UP上的视图。

为了跟踪 Velocity,我使用了 VelocityTracker。当我拖动视图时,视图按预期移动,VelocityTracker 给出了看似随机的结果。

下面是我的手指在屏幕上从左向右滑动的日志 sn-p(两个数字是 x 和 y 速度)。如您所见,有很多负数,y 速度似乎比应有的大。

有人知道我做错了什么吗?

03-30 20:37:29.857: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    23.123592   11.537558
03-30 20:37:29.873: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    356.74066   55.184505
03-30 20:37:29.888: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    343.06155   43.027973
03-30 20:37:29.904: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    248.62907   32.232735
03-30 20:37:29.927: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    182.43666   22.957638
03-30 20:37:29.943: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    157.40408   54.90605
03-30 20:37:29.959: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    59.81672    15.241951
03-30 20:37:29.974: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    45.65707    -8.753063
03-30 20:37:29.990: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    62.7431 -23.311165
03-30 20:37:30.005: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    82.24246    -20.412537
03-30 20:37:30.029: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    101.6548    4.1870637
03-30 20:37:30.045: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    35.63154    -25.088724
03-30 20:37:30.060: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -65.35024   8.635846
03-30 20:37:30.076: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    34.84411    12.235493
03-30 20:37:30.091: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    137.96663   -32.02561
03-30 20:37:30.107: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    104.81523   4.6049824
03-30 20:37:30.130: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -15.846537  -23.924715
03-30 20:37:30.146: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    2.1034415   19.266556
03-30 20:37:30.162: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    20.578733   29.17785
03-30 20:37:30.177: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -28.217247  -42.907413
03-30 20:37:30.193: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -0.87727404 -1.170224
03-30 20:37:30.209: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -24.889711  8.474885
03-30 20:37:30.232: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    153.30855   23.77272
03-30 20:37:30.248: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    44.412945   17.595121
03-30 20:37:30.263: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -39.40518   -28.735428
03-30 20:37:30.279: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -58.433273  -2.295834
03-30 20:37:30.295: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    51.650055   -26.379906
03-30 20:37:30.310: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    152.88931   -20.75504
03-30 20:37:30.334: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    16.233286   -44.017315
03-30 20:37:30.349: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    23.231287   18.601854
03-30 20:37:30.365: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    7.3124657   38.14189
03-30 20:37:30.380: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    84.67032    -22.859661
03-30 20:37:30.396: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    22.753403   -6.019523
03-30 20:37:30.412: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    59.714558   -35.091564
03-30 20:37:30.435: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    27.547312   24.507784
03-30 20:37:30.451: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    114.54237   29.865501
03-30 20:37:30.466: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    70.55507    3.2689145
03-30 20:37:30.482: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -2.4525054  -6.8937516
03-30 20:37:30.498: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    17.924507   -40.815117
03-30 20:37:30.521: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    43.035046   0.5026546
03-30 20:37:30.537: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    95.18336    -11.013772
03-30 20:37:30.552: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -58.86387   10.808097
03-30 20:37:30.568: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -15.751452  12.716822
03-30 20:37:30.584: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    6.3607893   -19.160402
03-30 20:37:30.599: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    93.13071    12.679931
03-30 20:37:30.623: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    71.644485   -24.96885
03-30 20:37:30.638: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -12.482128  18.495268
03-30 20:37:30.654: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -107.08017  23.484608
03-30 20:37:30.670: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -1.009377   -20.781479
03-30 20:37:30.685: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    48.203453   0.5582556
03-30 20:37:30.701: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    12.369134   -34.194973
03-30 20:37:30.724: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    20.611326   14.374227
03-30 20:37:30.740: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    120.71236   56.88748
03-30 20:37:30.755: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    149.84518   14.843528
03-30 20:37:30.771: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -129.18591  -13.255397
03-30 20:37:30.787: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -110.96849  -42.02827
03-30 20:37:30.802: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -77.30668   -12.200225
03-30 20:37:30.826: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    44.793446   16.331116
03-30 20:37:30.841: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    30.79781    -47.53295
03-30 20:37:30.857: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -53.739525  -2.9649315
03-30 20:37:30.873: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -86.65882   -16.804096
03-30 20:37:30.888: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    47.278873   52.180782
03-30 20:37:30.904: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    25.044767   32.227722
03-30 20:37:30.927: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    40.374264   -65.27872
03-30 20:37:30.927: DEBUG/SlidingListViewRow(21863): ACTION_MOVE    -12.49039   -48.878017

代码:

package com.example.SlidingListViewRow;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;

public class SlidingListViewRow extends RelativeLayout {
    VelocityTracker mVelocityTracker;
    Scroller mScroller = new Scroller(getContext());


    float mStartX, mStartY;
    public SlidingListViewRow(Context context) {
        super(context);
    }

    public SlidingListViewRow(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SlidingListViewRow(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            {
                mVelocityTracker.clear();

                mScroller.abortAnimation();

                Log.d("SlidingListViewRow", "ACTION_DOWN: " + " x:" + event.getX() + " y:" + event.getY());
                mStartX = event.getX();
                mStartY = event.getY();

                mVelocityTracker.addMovement(event);

                return true;
            }
            case MotionEvent.ACTION_MOVE:
            {
                mVelocityTracker.addMovement(event);
                mVelocityTracker.computeCurrentVelocity(1000);

                float vx = mVelocityTracker.getXVelocity();
                float vy = mVelocityTracker.getYVelocity();
                FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
                Log.d("SlidingListViewRow", "ACTION_MOVE\t" + vx + "\t" + vy);

                lp.leftMargin = (int)(lp.leftMargin + event.getX() - mStartX);
                lp.topMargin = (int)(lp.topMargin + event.getY() - mStartY);

                setLayoutParams(lp);
                return true;
            }
            case MotionEvent.ACTION_UP:
            {
                mVelocityTracker.computeCurrentVelocity(1000);
                FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();

                Log.d("SlidingListViewRow", "ACTION_UP: " + mVelocityTracker.getXVelocity() + " " + mVelocityTracker.getYVelocity());
                mScroller.forceFinished(true);
                mScroller.startScroll(lp.leftMargin, lp.topMargin,
                        (int) mVelocityTracker.getXVelocity(),
                        (int) mVelocityTracker.getYVelocity(), 1000);

                invalidate();

                mVelocityTracker.recycle();
                mVelocityTracker = null;

                return true;
            }
            case MotionEvent.ACTION_CANCEL:
            {
                mVelocityTracker.recycle();
                mVelocityTracker = null;

            }

        }
        return super.onTouchEvent(event);
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            Log.d("SlidingListViewRow", "computeScroll " + mScroller.getCurrX() + " " + mScroller.getCurrY());


            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();

            lp.leftMargin = mScroller.getCurrX();
            lp.topMargin = mScroller.getCurrY();


            setLayoutParams(lp);

            invalidate();
        }
    }
}

编辑:我想我已经接近了。似乎正在发生的事情是运动事件与视图相关,并且因为我正在移动视图,它们只是在我最初触摸视图的地方抖动。记录event.getX() 和event.getY(),从上到下拖动手指时,我得到以下信息。请注意,x 和 y 几乎总是相同的。所以很明显,这种方法是行不通的。现在的问题是,我该如何绕过它?

04-06 10:55:13.460: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:241.85272 vx: 0.008770505 vy:7.7523403
04-06 10:55:13.476: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:244.04398 vx: -0.0014130835 vy:7.125545
04-06 10:55:13.491: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:242.04156 vx: -0.0018627803 vy:-8.498776
04-06 10:55:13.515: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:243.98645 vx: -0.0011581925 vy:-10.778463
04-06 10:55:13.530: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:243.67465 vx: 0.003123357 vy:-0.96067995
04-06 10:55:13.546: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:244.90335 vx: 0.0012589534 vy:20.408503
04-06 10:55:13.562: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:245.38507 vx: 0.0031079662 vy:42.45428
04-06 10:55:13.577: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:246.9231 vx: 0.00393455 vy:20.763577
04-06 10:55:13.616: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:245.3899 vx: 0.0024473427 vy:-15.408336
04-06 10:55:13.632: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:246.62701 vx: 1.6782524E-4 vy:12.024636
04-06 10:55:13.648: DEBUG/SlidingListViewRow(29988): ACTION_MOVE: x:174.0 y:247.16913 vx: 0.0032229617 vy:5.3146386

【问题讨论】:

  • 我想说你必须把你的 toucheventlistener 放在另一个视图上,一个不会移动的视图。
  • 谢谢你,你真棒!我在移动的View 上遇到了完全相同的速度问题。正确的解决方法是在第一个透明的View 上放置另一个透明的View,并将其向相反方向移动以使其固定。 :)

标签: android android-relativelayout touch-event


【解决方案1】:

我必须用你的手指看看你的动作,看看数字是否匹配。 一些注意事项: - 在某些情况下,模拟器中的结果完全不准确且出乎意料。 - 请注意,您没有跟踪指针。如果某一时刻屏幕上有多个压力点,它们可能会影响速度跟踪器的计算结果。

编辑: 你说的对。这些事件与其初始状态下的视图相关(除非您更改其 layoutParams),我不建议这样做。对于您想要做的事情,滚动应该可以完美地工作,这就是您正在做的事情。你想达到什么目的?我们最近发布了一个我过去几个月一直在研究的库,我的第一个方法与你的相似。 而是探索这个选项:

mScroller.startScroll(sx, sy, dx, dy, duration);

实际上,您拥有的代码似乎足以实现您想要的。您可以避免更改视图的布局参数,这不是那里的目标。 这将有助于了解您的目标是什么。 检查我们的图书馆,看看它是否更接近: https://github.com/6wunderkinder/android-sliding-layer-lib

您可以在此处的应用商店中找到演示应用:https://play.google.com/store/apps/details?id=com.slidinglayersample

让我们从这里重新开始。

编辑 2: 潜入 Android 源代码的 AbsListView 的代码中,我看到了一种对您有用的方法。 第 3502 行:

mFlingRunnable.startOverfling(-initialVelocity);

mFlingRunnable 是 Fl​​ingRunnable 类的一个对象,它在同一个 AbsListView 类中定义并从 Runnable 实现(http://code.metager.de/source/xref/android/1.6/frameworks/base/core/java/android/widget/AbsListView.java - 第 2237 行)。这是一大堆代码。 在第 1287 行的 Gallery 类 (http://code.metager.de/source/xref/android/1.6/frameworks/base/core/java/android/widget/Gallery.java) 中还有另一个示例。

这个想法是使用 Runnable 作为一种在每一帧上重新运行以重新计算和绘制被抛出对象的位置的方法。

这对于您的目标来说可能过于复杂。另一个想法是从 MotionEven.UP 或 CANCEL 上的速度跟踪器获取速度,并根据 VelocityTracked 注册的最后一个速度创建对象位置的动画:根据 VelocityTracked 将对象发送得更远或更近用户向上移动手指时的速度。

【讨论】:

  • 所以,我一直在使用我的设备 (Galaxy Nexus),还没有担心指针问题(小心只按一根手指)。我知道我最终将不得不这样做。不过,请参阅我上面的编辑,您的评论让我想到了我可能做错了什么,而且似乎是通过移动视图,我所有的运动事件都针对视图中的同一位置 - 因此抖动速度。
  • 看看编辑。你说的对。不要更改视图的 layoutParams。滚动应该就足够了。
  • 目标是点击视图,拖动它,然后就可以扔了。我的代码做前者就好了,但不是一掷千金。
  • 使用 fling 是什么意思:在该视图中滚动某些内容?还是放下它并让它四处移动直到停止?编辑有帮助吗?
  • 我做了,我查看了你的演示。我现在正在阅读代码,我认为 scrollTo 是我真正必须弄清楚的方法。对于投掷:在屏幕上画一个 100x100 像素的框。当你点击它时,你可以拖动它——它会跟随你的手指。当你松开它时,它会继续向你拖动它的方向移动一段时间,然后减速并停止。
【解决方案2】:

我也遇到了同样的问题。您在正确的轨道上翻译您的视图会影响速度跟踪器的计算。要解决此问题,请致电

MotionEvent.offsetLocation(diffX, diffY)

其中 diffX, diffY 对应于您在布局参数上所做的偏移量 - 所以在您的情况下 diffX 将是 event.getX() - mStartX。在您应用偏移量后,还请将运动事件添加到跟踪器作为处理 ACTION_MOVE 的最后一行。所以你的 ACTION_MOVE 处理应该是:

case MotionEvent.ACTION_MOVE:
                    {

                        float vx = mVelocityTracker.getXVelocity();
                        float vy = mVelocityTracker.getYVelocity();
                        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
                        Log.d("SlidingListViewRow", "ACTION_MOVE\t" + vx + "\t" + vy);

                        lp.leftMargin = (int)(lp.leftMargin + event.getX() - mStartX);
                        lp.topMargin = (int)(lp.topMargin + event.getY() - mStartY);

                        setLayoutParams(lp);
                        event.offsetLocation(event.getX() - mStartX, event.getY() - mStartY);
                        mVelocityTracker.addMovement(event);
                        mVelocityTracker.computeCurrentVelocity(1000);
                        return true;
                    }

【讨论】:

  • 这应该是公认的答案。我在这个 scheiße 上挣扎了 3 天。解决方案确实是在为 hte 跟踪器添加移动之前设置 motionEvent offsetLocation。就像你做的那样,在我的应用程序中我使用了 (event.rawX - touchPositionXInView, event.rawY - touchPositionYInView),它解决了我的速度问题。现在速度在任何方向上都有正确的 +/-。另外,在您的回答中, mVelocityTracker.computeCurrentVelocity(1000);除非您在该行之后立即输出速度,否则在这里没有用。如果在 ACTION_UP 中提取速度,则应该移动计算线。
【解决方案3】:

我遇到了完全相同的问题:我在跟踪速度的同时翻译视图。

为避免由于平移视图而导致速度计算错误,我使用了来自 Nineoldandroids 的AnimatorProxy.wrap(yourView).translateX(42);(也可在操作栏 sherlock 中使用)。这将允许您在不影响速度跟踪的情况下转换视图。

【讨论】:

    猜你喜欢
    • 2013-02-06
    • 1970-01-01
    • 2012-05-16
    • 2019-05-10
    • 2014-04-08
    • 2012-01-30
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    相关资源
    最近更新 更多