Android SurfaceView預覽變形完美解決

轉(zhuǎn)載請注明出處:http://www.itdecent.cn/p/0ea58e77ef57
這個問題百度上一搜一大把,基本上都是說找到和SurfaceView的比例相近的camera預覽尺寸,但是發(fā)現(xiàn)預覽時候還是差了點意思,具體看下面這個回調(diào)就知道是為什么了。

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

從上面的回調(diào)打印的數(shù)據(jù)知道surfaceview的寬高比可能與camera設(shè)置的寬高比不一致,其實取相近的比例解決不了根本問題。
所以,對于此類的解決方法我只想說僅僅相近有神馬用。

那么既然知道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);
            }
        }
        
        ...代碼省略
    }

可以看到寬高其實就是調(diào)用的View的getHeight和getWidth或者是mRequestedWidth和mRequestedHeight。
熟悉了View的自定義就知道getHeight和getWidth都是和View的onMeasure息息相關(guān),所以想到重寫onMeasure方法。
再從源碼看到關(guān)于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(); 
    }
}

實例化的時候記得調(diào)用resize方法就好了。
注意和camera的預覽尺寸比例一致,且寬高記得傳正確,不然可能不全屏

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容