安卓系统的缩放和平移以及长时间点击时的儿童拖放功能



我有以下情况:

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。

知道吗?

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

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

总是返回CCD_ 6,并且它还阻止子级接收事件。

最新更新