0

I am using Xamarin.Android to use inbuilt camera app to take a photo but there are two missed things that I cant do and I have been googling them for long time:

  1. I want to get a msg or popup (anything) after pressing the button to take a photo like "photo taken"
  2. I want to let the user focus on any point of the camera - TAP TO FOCUS
async void TakePhotoButtonTapped(object sender, EventArgs e)
{
    camera.StopPreview();
    Android.Hardware.Camera.Parameters parameters = camera.GetParameters();
    parameters.FocusMode = global::Android.Hardware.Camera.Parameters.FocusModeAuto;
    camera.SetParameters(parameters);
    var image = textureView.Bitmap;
    try
    {
        var absolutePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim).AbsolutePath;
        var folderPath = absolutePath + "/Camera";
        var filePath = System.IO.Path.Combine(folderPath, string.Format("photo_{0}.jpg", Guid.NewGuid()));
        var fileStream = new FileStream(filePath, FileMode.Create);
        await image.CompressAsync(Bitmap.CompressFormat.Jpeg, 92, fileStream);
        fileStream.Close();
        image.Recycle();
        var intent = new Android.Content.Intent(Android.Content.Intent.ActionMediaScannerScanFile);
        var file = new Java.IO.File(filePath);
        var uri = Android.Net.Uri.FromFile(file);
        intent.SetData(uri);
        MainActivity.Instance.SendBroadcast(intent);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(@"               ", ex.Message);
    }
    camera.StartPreview();
}

I tried this but not working:

public void OnAutoFocus(bool success, Android.Hardware.Camera camera)
{
    var parameters = camera.GetParameters();
    if (parameters.FocusMode != Android.Hardware.Camera.Parameters.FocusModeContinuousPicture)
    {
        parameters.FocusMode = Android.Hardware.Camera.Parameters.FocusModeContinuousPicture;
        if (parameters.MaxNumFocusAreas > 0)
        {
            parameters.FocusAreas = null;
        }
        camera.SetParameters(parameters);
        camera.StartPreview();
    }
}
public bool OnTouch(Android.Views.View view, MotionEvent e)
{
    if (camera != null)
    {
        var parameters = camera.GetParameters();
        camera.CancelAutoFocus();
        Rect focusRect = CalculateTapArea(e.GetX(), e.GetY(), 1f);
        if (parameters.FocusMode != Android.Hardware.Camera.Parameters.FocusModeAuto)
        {
            parameters.FocusMode = Android.Hardware.Camera.Parameters.FocusModeAuto;
        }
        if (parameters.MaxNumFocusAreas > 0)
        {
            List<Area> mylist = new List<Area>();
            mylist.Add(new Android.Hardware.Camera.Area(focusRect, 1000));
            parameters.FocusAreas = mylist;
        }
        try
        {
            camera.CancelAutoFocus();
            camera.SetParameters(parameters);
            camera.StartPreview();
            camera.AutoFocus(this);
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.Write(ex.StackTrace);
        }
        return true;
    }
    return false;
}
private Rect CalculateTapArea(object x, object y, float coefficient)
{
    var focusAreaSize = 500;
    int areaSize = Java.Lang.Float.ValueOf(focusAreaSize * coefficient).IntValue();
    int left = clamp((int) x - areaSize / 2, 0, textureView.Width - areaSize);
    int top = clamp((int) y - areaSize / 2, 0, textureView.Height - areaSize);
    RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
    Matrix.MapRect(rectF);
    return new Rect((int) System.Math.Round(rectF.Left), (int) System.Math.Round(rectF.Top), (int) System.Math.Round(rectF.Right),
        (int) System.Math.Round(rectF.Bottom));
}
private int clamp(int x, int min, int max)
{
    if (x > max)
    {
        return max;
    }
    if (x < min)
    {
        return min;
    }
    return x;
}
Mihail Duchev
  • 4,691
  • 10
  • 25
  • 32

1 Answers1

0

For focusing the camera when touching the preview you will need to:

  1. Add a touch event handler to listen for the user touching the preview
  2. Get the X and Y coordinates from that touch event, which are usually in the event arguments
  3. Create a rectangle to focus to tell the Android Camera where to focus and in which area
  4. Set FocusAreas and MeteringAreas on Camera.Parameters from your rectangle
  5. Set the new Camera.Parameters on the camera
  6. Set a AutoFocus callback on the camera
  7. When the callback triggers, remove the callback from the camera, and cancel auto focus

To notify the user about a picture being taken, you can use a Toast or create a area in your preview where you want to show such messages. It is entirely up to you how you want to notify the user.

Cheesebaron
  • 24,131
  • 15
  • 66
  • 118