1

我创建了一个视图,它有一个占据屏幕顶部 1/3 的 MapFragment 和一个占据屏幕底部 2/3 的 ListView。ListView 在其列表项的正上方有一个“句柄”,用户可以使用它来向上或向下拖动整个 ListView。一旦用户将手指从屏幕上松开,ListView 应该动画到整个屏幕的壁橱顶部或底部边框。到目前为止,我的工作正常,但动画并不流畅。在用户从屏幕上松开手指之后,ListView 开始向最近的边缘移动之前,有一个明显的停顿。我正在使用 ObjectAnimator 的 Nineoldandroids 实现,以便动画可以在蜂窝设备之前运行。有任何想法吗?

下面是我的 onTouch 实现:

public boolean onTouch(View v, MotionEvent event) {
    final LayoutParams listLp = (LayoutParams) mListFrame.getLayoutParams();
    final int topMargin = -mHandleShadow.getHeight();
    final int middleMargin = getResources().getDimensionPixelSize(R.dimen.map_handle_margin_top);
    final int bottomMargin = getView().getHeight() - mHandle.getHeight() - mHandleShadow.getHeight();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mInitY = (int) event.getRawY();
            mTopMargin = listLp.topMargin;

            break;
        case MotionEvent.ACTION_MOVE:
            int y = mTopMargin + (int) event.getRawY() - mInitY;

            if (y >= -mHandleShadow.getHeight() && y <= (mViewHeight - mHandle.getHeight() - mHandleShadow.getHeight())) {
                listLp.topMargin = y;
                mListFrame.setLayoutParams(listLp);
            }

            break;
        case MotionEvent.ACTION_UP:
            if ((mInitY > event.getRawY() && mClosestAnchor == Anchor.MIDDLE) || (listLp.topMargin < middleMargin && mClosestAnchor == Anchor.BOTTOM)) {
                ObjectAnimator animator = ObjectAnimator.ofInt(AnimatorProxy.wrap(mListFrame), "topMargin", topMargin);
                animator.setInterpolator(new AccelerateInterpolator());
                animator.start();

                mClosestAnchor = Anchor.TOP;
            }
            else if ((mInitY < event.getRawY() && mClosestAnchor == Anchor.MIDDLE) || (listLp.topMargin > middleMargin && mClosestAnchor == Anchor.TOP)) {
                ObjectAnimator animator = ObjectAnimator.ofInt(AnimatorProxy.wrap(mListFrame), "topMargin", bottomMargin);
                animator.setInterpolator(new AccelerateInterpolator());
                animator.start();

                mClosestAnchor = Anchor.BOTTOM;
            }
            else {
                ObjectAnimator animator = ObjectAnimator.ofInt(AnimatorProxy.wrap(mListFrame), "topMargin", middleMargin);
                animator.setInterpolator(new AccelerateInterpolator());
                animator.start();

                mClosestAnchor = Anchor.MIDDLE;
            }

            break;
    }

    return true;
}
4

1 回答 1

8

在阅读了 Google 的 Chet Haase 对此处发现的类似问题的回答后,终于解决了这个问题。https://stackoverflow.com/a/14780019/476005

在每一帧上调整视图的边距过于昂贵并且总是会卡顿,除非您移动的视图非常简单。所以要解决这个问题,我在 OnTouch(...) 方法中执行以下操作:

  1. 在 MotionEvent.ACTION_DOWN 上:将 View 的高度设置为其最大高度。
  2. 在 MotionEvent.ACTION_MOVE 上:将 View 的“y”属性动画化到 event.getRawY,持续时间为 0。
  3. 在 MotionEvent.ACTION_UP 上:将 View 的“y”属性动画化到 View 的父级边缘之一。这里要做的重要事情是在 onAnimationEnd 中适当地设置 View 的高度。

我希望这对每个人都有帮助。

于 2013-04-19T11:24:45.457 回答