10

Currently I am working on a Xamarin Forms Android project using MvvmCross. I have a strange problem regarding the Frame. Whenever I set the OutlineColor, it is displayed only in iOS and not in Android. I've tried with a different Xamarin Forms projects and it is displayed by both platforms without any problems. I don't have any indications why this is happening. Could MvvmCross somehow related with the issue?

Here is a sample:

  <core:BasePage
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:core="clr-namespace:Core.Base.Views;assembly=Core"
        x:Class="Views.TestPage"
        BackgroundImage="background_secret.png"
        Title="Test">

        <ContentPage.Content>
            <Grid
                HorizontalOptions="FillAndExpand"
                Padding="12,20,12,20"
                VerticalOptions="FillAndExpand">
                <Frame
                    HasShadow="false"
                    VerticalOptions="Fill"
                    BackgroundColor="White"
                    OutlineColor="#1961ac">
                    <StackLayout>
                        <Frame
                                VerticalOptions="Start"
                                Padding="8,4,8,4"
                                HasShadow="false"
                                OutlineColor="#9DB0BB">
                                <Label Text="Test"></Label>
                            </Frame>
                    </StackLayout>
        </Frame>
            </Grid>
        </ContentPage.Content>
    </core:BasePage>

Android page

iOS page

Xamarin Forms Version 2.1 MvvmCross Version 4.1

2
  • Could you add the important pieces of your XAML or UI code and a screenshot of iOS and Android? This might help. Commented Apr 12, 2016 at 18:39
  • Same issue from my side! any work around for this ?
    – Suchith
    Commented Sep 20, 2016 at 17:54

3 Answers 3

8

Even i got the same issue, to solve this i have added custom renderer for Frame control. In framerenderer need to override method Draw and private method DrawOutline as follows,

public override void Draw(ACanvas canvas)
{
    base.Draw(canvas);
    DrawOutline(canvas, canvas.Width, canvas.Height, 4f);//set corner radius
}
void DrawOutline(ACanvas canvas, int width, int height, float cornerRadius)
{
    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, width, height))
    {
        float rx = Forms.Context.ToPixels(cornerRadius);
        float ry = Forms.Context.ToPixels(cornerRadius);
        path.AddRoundRect(rect, rx, ry, direction);

        paint.StrokeWidth = 2f;  //set outline stroke
        paint.SetStyle(style);
        paint.Color = Color.ParseColor("#A7AE22");//set outline color //_frame.OutlineColor.ToAndroid(); 
        canvas.DrawPath(path, paint);
    }
} 

And in another approach you can also consider using the android selector xml of rounded corner as a background resource. For more detail on this check my blog post: http://www.appliedcodelog.com/2016/11/xamarin-form-frame-outline-color_21.html

3
  • 2nd option is an alternative right? you create a custom control out of frame. It is not very clear for me.
    – Emil
    Commented Jan 27, 2017 at 16:22
  • Create a custom control for frame and define background resource xml with darker border.
    – Suchith
    Commented Feb 21, 2017 at 9:23
  • 1
    The second alternative mentioned in the blog worked for me. Commented Sep 21, 2017 at 18:57
1

Suchith answer is correct and solve my problem here, but the Xamarin.Forms.Forms.Context is obsolete since the Xamarin version 2.5.

Now, the better approach is using Android.App.Application.Context so this is what code should be now.

    public override void Draw(Canvas canvas)
    {
        base.Draw(canvas);
        DrawOutline(canvas, canvas.Width, canvas.Height, 4f);//set corner radius
    }

    void DrawOutline(Canvas canvas, int width, int height, float cornerRadius)
    {
        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, width, height))
        {
            float rx = Android.App.Application.Context.ToPixels(cornerRadius);
            float ry = Android.App.Application.Context.ToPixels(cornerRadius);
            path.AddRoundRect(rect, rx, ry, direction);

            paint.StrokeWidth = 2f;  //set outline stroke
            paint.SetStyle(style);
            paint.Color = Android.Graphics.Color.ParseColor("#FFFFFF");//set outline color //_frame.OutlineColor.ToAndroid(); 
            canvas.DrawPath(path, paint);
        }
    }

In this link we have a great explanation for why we should use this new approach and why the Xamarin.Forms.Forms.Context is obsolete.

-1

MyCustomRenderer, see you ;)

using Xamarin.Forms.Platform.Android;
using Android.Graphics;
using Android.Graphics.Drawables;

[assembly: ExportRenderer(typeof(Frame), typeof(YourProject.Droid.Renderers.BorderFrameRenderer))]
namespace YourProject.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))
     {

          // stroke
         strokePaint.SetStyle(Paint.Style.Stroke);
          strokePaint.Color = Element.OutlineColor.ToAndroid();
         strokePaint.StrokeWidth = 5;

           canvas.DrawRoundRect(rect, Element.CornerRadius * 2, Element.CornerRadius * 2, strokePaint);  // stroke
        }
    }

 public BorderFrameRenderer(Context context) : base(context)
    {
    }

 protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
    {
        base.OnElementChanged(e);
    }
  }
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.