首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用OnSizeAllocated的RibbonView - Android

使用OnSizeAllocated的RibbonView - Android
EN

Stack Overflow用户
提问于 2018-05-27 06:09:33
回答 1查看 134关注 0票数 0

我已经创建了自己的RibbonView,它在ListViews中如下所示

乍一看,它在所有平台上看起来都很好,但在安卓系统上,当我滚动回到ListView中的项目时,比如滚动到底部,然后再滚动到顶部,它看起来就不太好了。

因为我调用旋转的唯一方法是OnSizeAllocated,它可能来自那里,也可能来自设置TranslationX/TranslationY

我的RibbonView代码如下所示

代码语言:javascript
复制
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;
    }
  }
}

我还创建了一个示例应用程序,可以从this Dropbox link下载。

我希望这里有人能帮我

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-28 19:30:08

您的RibbonView需要使用CustomRender (MyContentViewContentView的类型):

代码语言:javascript
复制
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上渲染:

代码语言:javascript
复制
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);
        }
    }
}

这样做之后,首先你的应用应该是这样的:

如果你向上和向下滚动,它将变成:

我不明白你对翻译做了什么计算。我还测试了你的原始代码和我的CustomRender代码的固定值,结果是相同的值,不同的结果,我在上面的图片中显示了它们。

我希望这能给你一些想法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50547397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档