如何通过手势缩放Xamarin Android布局?

时间:2015-07-21 09:30:35

标签: android xamarin

我是Xamarin的新手。所以我正在制作Android应用程序。
我无法缩放Xamarin的布局。
我可以通过Zoom Controls 缩放布局,但是 不是用手势做的。

我想要缩放此布局,已经给出了布局的图像,所以我需要通过捏合手势来缩放整个事物。 http://imgur.com/ecWbZ7H

2 个答案:

答案 0 :(得分:0)

以这种方式尝试长期为我工作

using Android.Content;
using Android.Graphics;
using Android.Util;
using Android.Views;
using Android.Widget;
using System;

namespace TestApp.Mobile.AL
{
public class ScaleImageView : ImageView, View.IOnTouchListener
{
private Context _cContext;
private float MAX_SCALE = 2f;

    private Matrix _mMatrix;
    private float[] _fMatrixValues = new float[9];

    // display width height.
    private int _iWidth;
    private int _iHeight;

    private int _iIntrinsicWidth;
    private int _iIntrinsicHeight;

    private float _fScale;
    private float _fMinScale;

    private float _fPrevDistance;
    private bool _bIsScaling;

    private int _iPrevMoveX;
    private int _iPrevMoveY;
    private GestureDetector _gdDetector;

    String TAG = "ScaleImageView";

    public ScaleImageView(Context cContext, IAttributeSet asAttr)
        : base(cContext, asAttr)
    {
        this._cContext = cContext;
        Initialize();
    }

    public ScaleImageView(Context context)
        : base(context)
    {
        this._cContext = context;
        Initialize();
    }

    public override void SetImageBitmap(Bitmap bBitmap)
    {
        base.SetImageBitmap(bBitmap);
        this.Initialize();
    }


    public override void SetImageResource(int iResId)
    {
        base.SetImageResource(iResId);
        this.Initialize();
    }

    private void Initialize()
    {
        this.SetScaleType(ScaleType.Matrix);
        this._mMatrix = new Matrix();
        Android.Graphics.Drawables.Drawable dDrawable = this.Drawable;
        if (dDrawable != null)
        {
            _iIntrinsicWidth = dDrawable.IntrinsicWidth;
            _iIntrinsicHeight = dDrawable.IntrinsicHeight;
            SetOnTouchListener(this);
        }

        ScaleImageViewGestureListner glListner = new ScaleImageViewGestureListner(this);
        _gdDetector = new GestureDetector(_cContext, glListner);
    }

    protected override bool SetFrame(int iL, int iT, int iR, int iB)
    {
        _iWidth = iR - iL;
        _iHeight = iB - iT;

        _mMatrix.Reset();
        int r_norm = iR - iL;
        _fScale = (float)r_norm / (float)_iIntrinsicWidth;

        int paddingHeight = 0;
        int paddingWidth = 0;
        // scaling vertical
        if (_fScale * _iIntrinsicHeight > _iHeight)
        {
            _fScale = (float)_iHeight / (float)_iIntrinsicHeight;
            _mMatrix.PostScale(_fScale, _fScale);
            paddingWidth = (iR - _iWidth) / 2;
            paddingHeight = 0;
            // scaling horizontal
        }
        else
        {
            _mMatrix.PostScale(_fScale, _fScale);
            paddingHeight = (iB - _iHeight) / 2;
            paddingWidth = 0;
        }
        _mMatrix.PostTranslate(paddingWidth, paddingHeight);

        this.ImageMatrix = _mMatrix;
        _fMinScale = _fScale;
        ZoomTo(_fScale, _iWidth / 2, _iHeight / 2);
        Cutting();
        return SetFrame(iL, iT, iR, iB);
    }

    protected float GetValue(Matrix mMatrix, int iWhichValue)
    {
        mMatrix.GetValues(_fMatrixValues);
        return _fMatrixValues[iWhichValue];
    }

    protected float GetScale()
    {
        return GetValue(_mMatrix, Matrix.MscaleX);
    }

    public float GetTranslateX()
    {
        return GetValue(_mMatrix, Matrix.MscaleX);
    }

    protected float GetTranslateY()
    {
        return GetValue(_mMatrix, Matrix.MscaleY);
    }

    protected void MaxZoomTo(int iX, int iY)
    {
        if (_fMinScale != GetScale() && (GetScale() - _fMinScale) > 0.1f)
        {
            // threshold 0.1f
            float scale = _fMinScale / GetScale();
            ZoomTo(scale, iX, iY);
        }
        else
        {
            float scale = MAX_SCALE / GetScale();
            ZoomTo(scale, iX, iY);
        }
    }

    public void ZoomTo(float fScale, int iX, int iY)
    {
        if (GetScale() * fScale < _fMinScale)
        {
            return;
        }
        if (fScale >= 1 && GetScale() * fScale > MAX_SCALE)
        {
            return;
        }
        _mMatrix.PostScale(fScale, fScale);
        // move to center
        _mMatrix.PostTranslate(-(_iWidth * fScale - _iWidth) / 2, -(_iHeight * fScale - _iHeight) / 2);

        // move x and y distance
        _mMatrix.PostTranslate(-(iX - (_iWidth / 2)) * fScale, 0);
        _mMatrix.PostTranslate(0, -(iY - (_iHeight / 2)) * fScale);
        this.ImageMatrix = _mMatrix;
    }

    public void Cutting()
    {
        int iWidth = (int)(_iIntrinsicWidth * GetScale());
        int iHeight = (int)(_iIntrinsicHeight * GetScale());
        if (GetTranslateX() < -(iWidth - _iWidth))
        {
            _mMatrix.PostTranslate(-(GetTranslateX() + iWidth - _iWidth), 0);
        }
        if (GetTranslateX() > 0)
        {
            _mMatrix.PostTranslate(-GetTranslateX(), 0);
        }
        if (GetTranslateY() < -(iHeight - _iHeight))
        {
            _mMatrix.PostTranslate(0, -(GetTranslateY() + iHeight - _iHeight));
        }
        if (GetTranslateY() > 0)
        {
            _mMatrix.PostTranslate(0, -GetTranslateY());
        }
        if (iWidth < _iWidth)
        {
            _mMatrix.PostTranslate((_iWidth - iWidth) / 2, 0);
        }
        if (iHeight < _iHeight)
        {
            _mMatrix.PostTranslate(0, (_iHeight - iHeight) / 2);
        }
        this.ImageMatrix = _mMatrix;
    }

    private float Distance(float fX0, float fX1, float fY0, float fY1)
    {
        float x = fX0 - fX1;
        float y = fY0 - fY1;
        return FloatMath.Sqrt(x * x + y * y);
    }

    private float DispDistance()
    {
        return FloatMath.Sqrt(_iWidth * _iWidth + _iHeight * _iHeight);
    }

    public override bool OnTouchEvent(MotionEvent meMotionEvent)
    {
        if (_gdDetector.OnTouchEvent(meMotionEvent))
        {
            return true;
        }
        int iTouchCount = meMotionEvent.PointerCount;
        if (meMotionEvent.Action == MotionEventActions.Down || meMotionEvent.Action == MotionEventActions.Pointer1Down || meMotionEvent.Action == MotionEventActions.Pointer2Down)
        {
            if (iTouchCount >= 2)
            {
                float distance = Distance(meMotionEvent.GetX(0), meMotionEvent.GetX(1), meMotionEvent.GetY(0), meMotionEvent.GetY(1));
                _fPrevDistance = distance;
                _bIsScaling = true;
            }
            else
            {
                _iPrevMoveX = (int)meMotionEvent.GetX();
                _iPrevMoveY = (int)meMotionEvent.GetY();
            }
        }
        else if (meMotionEvent.Action == MotionEventActions.Move)
        {
            if (iTouchCount >= 2 && _bIsScaling)
            {
                float dist = Distance(meMotionEvent.GetX(0), meMotionEvent.GetX(1), meMotionEvent.GetY(0), meMotionEvent.GetY(1));
                float scale = (dist - _fPrevDistance) / DispDistance();
                _fPrevDistance = dist;
                scale += 1;
                scale = scale * scale;
                ZoomTo(scale, _iWidth / 2, _iHeight / 2);
                Cutting();
            }
            else if (!_bIsScaling)
            {
                int distanceX = _iPrevMoveX - (int)meMotionEvent.GetX();
                int distanceY = _iPrevMoveY - (int)meMotionEvent.GetY();
                _iPrevMoveX = (int)meMotionEvent.GetX();
                _iPrevMoveY = (int)meMotionEvent.GetY();
                _mMatrix.PostTranslate(-distanceX, -distanceY);
                Cutting();
            }
        }
        else if (meMotionEvent.Action == MotionEventActions.Up || meMotionEvent.Action == MotionEventActions.Pointer1Up || meMotionEvent.Action == MotionEventActions.Pointer2Up)
        {
            if (meMotionEvent.PointerCount <= 1)
            {
                _bIsScaling = false;
            }
        }
        return true;
    }

    public bool OnTouch(Android.Views.View vView, Android.Views.MotionEvent meMotionEvent)
    {
        return OnTouchEvent(meMotionEvent);
    }

    public class ScaleImageViewGestureListner : GestureDetector.SimpleOnGestureListener
    {
        private ScaleImageView _sivView;

        public ScaleImageViewGestureListner(ScaleImageView sivView)
        {
            this._sivView = sivView;
        }

        public override bool OnDoubleTap(MotionEvent e)
        {
            _sivView.MaxZoomTo((int)e.GetX(), (int)e.GetY());
            _sivView.Cutting();
            return OnDoubleTap(e);
        }
    }
 }

}

答案 1 :(得分:0)

按照本指南,它将为您提供触摸和捏合手势的基础知识,以便您轻松进行缩放。

Part 4 - Walkthrough: Using Touch in Android