4

为了更好地理解视图是如何工作的,我正在尝试制作一个RelativeLayout我可以拖动和扔的东西。这个想法是捕获onTouch事件,设置RelativeLayoutduring的布局参数ACTION_MOVE,然后使用 aScroller将视图“投掷”在ACTION_UP.

为了跟踪速度,我使用了VelocityTracker. 虽然当我拖动视图时视图按预期移动,但它VelocityTracker给出了看似随机的结果。

下面是我的手指在屏幕上从左向右滑动的日志片段(两个数字是 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
4

3 回答 3

5

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

编辑:你是对的。这些事件与其初始状态下的视图相关(除非您更改其 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 ) 中还有另一个示例。

The idea is to use a Runnable as a means of something that re-runs on every frame recalculating and drawing the position of the flinged object.

This might go too complex for your goal. Another idea would be to take the velocity from the velocity tracker on MotionEven.UP or CANCEL and create an animation of the position of the object calculating the destination based on the last velocity registered by the VelocityTracked: sending the object further or nearer depending on the velocity at the time the user move her finger up.

于 2013-04-05T21:51:54.940 回答
2

I struggled with same problem. You are on right track that translating your view affects velocity tracker computation. To fix the problem please call

MotionEvent.offsetLocation(diffX, diffY)

where diffX, diffY are corresponding to the offset you made on layout params - so diffX in your case would be event.getX() - mStartX. Please also add motion event to tracker as last line of handling ACTION_MOVE, after you applied the offset. So your ACTION_MOVE handling should be:

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;
                    }
于 2016-03-25T14:15:10.497 回答
1

I had the exact same problem: I was translating the view while tracking velocity.

To avoid having the velocity mis-calculated due to translating the view, I used AnimatorProxy.wrap(yourView).translateX(42); from nineoldandroids (also available in action bar sherlock). This will allow you to translate your view without affecting velocity tracking.

于 2013-09-18T22:31:01.740 回答