Got a perfect solution from my Microsoft thread.
Write a new badgeview.
Firstly, create CircleView.cs
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace MyProject
{
public partial class CircleView : BoxView
{
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(double), typeof(CircleView), 0.0);
public double CornerRadius
{
get { return (double)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
public CircleView()
{
// InitializeComponent();
}
}
}
Then create contentview called BadgeView.xaml
and edit it to the Grid.
<?xml version="1.0" encoding="UTF-8"?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local1="clr-namespace:MyProject"
x:Class="MyProject.BadgeView"
HeightRequest="30"
WidthRequest="30">
<local1:CircleView x:Name="BadgeCircle" HeightRequest="30" WidthRequest="30" CornerRadius="30" VerticalOptions="Center" HorizontalOptions="Center" />
<Label x:Name="BadgeLabel" TextColor="White" VerticalOptions="Center" HorizontalOptions="Center" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" FontSize="15"/>
</Grid>
Here is BadgeView.xaml.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace MyProject
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BadgeView : Grid
{
public static BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(BadgeView), "0", propertyChanged: (bindable, oldVal, newVal) =>
{
var view = (BadgeView)bindable;
view.BadgeLabel.Text = (string)newVal;
});
public static BindableProperty BadgeColorProperty = BindableProperty.Create("BadgeColor", typeof(Color), typeof(BadgeView), Color.Blue, propertyChanged: (bindable, oldVal, newVal) =>
{
var view = (BadgeView)bindable;
view.BadgeCircle.BackgroundColor = (Color)newVal;
});
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
public Color BadgeColor
{
get
{
return (Color)GetValue(BadgeColorProperty);
}
set
{
SetValue(BadgeColorProperty, value);
}
}
public BadgeView()
{
InitializeComponent();
BadgeLabel.Text = Text;
BadgeCircle.BackgroundColor = BadgeColor;
}
}
}
Then you need to create a custom renderer for this CircleView in android.
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using MyProject;
using MyProject.Droid;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(CircleView), typeof(CircleViewRenderer))]
namespace MyProject.Droid
{
public class CircleViewRenderer : BoxRenderer
{
private float _cornerRadius;
private RectF _bounds;
private Path _path;
public CircleViewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
if (Element == null)
{
return;
}
var element = (CircleView)Element;
_cornerRadius = TypedValue.ApplyDimension(ComplexUnitType.Dip, (float)element.CornerRadius, Context.Resources.DisplayMetrics);
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
base.OnSizeChanged(w, h, oldw, oldh);
if (w != oldw && h != oldh)
{
_bounds = new RectF(0, 0, w, h);
}
_path = new Path();
_path.Reset();
_path.AddRoundRect(_bounds, _cornerRadius, _cornerRadius, Path.Direction.Cw);
_path.Close();
}
public override void Draw(Canvas canvas)
{
canvas.Save();
canvas.ClipPath(_path);
base.Draw(canvas);
canvas.Restore();
}
}
}
For iOS renderer.
[assembly: ExportRenderer(typeof(CircleView), typeof(CircleViewRenderer))]
namespace MyProject.iOS
{
public class CircleViewRenderer : BoxRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
Layer.MasksToBounds = true;
Layer.CornerRadius = (float)((CircleView)Element).CornerRadius / 2.0f;
}
}
}
In the end, we can use it in your HomePage1.cs Find the tag copy following code
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="33*" />
<ColumnDefinition Width="34*" />
<ColumnDefinition Width="33*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0">
<Grid>
<Grid TranslationY="-15">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="ic_white_dot_xx.png">
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
</Image>
<Image
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Source="ic_medal_xx.png" >
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
</Image>
</Grid>
<views:BadgeView x:Name="medals_badge" Text="30" BadgeColor="Red" VerticalOptions="Start" HorizontalOptions="End"/>
</Grid>
</StackLayout>
<StackLayout Grid.Column="1">
<Grid>
<Grid TranslationY="-15">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="ic_white_dot_xx.png">
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
</Image>
<Image
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Source="ic_badge_xx.png" >
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
</Image>
</Grid>
<views:BadgeView x:Name="badges_badge" Text="30" BadgeColor="Red" VerticalOptions="Start" HorizontalOptions="End"/>
</Grid>
</StackLayout>
<StackLayout Grid.Column="2">
<Grid>
<Grid TranslationY="-15">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="ic_white_dot_xx.png">
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>120</OnIdiom.Phone>
<OnIdiom.Tablet>240</OnIdiom.Tablet>
<OnIdiom.Desktop>120</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
</Image>
<Image
HorizontalOptions="Center"
VerticalOptions="Center"
Source="ic_star_xx.png" >
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.WidthRequest>
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>60</OnIdiom.Phone>
<OnIdiom.Tablet>90</OnIdiom.Tablet>
<OnIdiom.Desktop>60</OnIdiom.Desktop>
</OnIdiom>
</Image.HeightRequest>
</Image>
</Grid>
<views:BadgeView x:Name="star_badge" Text="30" BadgeColor="Red" VerticalOptions="Start" HorizontalOptions="End"/>
</Grid>
</StackLayout>
</Grid>
In the end, open your layout background code, you can find the GetUserMedals method. Set it directly.
medals_badge.Text = urlDetails.medals;
badges_badge.Text = urlDetails.badges;
star_badge.Text = urlDetails.stars;