【问题标题】:Android zoom and pan and child drag and drop on long clickAndroid缩放和平移以及长按鼠标拖放
【发布时间】:2014-10-03 11:50:08
【问题描述】:

我有以下情况:

ZoomAndPanLayout
  |
  +---> ImageView
  |
  +---> FrameLayout (DragLayer)
            |
            +--->  One or more controls. A view with a circle drawn on it.

有一些小问题,因为我现在不关心 ZoomAndPanLayout 工作的屏幕绑定。我这样实现了 ZoomAndPan:

public class ZoomAndPanLayout extends FrameLayout {

    //region Constants

    public static final float DEFAULT_MIN_SCALE_FACTOR = 1.0f;
    public static final float DEFAULT_MAX_SCALE_FACTOR = 5.0f;

    // endregion Constants


    // region Fields

    private float translationX = 0;
    private float translationY = 0;

    private float pivotX = 0;
    private float pivotY = 0;

    private float oldX;
    private float oldY;

    private float scaleFactor = 1.0f;

    private float minScaleFactor = ZoomAndPanLayout.DEFAULT_MIN_SCALE_FACTOR;
    private float maxScaleFactor = ZoomAndPanLayout.DEFAULT_MAX_SCALE_FACTOR;

    private ScaleGestureDetector scaleGestureDetector = null;

    // endregion Fields


    // region Constructor

    public ZoomAndPanLayout(Context context) {
        super(context);
        this.initialize(context);
    }

    public ZoomAndPanLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.initialize(context);
    }

    public ZoomAndPanLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.initialize(context);
    }

    private void initialize(Context context) {
        this.scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
    }


    // endregion Constructor


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.scaleGestureDetector.onTouchEvent(event);

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
            {
                this.oldX = event.getX();
                this.oldY = event.getY();

                break;
            }

            case MotionEvent.ACTION_MOVE:
            {
                if (!this.scaleGestureDetector.isInProgress())
                {
                    float x = event.getX();
                    float y = event.getY();

                    float deltaX = x - this.oldX;
                    float deltaY = y - this.oldY;

                    this.translationX += deltaX;
                    this.translationY += deltaY;

                    this.applyTransformations();

                    this.oldX = x;
                    this.oldY = y;
                }
            }
        }

        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.scaleGestureDetector.onTouchEvent(event);
    }

    private void applyTransformations() {
        final View child = this.getChildAt(0);

        if (child != null)
        {
            child.setPivotX(this.pivotX);
            child.setPivotY(this.pivotY);

            child.setScaleX(this.scaleFactor);
            child.setScaleY(this.scaleFactor);

            // TODO: bound child to screen limits

            child.setTranslationX(this.translationX);
            child.setTranslationY(this.translationY);
        }
    }

    public Rect getChildRect() {

        View child = this.getChildAt(0);

        if (child != null)
        {
            Rect outRect = new Rect();

            outRect.right = (int) (child.getWidth() * child.getScaleX());
            outRect.bottom = (int) (child.getHeight() * child.getScaleY());

            int[] location = new int[2];
            child.getLocationOnScreen(location);

            outRect.offset(location[0], location[1]);

            return outRect;
        }
        else
        {
            return new Rect(0, 0, 0, 0);
        }
    }

    // region Private Inner Enums, Interfaces and Classes

    private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        private ZoomAndPanLayout upper = ZoomAndPanLayout.this;

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float newScaleFactor = detector.getScaleFactor();
            float originalScaleFactor = upper.scaleFactor;

            upper.scaleFactor *= newScaleFactor;

            // Bound the scaleFactor to the min and max limits
            if (upper.scaleFactor >= upper.maxScaleFactor)
            {
                upper.scaleFactor = upper.maxScaleFactor;
                newScaleFactor = upper.maxScaleFactor / originalScaleFactor;
            }
            else if (upper.scaleFactor * newScaleFactor <= upper.minScaleFactor)
            {
                upper.scaleFactor = upper.minScaleFactor;
                newScaleFactor = upper.minScaleFactor / originalScaleFactor;
            }

            // set pivot
            View child = upper.getChildAt(0);

            if (child != null)
            {
                if (newScaleFactor * child.getWidth() * upper.scaleFactor <= originalScaleFactor * child.getWidth()
                        || newScaleFactor * child.getHeight() * upper.scaleFactor <= originalScaleFactor * child.getWidth())
                {
                    upper.pivotX = newScaleFactor * child.getWidth() / 2;
                    upper.pivotY = newScaleFactor * child.getHeight() / 2;
                }
                else
                {
                    upper.pivotX = detector.getFocusX();
                    upper.pivotY = detector.getFocusY();
                }
            }

            upper.applyTransformations();

            return true;
        }
    }

    // endregion Private Inner Enums, Interfaces and Classes
}

当我创建 DragLayer 的每个子级时,我为它们分配了一个 OnLongClickListener,但该死的东西不会触发。当我长按 DragLayer 的任何子项时。

知道如何使用我的 ZoomAndPanLayout 想法或任何想法来实现这一点。如果你问自己为什么需要 ZoomAndPanLayout,那是因为我必须能够缩放和平移任何布局,而不仅仅是 ImageView。

有什么想法吗?

【问题讨论】:

    标签: android drag-and-drop zooming drag


    【解决方案1】:

    可能是因为您在 onTouchEvent 方法中返回了 true。 当true 返回时,它消耗了一个事件,孩子们不会收到他们自己的onTouchEvent

    @Override public boolean onInterceptTouchEvent(MotionEvent event) { return this.scaleGestureDetector.onTouchEvent(event); }

    总是返回true,它还会阻止孩子接收事件。

    【讨论】:

      猜你喜欢
      • 2011-08-28
      • 1970-01-01
      • 2018-03-20
      • 2023-01-25
      • 2023-02-11
      • 1970-01-01
      • 1970-01-01
      • 2012-08-23
      • 1970-01-01
      相关资源
      最近更新 更多