我已经创建了自己的RibbonView,它在ListViews中如下所示
乍一看,它在所有平台上看起来都很好,但在安卓系统上,当我滚动回到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下载。
我希望这里有人能帮我
发布于 2018-05-28 19:30:08
您的RibbonView
需要使用CustomRender
(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
代码的固定值,结果是相同的值,不同的结果,我在上面的图片中显示了它们。
我希望这能给你一些想法。
https://stackoverflow.com/questions/50547397
复制相似问题