Taoffi's blog

prisonniers du temps

Xamarin forms – the complete WP circle image!

James Montemagno published a post about implementing circle images using Xamarin Forms.

His proposed implementation for Win Phone was good. It clipped the image into a circle, but stopped a little short to draw the circle image border.

 

Droid

WP

 

I played with this to solve this small issue.

Here is a more complete version for WP renderer:

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
	base.OnElementPropertyChanged(sender, e);

	CircleImage		circleImg	= Element as CircleImage;

	if(circleImg == null || Control == null || Control.Clip != null || circleImg.Source == null)
		return;
			
	double		controlRadius	= Math.Min(Element.Width, Element.Height) / 2.0f;
	double		controlDiameter	= controlRadius * 2.0;

	if(controlRadius <= 0)
		return;


	// **********************************************
	// Note: this section ignores PNG transparency. 
	// **********************************************
	try
	{ 
		BitmapImage			srcBmp		= Control.Source as BitmapImage;

		WriteableBitmap		wrBmpSrc	= new WriteableBitmap((int) controlDiameter,
												 (int) controlDiameter);
		ImageBrush		imgBrush	= new ImageBrush();

		// use an image brush with the control’s image
		imgBrush.ImageSource = srcBmp;

		// set border thickness
		int	borderThickness	= circleImg.BorderThickness;
		Color	borderColor			= XamarinColor2WinColor(circleImg.BorderColor);

		// create a path with an ellipse geometry
		EllipseGeometry				ellipseG	= new EllipseGeometry()
			{
				Center		= new System.Windows.Point(controlRadius, controlRadius),
				RadiusX		= controlRadius,
				RadiusY		= controlRadius
			};
		GeometryGroup				geomGroup	= new GeometryGroup();

		geomGroup.Children.Add(ellipseG);

		System.Windows.Shapes.Path	path		= new System.Windows.Shapes.Path()
		{
			Stroke 		= new SolidColorBrush(borderColor),
			StrokeThickness	= borderThickness,
			Data			= geomGroup,
			Width			= controlDiameter,
			Height		= controlDiameter,
			Fill			= imgBrush,
		};

		wrBmpSrc.Render(path, null);
		wrBmpSrc.Invalidate();

		using (MemoryStream memStream = new MemoryStream())
		{
			wrBmpSrc.SaveJpeg(memStream, wrBmpSrc.PixelWidth, wrBmpSrc.PixelHeight, 0, 100);

			srcBmp.CreateOptions = BitmapCreateOptions.IgnoreImageCache;

			srcBmp = new BitmapImage();
			srcBmp.SetSource(memStream);
		}

		Control.Source			= srcBmp;
	}
	catch(Exception ex)
	{
		Debug.WriteLine(ex.Message);
		return;
	}

	// clip the control into circle
	Control.Clip = new EllipseGeometry
		{
			Center	= new System.Windows.Point(controlRadius, controlRadius),
			RadiusX	= Math.Max(controlRadius, 0),
			RadiusY	= Math.Max(controlRadius, 0)
		};
}

 

 

Color conversion helper method

 

		public static Color XamarinColor2WinColor(Xamarin.Forms.Color xamColor)
		{
			return Color.FromArgb (	(byte)(xamColor.A * 255),
									(byte)(xamColor.R * 255),
									(byte)(xamColor.G * 255),
									(byte)(xamColor.B * 255));
		}

 

 

 

Droid

WP

 

Comments are closed