视线转换后图像超出范围 [英] Image out of bounds after transformation on view

查看:86
本文介绍了视线转换后图像超出范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在显示图片时遇到问题.

I'm having a problem with displaying my image.

我有一个要全屏显示的图像.所以我有这个用match_parent和20dp填充的Imageview.

I have an Image I want to display full screen. So I have this Imageview with match_parent and 20dp padding.

它看起来不错,但是当我对其进行旋转时,视图的边界似乎没有改变,并且图像可以从屏幕上剪切掉!完全不希望那样的事情发生!我如何重新缩放图像,以使图像在旋转90度时也适合ImageView.

It looks good but when I apply rotation on it, it seems that the bounds of the view doesn't change and the image can get clipped out of the screen ! Totally don't want that to happen! How do I rescale the image so that the image also fits in the ImageView when its 90 degrees rotated.

这是我的XML,其中有旋转.

This is my XML WITH rotation in it.

如何固定图像的边界,以使文本在图像上方对齐?

How to fix the bounds of the Image so the Text is aligned just above the image?

推荐答案

在测量视图和计算缩放比例时不考虑旋转.一个可能的解决方案是自己做:

The rotation is not taken into account when measuring the view and calculating the scale ratio. A possible solution is to do it yourself :

public class RotatedImageView extends ImageView {

    ...
    constructors
    ...


    private double mRotatedWidth;
    private double mRotatedHeight;

    private boolean update() {
        Drawable d = getDrawable();

        if (d == null) {
            return false;
        }

        int drawableWidth = d.getIntrinsicWidth();
        int drawableHeight = d.getIntrinsicHeight();

        if (drawableWidth <= 0 || drawableHeight <= 0) {
            return false;
        }

        double rotationRad = getRotation() / 180 * Math.PI;

        // calculate intrinsic rotated size
        // see diagram

        mRotatedWidth = (Math.abs(Math.sin(rotationRad)) * drawableHeight
                + Math.abs(Math.cos(rotationRad)) * drawableWidth);
        mRotatedHeight = (Math.abs(Math.cos(rotationRad)) * drawableHeight
                + Math.abs(Math.sin(rotationRad)) * drawableWidth);

        return true;
    }


    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        if (update()) {
            double ratio = mRotatedWidth / mRotatedHeight;

            int wMax = Math.min(getDefaultSize(Integer.MAX_VALUE, widthMeasureSpec), getMaxWidth());
            int hMax = Math.min(getDefaultSize(Integer.MAX_VALUE, heightMeasureSpec), getMaxHeight());

            int w = (int) Math.min(wMax, hMax * ratio);
            int h = (int) Math.min(hMax, wMax / ratio);

            setMeasuredDimension(w, h);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }

    }

    private final float[] values = new float[9];

    protected void onDraw(Canvas canvas) {

        if (update()) {
            int availableWidth = getMeasuredWidth();
            int availableHeight = getMeasuredHeight();

            float scale = (float) Math.min(availableWidth / mRotatedWidth, availableHeight / mRotatedHeight);

            getImageMatrix().getValues(values);

            setScaleX(scale / values[Matrix.MSCALE_X]);
            setScaleY(scale / values[Matrix.MSCALE_Y]);
        }

        super.onDraw(canvas);
    }

    @Override
    public void setRotation(float rotation) {
        super.setRotation(rotation);
        requestLayout();
    }
}

adjustViewBounds必须为true:

<com.mypackage.RotatedImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="20dp"
    android:adjustViewBounds="true"
    android:rotation="90"
    android:maxWidth="100dp"
    android:maxHeight="100dp"
    android:scaleType="fitCenter"
    android:src="@drawable/test" />

有关计算的一个很好的解释,由

A nice explanation of the calculation, courtesy of Cheticamp :

更新:现在尝试调整边界. wrap_contentmatch_parent之间没有区别(根据图像方面,两者都尽可能增大).您应该改用maxWidth和/或maxHeight,或将其放在大小为0且重量为LinearLayoutLinearLayout中.

UPDATE: Now trying to adjust the bounds. There is no difference between wrap_content and match_parent (both grow as much as possible, based on the image aspect). You should instead use maxWidth and / or maxHeight, or put it in a LinearLayout with a 0 size and a weight.

它也不是可动画的,在动画时调整边界需要对每一帧进行布局遍历,这是非常低效的.请参见其他答案,以了解可与View.animate()

It is also not animatable, adjusting bounds while animating requires a layout pass for each frame, which is very inefficient. See the other answer for a version usable with View.animate()

这篇关于视线转换后图像超出范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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