双指缩放 ImageView - 想要将整个图像缩放到超出屏幕大小

Pinch zoom ImageView - Want to scale whole image beyond size of screen

我对图像进行了缩放,但是当我第一次加载应用程序时,整个图像不可见,只有一部分。图像填满了屏幕的宽度,但在其上方和下方有白色-space。此外,当缩放图像时,图像会变得非常短。宽高比应保持不变。

我想在应用程序加载时让整个图像可见,然后我希望能够用两根手指缩小图像不会变得小于屏幕尺寸,这样屏幕总是满满的(图片是一张地图)。

要放大,图像的缩放比例应超出 phone 屏幕的宽度和高度。这样我就可以平移以详细查看地图。

如有任何帮助,我们将不胜感激。相关代码如下。

我的 MainActivity 代码:

public class MainActivity extends Activity
{
    private MapView image;
    private Matrix matrix = new Matrix();

    float mLastTouchX, mPosX;
    float mLastTouchY, mPosY;

    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1f;

    private int mActivePointerId = MotionEvent.INVALID_POINTER_ID;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        image = (MapView)findViewById(R.id.imageView1);
        mScaleDetector = new ScaleGestureDetector(MainActivity.this, new ScaleListener());
    }

    public void onDraw(Canvas canvas)
    {
        canvas.save();

        canvas.scale(mScaleFactor, mScaleFactor);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings)
        {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }



    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        mScaleDetector.onTouchEvent(event);

        final int action = MotionEventCompat.getActionMasked(event);

        switch (action)
        {
            case MotionEvent.ACTION_DOWN:
            {
                final int pointerIndex = MotionEventCompat.getActionIndex(event);
                final float x = MotionEventCompat.getX(event, pointerIndex);
                final float y = MotionEventCompat.getY(event, pointerIndex);

                // Remember where we started (for dragging)
                mLastTouchX = x;
                mLastTouchY = y;
                // Save the ID of this pointer (for dragging)
                mActivePointerId = MotionEventCompat.getPointerId(event, 0);
                break;
            }

            case MotionEvent.ACTION_MOVE:
            {
                // Find the index of the active pointer and fetch its position
                final int pointerIndex =
                        MotionEventCompat.findPointerIndex(event, mActivePointerId);

                final float x = MotionEventCompat.getX(event, pointerIndex);
                final float y = MotionEventCompat.getY(event, pointerIndex);

                // Calculate the distance moved
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;

                mPosX += dx;
                mPosY += dy;

                // Remember this touch position for the next move event
                mLastTouchX = x;
                mLastTouchY = y;

                break;
            }

            case MotionEvent.ACTION_UP:
            {
                mActivePointerId = MotionEvent.INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_CANCEL:
            {
                mActivePointerId = MotionEvent.INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_POINTER_UP:
            {
                final int pointerIndex = MotionEventCompat.getActionIndex(event);
                final int pointerId = MotionEventCompat.getPointerId(event, pointerIndex);

                if (pointerId == mActivePointerId)
                {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastTouchX = MotionEventCompat.getX(event, newPointerIndex);
                    mLastTouchY = MotionEventCompat.getY(event, newPointerIndex);
                    mActivePointerId = MotionEventCompat.getPointerId(event, newPointerIndex);
                }
                break;
            }
        }

        image.setX(mPosX);
        image.setY(mPosY);

        return true;
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
    {
        @Override
        public boolean onScale(ScaleGestureDetector detector)
        {
            mScaleFactor *= detector.getScaleFactor();
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

            matrix.setScale(mScaleFactor, mScaleFactor);
            image.setImageMatrix(matrix);

            return true;
        }
    }
}

自定义 ImageView:

public class MapView extends ImageView
{
    public MapView(final Context context, final AttributeSet attrs)
    {
        super(context, attrs);
    }

    public void scaleImage(int boundBoxInDp)
    {
        Drawable drawable = getDrawable();
        Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();

        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        float xScale = ((float) boundBoxInDp) / width;
        float yScale = ((float) boundBoxInDp) / height;
        float scale = (xScale <= yScale) ? xScale : yScale;

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);

        Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        BitmapDrawable result = new BitmapDrawable(scaledBitmap);
        width = scaledBitmap.getWidth();
        height = scaledBitmap.getHeight();

        // Apply the scaled bitmap
        setImageDrawable(result);

        // Now change ImageView's dimensions to match the scaled image
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)getLayoutParams();
        params.width = width;
        params.height = height;
        setLayoutParams(params);
    }

    private int dpToPx(Context c, int dp)
    {
        float density = c.getResources().getDisplayMetrics().density;
        return Math.round((float)dp * density);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
    {
        final Drawable d = this.getDrawable();

        if (d != null)
        {
            // ceil not round - avoid thin vertical gaps along the left/right edges
            final int width = MeasureSpec.getSize(widthMeasureSpec);
            final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
            this.setMeasuredDimension(width, height);
        }
        else
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">

    <com.kilobolt.framework.locationfinder.MapView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="matrix"
        android:src="@drawable/uea" />

</RelativeLayout>

我采用了不同的方法来解决显示自定义地图的问题。我没有显示固定大小的图像,而是使用 Google Maps Javascript API v3 (https://developers.google.com/maps/documentation/javascript/examples/marker-simple).

我在网络视图中显示了它,并在 javascript 中创建了一个可重复使用的函数来创建自定义标记。

如果有人遇到这个似乎没有很好记录的问题,请试试这个地图解决方案,并随时给我发消息。希望这有帮助。