ImageView的缩放类型意外行为

时间:2015-05-17 16:41:56

标签: android xml user-interface imageview android-5.0-lollipop

我有一个带有scaleType="fitCenter"layout_width="match_parent"的ImageView,因此我希望其中的图片可以缩放并为所有视图充气。

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dp"
    android:layout_marginTop="20dp"
    android:gravity="center"
    android:orientation="vertical">

<FrameLayout
    android:layout_width="250dp"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        android:src="@drawable/border" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:padding="6dp">

        <ImageView
            android:id="@+id/myImageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:scaleType="fitCenter"
            android:src="@drawable/aaa"
            android:transitionName="image" />

        <!-- Some other views... -->
    </RelativeLayout>
</FrameLayout>

问题在图像太小(例如,50x50像素)时开始,并且在所有设备上都无法正常工作。

下图显示了API 16和22之间的区别。

screenshot

有任何想法如何解决这个问题?

3 个答案:

答案 0 :(得分:4)

问题不在于您的代码,而在于android:adjustViewBounds的工作方式。这在ImageViewsetAdjustViewBounds方法中有记录。

  

注意:如果应用程序的目标是API级别17或更低,   adjustViewBounds将允许drawable缩小视图边界,   但在所有情况下都不会增长以填充可用的测量空间。

根据nuuneoi的帖子Correct the ImageView's adjustViewBounds behaviour on API Level 17 and below with AdjustableImageView,此问题的可能解决方案是使用自定义AdjustableImageView

<强>代码:

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;

/**
 * Created by nuuneoi on 2/17/15 AD.
 */
public class AdjustableImageView extends ImageView {

    boolean mAdjustViewBounds;

    public AdjustableImageView(Context context) {
        super(context);
    }

    public AdjustableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AdjustableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setAdjustViewBounds(boolean adjustViewBounds) {
        mAdjustViewBounds = adjustViewBounds;
        super.setAdjustViewBounds(adjustViewBounds);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Drawable mDrawable = getDrawable();
        if (mDrawable == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        if (mAdjustViewBounds) {
            int mDrawableWidth = mDrawable.getIntrinsicWidth();
            int mDrawableHeight = mDrawable.getIntrinsicHeight();
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);

            if (heightMode == MeasureSpec.EXACTLY && widthMode != MeasureSpec.EXACTLY) {
                // Fixed Height & Adjustable Width
                int height = heightSize;
                int width = height * mDrawableWidth / mDrawableHeight;
                if (isInScrollingContainer())
                    setMeasuredDimension(width, height);
                else
                    setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
            } else if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
                // Fixed Width & Adjustable Height
                int width = widthSize;
                int height = width * mDrawableHeight / mDrawableWidth;
                if (isInScrollingContainer())
                    setMeasuredDimension(width, height);
                else
                    setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
            } else {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            }
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    private boolean isInScrollingContainer() {
        ViewParent p = getParent();
        while (p != null && p instanceof ViewGroup) {
            if (((ViewGroup) p).shouldDelayChildPressedState()) {
                return true;
            }
            p = p.getParent();
        }
        return false;
    }
}

答案 1 :(得分:0)

使用body { margin: 0 0 200px; //Same height of the footer } div.content { display: table; margin: 0 auto; } div.main-content { margin: 20px 10px; text-align: left; background-color: rgba(255, 255, 255, 0.95); -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; padding: 15px; -webkit-box-shadow: 0px 4px 5px 0px rgba(0,0,0,0.75); -moz-box-shadow: 0px 4px 5px 0px rgba(0,0,0,0.75); box-shadow: 0px 4px 5px 0px rgba(0,0,0,0.75); } footer { position: absolute; left: 0; bottom: 0; height: 200px; width: 100%; overflow: auto; background-color: rgba(67, 191, 115, 0.95); } table .tab { width: 1500px; } 使用您要查找的FILL缩放图像。

答案 2 :(得分:0)

如果您使用Issue,则图片会在两个维度中填充视图,而忽略其宽高比。这无疑会造成扭曲。

另一个选项是fitXy。此缩放类型将重新缩放图像,直到尺寸x或y都大于或等于容器,同时保留纵横比。结果将在视图中居中。

centerCrop将与centerCrop相反。它缩放图像,直到至少一个维度x或y小于或等于视图。

也就是说,您在屏幕截图中显示的行为更多地与屏幕尺寸有关,而不是api级别。