Android PhotoView在方向改变后保持缩放 [英] Android PhotoView Keep Zoom After Orientation Change

查看:184
本文介绍了Android PhotoView在方向改变后保持缩放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Chris Banes的 PhotoView 课程,以便能够放大图像并查看它,但我想这样做,以便当我改变方向时,照片仍会在更改后放大。

I am utilizing the PhotoView class by Chris Banes to be able to zoom into an image and see it, but I want to make it so that when I change the orientation, the photo will still be zoomed in after the change.

我理解如何执行此操作的基本知识,当检测到方向改变时,将调用onSaveInstanceState,所以我试图在那里保存实例,然后在调用onCreate时将其放回PhotoView。

I understand the basics of how to do this, that when an orientation change is detected, onSaveInstanceState will be called, so I'm trying to save the instance in there, and then put it back into the PhotoView when onCreate is called.

public class MainActivity extends ActionBarActivity
{
PhotoView mPhotoView;

@Override
protected void onCreate( Bundle aSavedInstanceState )
{
    super.onCreate( aSavedInstanceState );

    mPhotoView = new PhotoView(this);
    mPhotoView.setMaximumScale( 12 );
    setContentView( mPhotoView );
    mPhotoView.setImageResource( R.drawable.vm_app_icon);

    if (aSavedInstanceState != null)
    {
        RectF theRect = aSavedInstanceState.getParcelable( "Rect" );
        if ( theRect != null)
        {
            Matrix theMatrix = new Matrix();
            theMatrix.setScale( theRect.bottom, theRect.left, theRect.right, theRect.top );
            mPhotoView.setDisplayMatrix( theMatrix );

        }
    }
}

@Override
protected void onSaveInstanceState( final Bundle outState )
{
    super.onSaveInstanceState( outState );
    RectF theRect = mPhotoView.getDisplayRect();
    if (theRect != null)
    {
        outState.putParcelable( "Rect", theRect );
    }
}
}

但这不起作用。我应该在捆绑中存储什么才能应用回PhotoView来保持缩放级别?

But this doesn't work. What should I be storing in the bundle to be able to apply back to the PhotoView to keep the zoom level?

推荐答案

好吧之后比如10个小时的尝试我已经弄清楚了。

Alright after like 10 hours of trying I've figured it out.

为了保存缩放级别,我需要在Bundle中保存两个东西,Scale(缩放级别)和DisplayRect(类型为RectF)。

To save the zoom level I needed to save two things in the Bundle, the Scale (Zoom level), and the DisplayRect (of type RectF).

缩放级别 - MinScale和MaxScale之间的数字,在我的实例中介于1和16之间

Zoom Level - Number between the MinScale and MaxScale, in my instance between 1 and 16

RectF 包含四个值,由于某种原因,这些值是当前视图相对于当前屏幕方向的左上角坐标。即使它保持左上角坐标我不想围绕它旋转,我想围绕中心旋转,所以我需要找到矩形的中心然后将该值除以ScreenBase,这是一个将标准化值并使其能够转换为差异平面的值。以下是我保存它的方法:

The RectF holds four values, which for some reason are the coordinates of the Top-Left corner of the current view with respect to the current screen orientation. Even though it holds the top-left coordinates I don't want to rotate around that, I want to rotate around the center, so I need to find the center of the rect and then divide that value by the "ScreenBase" which is a value that will standardize the values and will make it able to be translated into a difference plane. Here's how I saved it:

@Override
    protected void onSaveInstanceState( final Bundle outState )
    {
        super.onSaveInstanceState( outState );

        Matrix theMatrix = mPhotoView.getDisplayMatrix();
        float[] theFloat = new float[9];
        theMatrix.getValues( theFloat );
        RectF theRect = mPhotoView.getDisplayRect();


        if (theRect != null)
        {
            if( theRect.left > ( mViewWidth / 2 ) || ( theRect.left >= 0 ) )
            {
                theRect.left = 0;
            }
            else
            {
                theRect.left = ( theRect.left - ( mViewWidth / 2 ) ) / mScreenBase;
            }

            if( theRect.top > ( mViewHeight / 2 ) || ( theRect.top >= 0 ) )
            {
                theRect.top = 0;
            }
            else
            {
                theRect.top = ( theRect.top - ( mViewHeight / 2 ) ) / mScreenBase;

            }
            outState.putParcelable( "RectF", theRect );

            outState.putFloat( "ZoomLevel", mPhotoView.getScale() );
        }
    }

然后当我们在另一边拿起它时,我们必须对数字进行大量操作,以使新屏幕空间的左上角居中于同一位置(并在出现边界问题时对其进行操作),这是我如何做到的:

Then when we pick it up on the other side, we have to do a lot of manipulation to the numbers to get the top left corner of the new screen space centered around the same place (and manipulate it if an boundary problem occurs), here's how I did it:

@Override
    protected void onCreate( final Bundle aSavedInstanceState )
    {
        super.onCreate( aSavedInstanceState );

        mPhotoView = new PhotoView( this );
        mPhotoView.setMaximumScale( 16 );
        setContentView( mPhotoView );
        mPhotoView.setImageResource( R.drawable.vm_app_icon );

        mPhotoView.getViewTreeObserver().addOnPreDrawListener( new ViewTreeObserver.OnPreDrawListener()
        {
            public boolean onPreDraw()
            {
                mPhotoView.getViewTreeObserver().removeOnPreDrawListener( this );
                mViewHeight = mPhotoView.getMeasuredHeight();
                mViewWidth = mPhotoView.getMeasuredWidth();
                Matrix theMatrix = mPhotoView.getDisplayMatrix();
                theMatrix.getValues( mBaseMatrixValues );
                mScreenBase = mBaseMatrixValues[ 0 ];
                int theWidth = mPhotoView.getWidth();
                Log.e(TAG, theWidth + "");

                if( aSavedInstanceState != null )
                {
                    float[] theFloats = new float[ 9 ];
                    float theZoom = aSavedInstanceState.getFloat( "ZoomLevel" );
                    RectF theRect = aSavedInstanceState.getParcelable( "RectF" );
                    theFloats[ 0 ] = theZoom;
                    theFloats[ 4 ] = theZoom;
                    theFloats[ 2 ] = ( theRect.left * mScreenBase ) - ( theZoom * mBaseMatrixValues[ 2 ] ) + ( mViewWidth / 2 ); //Left
                    theFloats[ 5 ] = ( theRect.top * mScreenBase ) - ( theZoom * mBaseMatrixValues[ 5 ] ) + ( mViewHeight / 2 ); //Top
                    theFloats[ 8 ] = (float) 1.0;

                    theFloats = CheckBoundaries( theZoom, theFloats, theRect );

                    theMatrix.setValues( theFloats );
                    mPhotoView.setDisplayMatrix( theMatrix ); //Sets the mSuppMatrix in the PhotoViewAttacher

                    Matrix theImageViewMatrix = mPhotoView.getDisplayMatrix(); //Gets the new mDrawMatrix
                    mPhotoView.setImageMatrix( theImageViewMatrix ); //And applies it to the PhotoView (catches out of boundaries problems)
                }
                return true;
            }
        } );
    }

        private float[] CheckBoundaries(final float aZoom, float[] aFloats, final RectF aRect )
        {
            if( aZoom == 1.0 ) //If the zoom is all the way out
            {
                aFloats[ 2 ] = 0;
                aFloats[ 5 ] = 0;
                return aFloats;
            }

            theMaxLeftValue = ( ( mViewHeight * aZoom ) - mViewWidth + ( aZoom * mBaseMatrixValues[ 2 ] ) );
            theMaxTopValue = ( ( mViewWidth * aZoom ) - mViewHeight + ( aZoom * mBaseMatrixValues[ 5 ] ) );
            if( Math.abs( aFloats[ 2 ] ) > ( theMaxLeftValue ) )
            {
                aFloats[ 2 ] = -Math.abs( theMaxLeftValue ) + 10;
            }
            else if( Math.abs( aFloats[ 2 ] ) < ( aZoom * mBaseMatrixValues[ 2 ] ) )
            {
                aFloats[ 2 ] = -( aZoom * mBaseMatrixValues[ 2 ] );
            }

            if( Math.abs( aFloats[ 5 ] ) > ( theMaxTopValue ) )
            {
                aFloats[ 5 ] = -Math.abs( theMaxTopValue ) + 10;
            }
            else if( Math.abs( aFloats[ 5 ] ) < ( aZoom * mBaseMatrixValues[ 5 ] ) )
            {
                aFloats[ 5 ] = -( aZoom * mBaseMatrixValues[ 5 ] );
            }

            if( aFloats[ 2 ] > 0 )
                aFloats[ 2 ] = -( mViewWidth / 2 );
            else if( aFloats[ 5 ] > 0 )
                aFloats[ 5 ] = -( mViewHeight / 2 );

            return aFloats;
        }

这篇关于Android PhotoView在方向改变后保持缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆