Xamarin forms: ImageCropper.Forms: How to remove the multiple pop-up and how to get the stream & path value of the final image?

Sreejith Sree 1,251 Reputation points
2021-01-21T10:24:34.67+00:00

I am using ImageCropper.Forms for cropping the image selected from the camera and gallery. I have 3 options for changing a profile picture; Take Photo, Upload from Gallery and Select Avatar. So for showing the Media options I am using a DisplayActionSheet like below:

var actionSheet = await DisplayActionSheet(null,"Cancel", null, "Take Photo", "Upload from Gallery", "Select Avatar");  
if (actionSheet == "Take Photo")  
{  
	OpenCamera();  
}  
else if(actionSheet == "Upload from Gallery")  
{  
	Opengallery();  
}  
else if(actionSheet == "Select Avatar")  
{  
	OpenAvatar();  
}  

OpenCamera() and Opengallery() are added below. That code is also asking the Take Photo and Photo Library options again as a popup. I don't need that pop up, is there any way to remove the second popup asked by ImageCropper.Forms and load the camera or gallery directly?

My Code:

    async void OpenCamera()  
	{  
		try  
		{  
			await CrossMedia.Current.Initialize();  
            //I need to open camera only here, no need of a pop up again.  
			new ImageCropper()  
			{  
				PageTitle = "Test Title",  
				AspectRatioX = 1,  
				AspectRatioY = 1,  
				CropShape = ImageCropper.CropShapeType.Rectangle,  
				SelectSourceTitle = "Select source",  
				TakePhotoTitle = "Take Photo",  
				PhotoLibraryTitle = "Photo Library",  
				Success = (imageFile) =>  
				{  
					Device.BeginInvokeOnMainThread(() =>  
					{  
						profilephoto.Source = ImageSource.FromFile(imageFile);  
					});  
				}  
			}.Show(this);  
		}  
		catch (Exception ex)  
		{  
			System.Diagnostics.Debug.WriteLine("CameraException:>" + ex);  
		}  
	}  

async void Opengallery()  
{  
	try  
	{  
		await CrossMedia.Current.Initialize();  
        //I need to open gallery only here, no need of a pop up again.  
		new ImageCropper()  
		{  
			PageTitle = "Test Title",  
			AspectRatioX = 1,  
			AspectRatioY = 1,  
			CropShape = ImageCropper.CropShapeType.Rectangle,  
			SelectSourceTitle = "Select source",  
			TakePhotoTitle = "Take Photo",  
			PhotoLibraryTitle = "Photo Library",  
			Success = (imageFile) =>  
			{  
				Device.BeginInvokeOnMainThread(() =>  
				{  
					profilephoto.Source = ImageSource.FromFile(imageFile);  
					//var stream = ImageSource.FromFile(imageFile);  
					//imagefile = imageFile;  
				});  
			}  
		}.Show(this);  
	}  
}  

Screenshot:

59162-processased.jpeg

I have one more issue related to this. I need to save the cropped image to server, I was using MediaPlugin in my initial implementation and using that plugin I get the selected image as a MediaFile. Using MediaFile I am able to save the picture to server using it's stream and path like below.

private MediaFile _mediaFile;  
public async void SaveProfile(object sender, EventArgs args)  
{  
	var content = new MultipartFormDataContent();  
	content.Add(new StreamContent(_mediaFile.GetStream()), "\"file\"", $"\"{_mediaFile.Path}\"");  
	HttpClient client = new HttpClient();  
	var response = client.PostAsync(new Uri("Service URL"), content).Result;  
}  

But after the cropping implementation, I don't know how to get the stream value and path of the final cropped image. So please suggest a solution for that issue. SaveProfile is an another function outside OpenCamera() and Opengallery().

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,364 questions
0 comments No comments
{count} votes

Accepted answer
  1. Sreejith Sree 1,251 Reputation points
    2021-01-22T04:41:24.71+00:00

    The default alert is been defined in the package . So I don't think we can block it directly . If you want to set the text of it you just need to set

    SelectSourceTitle = " ",
    TakePhotoTitle = "Take Photo",
    PhotoLibraryTitle = "Upload from Gallery"
    

    Use a Success handler

    String path = "";
    new ImageCropper()
    {
        Success = (imageFile) =>
        {
            // image file is the string path, do whatever you
            // need here
            path = imageFile;
        }
    }.Show(this);
    

    Convert stream like below in save function:

    var fileBytes = File.ReadAllBytes(path);
    ByteArrayContent byteContent = new ByteArrayContent(fileBytes);
    var fileName = Path.GetFileName(path);
    content.Add(byteContent, "file", fileName);
    

    where imageFile is a string containing the file path

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.