Android setFocusArea and Auto Focus

后端 未结 5 1186
余生分开走
余生分开走 2020-12-02 07:34

I\'ve been battling with this feature for couple of days now...

It seems, that camera is ignoring(?) focus areas that I\'ve defined. Here is snippets of the code:

5条回答
  •  天命终不由人
    2020-12-02 08:05

    My problem was much simpler :)

    All I had to do is cancel previously called autofocus. Basically the correct order of actions is this:

    protected void focusOnTouch(MotionEvent event) {
        if (camera != null) {
    
            camera.cancelAutoFocus();
            Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f);
            Rect meteringRect = calculateTapArea(event.getX(), event.getY(), 1.5f);
    
            Parameters parameters = camera.getParameters();
            parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
            parameters.setFocusAreas(Lists.newArrayList(new Camera.Area(focusRect, 1000)));
    
            if (meteringAreaSupported) {
                parameters.setMeteringAreas(Lists.newArrayList(new Camera.Area(meteringRect, 1000)));
            }
    
            camera.setParameters(parameters);
            camera.autoFocus(this);
        }
    }
    

    Update

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        ...
        Parameters p = camera.getParameters();
        if (p.getMaxNumMeteringAreas() > 0) {
           this.meteringAreaSupported = true;
        }
        ...
    }
    
    /**
     * Convert touch position x:y to {@link Camera.Area} position -1000:-1000 to 1000:1000.
     */
    private Rect calculateTapArea(float x, float y, float coefficient) {
        int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();
    
        int left = clamp((int) x - areaSize / 2, 0, getSurfaceView().getWidth() - areaSize);
        int top = clamp((int) y - areaSize / 2, 0, getSurfaceView().getHeight() - areaSize);
    
        RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
        matrix.mapRect(rectF);
    
        return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), 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;
    }
    

提交回复
热议问题