我正在尝试为我的相机页面实现手动对焦功能,以便用户可以点按以对焦相机。
我正在关注原始Android的this StackOverflow question that's currently written in Java。我一直在将它转换为C#,用于我的Xamarin.Forms Android应用程序。
这是我到目前为止所拥有的:
public class CameraPage : PageRenderer, TextureView.ISurfaceTextureListener, Android.Views.View.IOnTouchListener, IAutoFocusCallback
{
global::Android.Hardware.Camera camera;
TextureView textureView;
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 v, 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(OnAutoFocus); //Here is the issue. How do I use the callback?
}
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;
}
}
我设法转换了大部分内容,但我不确定如何正确使用AutoFocusCallback。我应该如何从我的OnTouch事件中调用OnAutoFocus,就像上面链接的java答案一样?
在我附加回调之后,我需要做的就是将OnTouch事件订阅到我的页面正确或......?
例如,我尝试过:
textureView.Click += OnTouch;
但是'OnTouch'没有超载匹配委托'EventHandler'。我需要使用特定的事件处理程序吗?
答案 0 :(得分:2)
您可以尝试更改
camera.AutoFocus(OnAutoFocus);
到
camera.AutoFocus(this);
它将使用OnAutoFocus,因为它是从IAutoFocusCallback实现的。
关于订阅事件的问题,您可以尝试在OnElementChanged中订阅事件
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
this.SetOnTouchListener(this);
}
catch (Exception e)
{
}
}
顺便说一句,我不想在此代码中使用TextureView.ISurfaceTextureListener
。
答案 1 :(得分:1)
在链接的Java答案中发生的所有事情是它们提供了在操作系统调用回调时运行的代码:
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
camera.cancelAutoFocus();
Parameters params = camera.getParameters();
if(params.getFocusMode() != Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE){
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.setParameters(params);
}
}
});
上面没有“调用”回调,只是提供回调代码来运行。操作系统调用回调。所以在Xamarin中,你需要传入实现IAutoFocusCallback
接口的类型,所以你应该能够做到这一点我认为,因为CameraPage正在实现IAutoFocusCallback
接口:
camera.AutoFocus(this); // "this" refers to your current CameraPage which implements the interface.
这里的线索是,当您在camera.AutoFocus
之后键入左括号时,弹出窗口显示您需要传入类型IAutoFocusCallback
,这意味着实现该接口的任何类型,所以在这种情况下那就是“这个”CameraPage。 : - )