PreviewFrameLayout导致方向问题

时间:2014-02-18 07:10:45

标签: java android android-layout android-camera android-orientation

我从AOSP借用了PreviewFrameLayout以保持相机的纵横比,它几乎可以工作(它几乎是全屏):

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;

public class PreviewFrameLayout extends RelativeLayout{

    static final String TAG="PreviewFrameLayout";
    public interface OnSizeChangedListener
    {
        public void onSizeChanged(int w,int h);
    }

    OnSizeChangedListener mListener;

    public void setOnSizeChangedListener(OnSizeChangedListener listener)
    {
        mListener=listener;
    }

    private double mAspectRatio;

    public PreviewFrameLayout(Context c,AttributeSet attrs)
    {
        super(c,attrs);
        setAspectRatio(4.0/3.0);
    }

    public void setAspectRatio(double ratio)
    {
        if(ratio<=0.0)
            throw new IllegalArgumentException();
        if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)
            ratio=1/ratio;
        if(mAspectRatio!=ratio)
        {
            mAspectRatio=ratio;
            requestLayout();
        }
    }

    @Override
    protected void onMeasure(int widthSpec,int heightSpec)
    {
        int previewWidth=MeasureSpec.getSize(widthSpec);
        int previewHeight=MeasureSpec.getSize(heightSpec);

        int hPadding=getPaddingLeft()+getPaddingRight();
        int vPadding=getPaddingTop()+getPaddingBottom();

        previewWidth-=hPadding;
        previewHeight-=vPadding;

        if(previewWidth>previewHeight*mAspectRatio)
            previewWidth=(int) (previewHeight*mAspectRatio+.5);
        else
            previewHeight=(int)(previewWidth/mAspectRatio+.5);
        previewWidth+=hPadding;
        previewHeight+=vPadding;
        Log.d(TAG,"Aspect ratio "+mAspectRatio);
        Log.d(TAG, "Width: "+previewWidth+" Height: "+previewHeight);
        super.onMeasure(MeasureSpec.makeMeasureSpec(previewWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(previewHeight, MeasureSpec.EXACTLY));
    }

     protected void onSizeChanged(int w,int h,int oldw,int oldh)
     {
        if(mListener!=null)
            mListener.onSizeChanged(w, h);
     }
    }

问:

将此项添加到CameraActivity而非简单FrameLayout会导致相机在landscape模式下拍摄的图像在90 degrees clockwise上旋转Galaxy Nexus {1}}。为什么会发生这种情况?如何修改PreviewFrameLayout以使用它?

#INFO
To fix the orientation I use the code:

    private void setDisplayOrientation()
    {
        Log.d(TAG, "Orientation changed fired");
        mDisplayRotation=getDisplayRotation(this);
        mDisplayOrientation=getDisplayOrientation(mDisplayRotation, CameraInfo.CAMERA_FACING_BACK);
        if(mCamera!=null)
        {   
            Log.d(TAG,"Setting camera and parameter orientation");
            mCamera.setDisplayOrientation(mDisplayOrientation);
            if(mParameters!=null)
            {
                mParameters.setRotation(mDisplayOrientation);
            }
            else
            {
                Camera.Parameters params=mCamera.getParameters();
                params.setRotation(mDisplayOrientation);
                mParameters=params;
                mCamera.setParameters(params);
            }
        }
    }

        @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    private int getDisplayOrientation(int degrees, int cameraId) {
        // See android.hardware.Camera.setDisplayOrientation for
        // documentation.
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
       //mCamera.setDisplayOrientation(result);
        return result;
    }

     private int getDisplayRotation(Activity activity) {
            int rotation = activity.getWindowManager().getDefaultDisplay()
                    .getRotation();
            switch (rotation) {
                case Surface.ROTATION_0: return 0;
                case Surface.ROTATION_90: return 90;
                case Surface.ROTATION_180: return 180;
                case Surface.ROTATION_270: return 270;
            }
            return 0;
        }

            class MyOrientationEventListener extends OrientationEventListener
    {

        @Override
        public void onOrientationChanged(int orientation)
        {
            if(orientation==ORIENTATION_UNKNOWN)
                return;
            mOrientation=roundOrientation(orientation,mOrientation);
            int orientationCompensation=getDisplayRotation(CameraActivity.this);
            if(mOrientationCompensation!=orientationCompensation)
                mOrientationCompensation=orientationCompensation;
            setOrientationIndicator(mOrientationCompensation);
        }


        public MyOrientationEventListener(Context context) {
            super(context);
        }

        public MyOrientationEventListener(Context context,int rate)
        {
            super(context,rate);
        }

        private int roundOrientation(int orientation, int orientationHistory) {
            boolean changeOrientation = false;
            final int ORIENTATION_HYSTERESIS=5;//a tolerance value above the limit
            if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
                changeOrientation = true;
            } else {
                int dist = Math.abs(orientation - orientationHistory);
                dist = Math.min(dist, 360 - dist);
                changeOrientation = (dist >= 45 +ORIENTATION_HYSTERESIS );
            }
            if (changeOrientation) {
                    return ((orientation + 45) / 90 * 90) % 360;
            }
            return orientationHistory;
        }
    }



 Among other places,the `setDisplayOrientation` is called inside the `capture` method before setting the parameters and taking a picture.

0 个答案:

没有答案