我创建了自己的RibbonView,在ListViews中看起来像这样
乍一看它在所有平台上看起来都很好,但在Android上它看起来不太好,当我滚动回ListView中的项目时,例如滚动到底部,然后回到顶部。
由于我调用旋转的唯一方法是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;
}
}
}
我还创建了一个示例应用,可以从this Dropbox link下载。
我希望有人在这里帮助我
答案 0 :(得分:0)
您需要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);
}
}
}
执行此操作后,首先应用此应用:
我无法理解您对翻译的计算方法。我还测试了您的原始代码和我的CustomRender
代码的修正值,结果是具有相同的值,不同的结果,我已在上面的图片中显示它们。
我希望这可以给你一些想法。