Как сделать изображение масштабируемым в Xamarin. Android? - PullRequest
1 голос
/ 12 января 2020

У меня есть следующее изображение:

enter image description here

Его размеры 1920 X 1901 pixels. По следующей ссылке указан его реальный размер:

https://i.stack.imgur.com/0rjdP.jpg

Я хочу, чтобы он занимал все пространство экрана ниже toolbar, но это так большой, когда я помещаю изображение на экран и запускаю приложение, когда я пытаюсь go на activity изображение, я получил исключение. Помимо желания заставить изображение занимать все пространство ниже панели инструментов, которое я хочу, когда я делаю жесты, растягиваю и зажимаю, изображение, чтобы увеличивать и уменьшать соответственно.

PS Я запускаю приложение на 5-дюймовом устройстве, но я планирую запустить его и на больших и меньших устройствах.

1 Ответ

1 голос
/ 13 января 2020

В Xamarin Android вы можете настроить Touch событие ImageView для его реализации.

Xml: добавление ImageView с примером изображения:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ImageView
        android:id="@+id/main_imgZooming"
        android:background="@color/accent_material_dark"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:scaleType="matrix"
        android:layout_gravity="center"
        android:src="@drawable/imageone"/>

</RelativeLayout>

Затем в Активность вы можете настроить сенсорное событие:

public class MainActivity : AppCompatActivity
{
    private ImageView view;

    private static  int NONE = 0;
    private static  int DRAG = 1;
    private static  int ZOOM = 2;

    private int mode = NONE;
    private float oldDist;
    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    private PointF start = new PointF();
    private PointF mid = new PointF();

    float minScaleR = 0.1f;  //Minimum scaling
    static  float MAX_SCALE = 4f; //Maximum zoom ratio
    //float dist = 1f;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.activity_main);

        /*
        view = FindViewById<ImageView>(Resource.Id.main_imgZooming);
        view.Touch += Img_test_Touch;

        matrix.SetScale(minScaleR, minScaleR); //Start zooming out first

        var metrics = Resources.DisplayMetrics;
        int screenWidth = metrics.WidthPixels;

        matrix.PostTranslate(screenWidth / 4, screenWidth / 2);     //The position of the image is offset by screenWidth/2 pixels from the top left corner of the imageview
        view.ImageMatrix = matrix;
        */
    }

    // calculator the distance of two points
    private float distance(MotionEvent eventA)
    {
        float x = eventA.GetX(0) - eventA.GetX(1);
        float y = eventA.GetY(0) - eventA.GetY(1);
        return (float)(System.Math.Sqrt(x * x + y * y));
    }

    // calculator the middle point of two points
    private PointF middle(MotionEvent eventB)
    {
        float x = eventB.GetX(0) + eventB.GetX(1);
        float y = eventB.GetY(0) + eventB.GetY(1);
        return new PointF(x / 2, y / 2);
    }


    private void Img_test_Touch(object sender, Android.Views.View.TouchEventArgs e)
    {
        ImageView view = sender as ImageView;
        switch (e.Event.Action & e.Event.ActionMasked)
        {
            //single finger
            case MotionEventActions.Down:
                //matrix.Set(view.Matrix);
                savedMatrix.Set(matrix);
                start.Set(e.Event.GetX(), e.Event.GetY());
                mode = DRAG;
                Console.WriteLine(mode +"---"+ e.Event.GetX());
            break;

            //double finger
            case MotionEventActions.PointerDown:
                oldDist = distance(e.Event);
                if (oldDist > 10f)
                {
                    savedMatrix.Set(matrix);
                    middle(e.Event);
                    mode = ZOOM;
                }
                Console.WriteLine(mode+"---" + oldDist);
             break;
            //finger up
            case MotionEventActions.Up:
            case MotionEventActions.PointerUp:
                mode = NONE;
                break;
            // finger move
            case MotionEventActions.Move:
                if (mode == DRAG)
                {
                    //single finger
                    matrix.Set(savedMatrix);
                    matrix.PostTranslate(e.Event.GetX() - start.X, e.Event.GetY() - start.Y);
                } else if (mode == ZOOM) {
                    //double finger
                    float newDist = distance(e.Event);
                    if (newDist > 10f) {
                        matrix.Set(savedMatrix);
                        float scale = newDist / oldDist;
                        matrix.PostScale(scale, scale, mid.X, mid.Y);
                    }
            }
            break;
        }

        view.ImageMatrix = matrix;
        CheckScale();  //Limit zoom range
        center();
    }

    //Limit maximum and minimum scaling
    protected void CheckScale()
    {
        float[] p = new float[9];
        matrix.GetValues(p);
        if (mode == ZOOM)
        {
            if (p[0] < minScaleR)
            {
                matrix.SetScale(minScaleR, minScaleR);
            }
            if (p[0] > MAX_SCALE)
            {
                matrix.Set(savedMatrix);
            }
        }
    }


    //Automatic centering
    protected void center()
    {
        center(true, true);
    }

    private void center(bool horizontal, bool vertical)
    {
        Matrix m = new Matrix();
        m.Set(matrix);
        Drawable d = GetDrawable(Resource.Drawable.imageone);
        //Get image width and height
        int imgWidth = d.IntrinsicWidth;
        int imgHeight = d.IntrinsicHeight;


        RectF rect = new RectF(0, 0, imgWidth, imgHeight);
        m.MapRect(rect);
        float height = rect.Height();
        float width = rect.Width();
        float deltaX = 0, deltaY = 0;

        var metrics = Resources.DisplayMetrics;

        if (vertical)
        {

            int screenHeight = metrics.HeightPixels;
            //Phone screen resolution height

            if (height < screenHeight)
            {
                deltaY = (screenHeight - height) / 2 - rect.Top;
            }
            else if (rect.Top > 0)
            {
                deltaY = -rect.Top;
            }
            else if (rect.Bottom < screenHeight)
            {
                deltaY = view.Height - rect.Bottom;
            }
        }

        if (horizontal)
        {
            //Phone screen resolution width
            int screenWidth = metrics.WidthPixels;

            if (width < screenWidth)
            {
                deltaX = (screenWidth - width) / 2 - rect.Left;
            }
            else if (rect.Left > 0)
            {
                deltaX = -rect.Left;
            }
            else if (rect.Right < screenWidth)
            {
                deltaX = screenWidth - rect.Right;
            }
        }
        matrix.PostTranslate(deltaX, deltaY);
    }
}

Эффект следующим образом:

enter image description here

...