RibbonView с использованием OnSizeAllocated - Android - PullRequest
0 голосов
/ 27 мая 2018

Я создал свой собственный RibbonView, который выглядит следующим образом в ListViews Intended Ribbons in ListViews

На первый взгляд он выглядит хорошо на всех платформах, но на Android он выглядит не очень хорошо, когда я прокручиваю назад к элементам в ListView, например, прокручиваю вниз, а затем обратно вверх.

Ribbons on Android after scrolling back

Как единственный метод, который я вызываю для поворотаOnSizeAllocated, это может быть оттуда или от настройки TranslationX / TranslationY.

Мой код для RibbonView показан ниже

using System;
using System.Collections.Generic;
using Xamarin.Forms;

namespace App1
{
  public class RibbonView : ContentView
  {
    public Point RotatedLowerLeftCorner { get; private set; }
    public Point RotatedLowerRightCorner { get; private set; }
    public Point RotatedUpperLeftCorner { get; private set; }
    public Point RotatedUpperRightCorner { get; private set; }

    protected override void OnSizeAllocated(double width, double height)
    {
      base.OnSizeAllocated(width, height);

      var upperLeft = new Point(Content.Margin.Left + Padding.Left, Content.Margin.Top + Padding.Top);

      var upperRight = upperLeft;
      upperRight.X += width - Content.Margin.HorizontalThickness - Padding.HorizontalThickness;

      var lowerLeft = upperLeft;
      lowerLeft.Y += height - Content.Margin.VerticalThickness - Padding.VerticalThickness;

      var lowerRight = upperRight;
      lowerRight.Y = lowerLeft.Y;

      var rotationPoint = new Point()
      {
        X = (lowerRight.X - upperLeft.X) * AnchorX + upperLeft.X,
        Y = (lowerRight.Y - upperLeft.Y) * AnchorY + upperLeft.Y
      };

      RotatedLowerLeftCorner = CalculateRotatedPoint(lowerLeft, rotationPoint);
      RotatedLowerRightCorner = CalculateRotatedPoint(lowerRight, rotationPoint);
      RotatedUpperLeftCorner = CalculateRotatedPoint(upperLeft, rotationPoint);
      RotatedUpperRightCorner = CalculateRotatedPoint(upperRight, rotationPoint);

      var translationX = Math.Min(Math.Min(RotatedUpperLeftCorner.X, RotatedUpperRightCorner.X), Math.Min(RotatedLowerLeftCorner.X, RotatedLowerRightCorner.X)) * (HorizontalOptions.Alignment == LayoutAlignment.End ? 1 : -1);
      var translationY = Math.Min(Math.Min(RotatedUpperLeftCorner.Y, RotatedUpperRightCorner.Y), Math.Min(RotatedLowerLeftCorner.Y, RotatedLowerRightCorner.Y)) * (VerticalOptions.Alignment == LayoutAlignment.End ? 1 : -1);

      Device.BeginInvokeOnMainThread(() =>
      {
        TranslationX = translationX;
        TranslationY = translationY;
      });

      CalculateSize(rotationPoint, translationX, translationY);
    }

    private Point AddTranslationsToPoint(Point p, double translationX, double translationY)
    {
      return new Point
      {
        X = p.X + translationX,
        Y = p.Y + translationY
      };
    }

    private Point CalculateRotatedPoint(Point p, Point rotationPoint)
    {
      var rotation = GetRotationInRadians();

      return new Point
      {
        X = Math.Cos(rotation) * (p.X - rotationPoint.X) - Math.Sin(rotation) * (p.Y - rotationPoint.Y) + rotationPoint.X,
        Y = Math.Sin(rotation) * (p.X - rotationPoint.X) + Math.Cos(rotation) * (p.Y - rotationPoint.Y) + rotationPoint.Y
      };
    }

    private void CalculateSize(Point rotationPoint, double translationX, double translationY)
    {
      var upperLeft = new Point(0, 0);
      var lowerLeft = new Point(Width, 0);
      var lowerRight = new Point(Width, Height);
      var upperRight = new Point(0, Height);

      var outerBox = new List<Point>
      {
        AddTranslationsToPoint(CalculateRotatedPoint(upperLeft, rotationPoint), X + translationX, Y + translationY),
        AddTranslationsToPoint(CalculateRotatedPoint(lowerLeft, rotationPoint), X + translationX, Y + translationY),
        AddTranslationsToPoint(CalculateRotatedPoint(lowerRight, rotationPoint), X + translationX, Y + translationY),
        AddTranslationsToPoint(CalculateRotatedPoint(upperRight, rotationPoint), X + translationX, Y + translationY)
      };

      var parentBox = new List<Point>();

      if (Parent is VisualElement parentVisualElement)
      {
        parentBox.Add(new Point(0, 0));
        parentBox.Add(new Point(parentVisualElement.Width, 0));
        parentBox.Add(new Point(parentVisualElement.Width, parentVisualElement.Height));
        parentBox.Add(new Point(0, parentVisualElement.Height));
      }
    }

    private double GetRotationInRadians()
    {
      var rotationInDeg = Rotation;

      while (rotationInDeg < 0)
      {
        rotationInDeg += 360;
      }

      return rotationInDeg * Math.PI / 180;
    }
  }
}

Я также создал образецприложение, которое можно загрузить с по этой ссылке Dropbox .

Я надеюсь, что кто-то здесь может помочь мне

1 Ответ

0 голосов
/ 28 мая 2018

Вам необходимо использовать CustomRender для вашего RibbonView (MyContentView - это тип ContentView):

public class RibbonView : MyContentView
{
 //....
        protected  override void OnSizeAllocated(double width, double height)
    {
        base.OnSizeAllocated(width, height);
        //System.Diagnostics.Debug.Write("width==" + width + "-------------------------------height==" + height);
        var upperLeft = new Point(Content.Margin.Left + Padding.Left, Content.Margin.Top + Padding.Top);

        var upperRight = upperLeft;
        upperRight.X += width - Content.Margin.HorizontalThickness - Padding.HorizontalThickness;

        var lowerLeft = upperLeft;
        lowerLeft.Y += height - Content.Margin.VerticalThickness - Padding.VerticalThickness;

        var lowerRight = upperRight;
        lowerRight.Y = lowerLeft.Y;

        var rotationPoint = new Point()
        {
            X = (lowerRight.X - upperLeft.X) * AnchorX + upperLeft.X,
            Y = (lowerRight.Y - upperLeft.Y) * AnchorY + upperLeft.Y
        };
        RotatedLowerLeftCorner = CalculateRotatedPoint(lowerLeft, rotationPoint);
        RotatedLowerRightCorner = CalculateRotatedPoint(lowerRight, rotationPoint);
        RotatedUpperLeftCorner = CalculateRotatedPoint(upperLeft, rotationPoint);
        RotatedUpperRightCorner = CalculateRotatedPoint(upperRight, rotationPoint);
        System.Diagnostics.Debug.Write("RotatedLowerLeftCorner==" + RotatedLowerLeftCorner + "-------------RotatedLowerRightCorner==" + RotatedLowerRightCorner 
            + "RotatedUpperLeftCorner==" + RotatedUpperLeftCorner +
            "-------------RotatedUpperRightCorner==" + RotatedUpperRightCorner);

        var translationX = Math.Min(Math.Min(RotatedUpperLeftCorner.X, RotatedUpperRightCorner.X), Math.Min(RotatedLowerLeftCorner.X, RotatedLowerRightCorner.X)) * (HorizontalOptions.Alignment == LayoutAlignment.End ? 1 : -1);
        var translationY = Math.Min(Math.Min(RotatedUpperLeftCorner.Y, RotatedUpperRightCorner.Y), Math.Min(RotatedLowerLeftCorner.Y, RotatedLowerRightCorner.Y)) * (VerticalOptions.Alignment == LayoutAlignment.End ? 1 : -1);

        //System.Diagnostics.Debug.Write("HorizontalOptions.Alignment========" + (HorizontalOptions.Alignment == LayoutAlignment.End ? 1 : -1)
        //  + "=============VerticalOptions.Alignment========" + (VerticalOptions.Alignment == LayoutAlignment.End ? 1 : -1));

        //Device.BeginInvokeOnMainThread(() =>
        //{
             //this.TranslateTo(97.8177608193967, -0.27103066889096);
            TranslationX = translationX;
            TranslationY = translationY;
            System.Diagnostics.Debug.Write("TranslationX=="+ TranslationX+ "-------------------------------TranslationY=="+ TranslationY);
        //});


        //CalculateSize(rotationPoint, translationX, translationY);
    }    

    //....
}

И вы визуализируете на Android:

using Android.Content;
using Android.Util;
using App1.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(App1.MyContentView), typeof(MyContentViewRender))]
namespace App1.Droid
{
    public class MyContentViewRender : ViewRenderer
    {

        public MyContentViewRender(Context context) : base(context)
        {
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);




            this.TranslationX = (float)e.NewElement.TranslationX;
            this.TranslationY= (float)e.NewElement.TranslationY;
            Log.Error("Android========", "TranslationX=="+ TranslationX+ "--------TranslationY"+ TranslationY); 

        }

        protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
        {
            base.OnSizeChanged(w, h, oldw, oldh);
        }
    }
}

После этого сначала ваше приложение должно выглядеть так:

enter image description here

Если вы прокрутите вверх и вниз, оно станет следующим: enter image description here

Не могу понять, что вы рассчитали на перевод.И я также проверяю значение исправления как ваших исходных кодов, так и моих CustomRender кодов, в результате я получаю их при одинаковом значении и разных результатах.

Я надеюсь, что это может датьвам несколько идей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...