2016-11-30 80 views
0

我正在尝试为我的相机页面实现手动对焦功能,以便用户可以点击以聚焦相机。点击以关注相机实现

我正在关注原生Android的this StackOverflow question that's currently written in Java。我一直在为我的Xamarin.Forms Android应用程序将其转换为C#。

这是我到目前为止有:

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' 匹配下放 '事件处理程序'。是否有我需要使用的特定事件处理程序?

回答

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问题。

+0

对于我的第二个问题,你能给我一个例子。我尝试了textureView.Click + = OnTouch;但'OnTouch'没有超载与委托'EventHandler'匹配。是否有我需要使用的特定事件处理程序? – Euridice01

+0

检查我编辑的答案,并尝试.. – albilaga

+0

谢谢blueboyz!这似乎工作。Castulate在CalculateTapArea()@ _ @中无效我想我必须调试它,但这意味着点击事件已注册 – Euridice01

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类型,这意味着任何实现该接口的类型,所以在本例中就是“This”CameraPage。 :-)

+0

好点!我最终还创建了一个内部类,它实现了IAutoFocusCallback接口中的OnAutoFocus方法,并在camera.AutoFocus()中创建类的实例。只需要测试它。这也会起作用,但“这个”会是做同样事情的一个更短的方法吗?哪种方法更清晰/更好的实践? – Euridice01