问题
I am developing the app in Xamarin Forms and I have faced a bug that should be fixed long time ago. I tried to set outline for frame and it works good on ios but doesn't work on android.
Here is my xaml for Frame.
<Frame
HasShadow="true"
CornerRadius="10"
OutlineColor="Red"
BackgroundColor="White">
<StackLayout
Orientation="Horizontal">
<Label
Text="TEST"
VerticalOptions="Center"/>
<Label
Text="For OUTLINE"
VerticalOptions="Center"/>
</StackLayout>
</Frame>
Thanks for any help!
回答1:
This doesn't work for android. Bug is reported here.
Solution 1:
You should make a Renderer
for the Frame
for Android Platform as follows:
using System;
using Android.Graphics.Drawables;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XFormsUI.Droid;
[assembly: ExportRenderer(typeof(Frame), typeof(RoundBorderFrameRenderer))]
namespace XFormsUI.Droid
{
public class RoundBorderFrameRenderer : FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null && e.OldElement == null)
{
SetBackgroundResource(Resource.Drawable.round_border_frame);
//Write following lines if you want to bring the XAML Frame Elements's background Color into Native. Otherwise, Frame's BackgroundColor will not be effective.
GradientDrawable drawable = (GradientDrawable)Background;
string FrameBackgroundColorHex = String.Format("#{0:X2}{1:X2}{2:X2}", (int)(e.NewElement.BackgroundColor.R * 255), (int)(e.NewElement.BackgroundColor.G * 255), (int)(e.NewElement.BackgroundColor.B * 255));
drawable.SetColor(Android.Graphics.Color.ParseColor(FrameBackgroundColorHex));
}
}
}
}
This also requires an xml
(round_border_frame.xml)
selector file. Put this file in your Drawable
folder.
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<!--We need to give Frame's 'BorderColor Here-->
<stroke android:width="1dp" android:color="#FF0000" />
<corners android:radius="10dp" />
</shape>
Solution 2:
Using Renderer
without selector xml file. Source.
using System;
using Android.Graphics;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XFormsUI.Droid;
[assembly: ExportRenderer(typeof(Frame), typeof(RoundBorderFrameRenderer))]
namespace XFormsUI.Droid
{
public class RoundBorderFrameRenderer : FrameRenderer
{
public override void Draw(Canvas canvas)
{
base.Draw(canvas);
using (var paint = new Paint { AntiAlias = true })
using (var path = new Path())
using (Path.Direction direction = Path.Direction.Cw)
using (Paint.Style style = Paint.Style.Stroke)
using (var rect = new RectF(0, 0, canvas.Width, canvas.Height))
{
float px = Forms.Context.ToPixels(Element != null ? Element.CornerRadius : 10); //Default Corner Radius = 10
float py = Forms.Context.ToPixels(Element != null ? Element.CornerRadius : 10); //Default Corner Radius = 10
path.AddRoundRect(rect, px, py, direction);
//Set the Width of the Border here
paint.StrokeWidth = 1f;
paint.SetStyle(style);
//Take OutLineColor from XAML Frame element and set it natively here.
string FrameBorderColorHex = String.Format("#{0:X2}{1:X2}{2:X2}", (int)(Element.OutlineColor.R * 255), (int)(Element.OutlineColor.G * 255), (int)(Element.OutlineColor.B * 255));
paint.Color = Android.Graphics.Color.ParseColor(FrameBorderColorHex);
canvas.DrawPath(path, paint);
}
}
}
}
Solution 3:
However this is not the best solution but it's kind of a workaround:
Wrap your outer Frame
inside another Frame
having Padding
and set its BackgroundColor
to whatever your Border Color should be.
Note: I haven't checked this yet on iOS.
<Frame BackgroundColor="Red" CornerRadius="10" Padding="1,1,1,1">
<Frame CornerRadius="10" BackgroundColor="White">
<StackLayout Orientation="Horizontal">
<Label Text="TEST" VerticalOptions="Center" />
<Label Text="For OUTLINE" VerticalOptions="Center" />
</StackLayout>
</Frame>
</Frame>
People are discussing this on this thread.
Hope this will help!!
回答2:
I was stuck around an half a day with this issue..
There my solution:
using System;
using Android.Content;
using MyGlobe.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Graphics;
using Android.Graphics.Drawables;
[assembly: ExportRenderer(typeof(Frame),typeof(MyGlobe.Droid.Renderers.BorderFrameRenderer))]
namespace Yours.Droid.Renderers
{
public class BorderFrameRenderer : FrameRenderer
{
public override void Draw(Canvas canvas)
{
base.Draw(canvas);
using (var strokePaint = new Paint())
using (var rect = new RectF(0, 0, canvas.Width, canvas.Height))
{
string FrameBorderColorHex = String.Format("#{3:X2}{0:X2}{1:X2}{2:X2}", (int)(Element.OutlineColor.R * 255), (int)(Element.OutlineColor.G * 255), (int)(Element.OutlineColor.B * 255), (int)(Element.OutlineColor.A * 255));
// stroke
strokePaint.SetStyle(Paint.Style.Stroke);
strokePaint.Color = Android.Graphics.Color.ParseColor(FrameBorderColorHex);
strokePaint.StrokeWidth = 5;
var radius = 10;
canvas.DrawRoundRect(rect, radius, radius, strokePaint); // stroke
}
}
public BorderFrameRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
}
}
}
来源:https://stackoverflow.com/questions/47484760/frame-outlinecolor-not-work-in-only-android-xamarin-forms