美文网首页AndroidAndroid开发Android开发
Android SurfaceView预览变形完美解决

Android SurfaceView预览变形完美解决

作者: KingVic | 来源:发表于2018-04-09 17:19 被阅读583次

    转载请注明出处:https://www.jianshu.com/p/0ea58e77ef57
    这个问题百度上一搜一大把,基本上都是说找到和SurfaceView的比例相近的camera预览尺寸,但是发现预览时候还是差了点意思,具体看下面这个回调就知道是为什么了。

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Log.i(TAG, "surfaceChanged: " + width + "  " + height);
        }
    

    从上面的回调打印的数据知道surfaceview的宽高比可能与camera设置的宽高比不一致,其实取相近的比例解决不了根本问题。
    所以,对于此类的解决方法我只想说仅仅相近有神马用。

    那么既然知道surfaceChanged的宽高就是SurfaceView的渲染宽高,那么想办法把surfaceChanged里的宽高比弄成和camera比例一样不就行了嘛,所以看SurfaceView的源码:

    protected void updateWindow(boolean force, boolean redrawNeeded) {
            ...代码省略
    
            int myWidth = mRequestedWidth;
            if (myWidth <= 0) myWidth = getWidth();
            int myHeight = mRequestedHeight;
            if (myHeight <= 0) myHeight = getHeight();
    
            ...代码省略
                
            if (creating || formatChanged || sizeChanged
                    || visibleChanged || realSizeChanged) {
                if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                        + "surfaceChanged -- format=" + mFormat
                        + " w=" + myWidth + " h=" + myHeight);
                if (callbacks == null) {
                    callbacks = getSurfaceCallbacks();
                }
                for (SurfaceHolder.Callback c : callbacks) {
                    c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
                }
            }
            
            ...代码省略
        }
    

    可以看到宽高其实就是调用的View的getHeight和getWidth或者是mRequestedWidth和mRequestedHeight。
    熟悉了View的自定义就知道getHeight和getWidth都是和View的onMeasure息息相关,所以想到重写onMeasure方法。
    再从源码看到关于mRequestedWidth和mRequestedHeight的赋值

    @Override
            public void setFixedSize(int width, int height) {
                if (mRequestedWidth != width || mRequestedHeight != height) {
                    mRequestedWidth = width;
                    mRequestedHeight = height;
                    requestLayout();
                }
            }
    

    以下是完整类代码:

    public class ResizeAbleSurfaceView extends SurfaceView {
    
        private int mWidth = -1;
        private int mHeight = -1;
    
        public ResizeAbleSurfaceView(Context context) {
            super(context);
        }
    
        public ResizeAbleSurfaceView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public ResizeAbleSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if (-1 == mWidth || -1 == mHeight) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            } else {
                setMeasuredDimension(mWidth, mHeight);
            }
        }
    
        public void resize(int width, int height) {
            mWidth = width;
            mHeight = height;
            getHolder().setFixedSize(width, height);
            requestLayout();
            invalidate(); 
        }
    }
    

    实例化的时候记得调用resize方法就好了。
    注意和camera的预览尺寸比例一致,且宽高记得传正确,不然可能不全屏

    相关文章

      网友评论

        本文标题:Android SurfaceView预览变形完美解决

        本文链接:https://www.haomeiwen.com/subject/icwihftx.html