ImageView无法在大屏幕设备上进行缩放

时间:2012-03-02 20:52:16

标签: android android-layout android-imageview android-2.2-froyo android-4.0-ice-cream-sandwich

这是我的基本布局:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

    <ImageView
    android:adjustViewBounds="true"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/welcome_hero" />

</LinearLayout>

我希望图像在保持纵横比适合屏幕的同时进行缩放,将任何后续视图向下推。

这对我的mdpi(LG LGP509)和hdpi(HTC G2,Nexus One)设备非常有效。但是,在我的Galaxy Nexus(xhdpi)上,图像顽固地无法缩放以适应。它在两侧留下了额外的空间。

以下是更多信息:

  • 布局位于通用布局/文件夹

  • welcome_hero.png位于drawables /文件夹中,宽度为320像素,高度为161像素

AndroidManifest.xml有这个条目:

<uses-sdk
android:targetSdkVersion="10"
android:minSdkVersion="8" />

<supports-screens
android:xlargeScreens="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="false" />

我尝试过的一些事情:

  • 将scaleType更改为fitCenter,fitInside或matrix会产生与不使用
  • 相同的结果
  • 将ImageView高度更改为fill_parent,正确缩放图像,但将所有其他视图推离屏幕
  • 用身体暴力威胁监视器让我更加沮丧
  • 明确将高度和宽度设置为320dp并且161dp未更改任何内容
  • 如上所述,我在IntelliJ的预览器和物理设备上尝试了新的布局

我已经经历了大约1.5小时的StackOverflow,现在看了几百个看起来与我类似的帖子,但似乎没有任何东西可以在Galaxy Nexus上运行。我正在拼命想成为一名优秀的开发人员并让我的东西扩展到新手机,但事实证明这很难。

4 个答案:

答案 0 :(得分:3)

使用布局标记和代码的组合进行缩放:

保持layout_width =“fill_parent”和layout_height =“wrap_content”。添加

android:scaleType="fitXY"

在您的代码中:

ImageView mImageView = findViewById (R.id.yourimageid);
LayoutParams lp = mImageView.getLayoutParams();
lp.height = (int)((float)context.getWindowManager().getDefaultDisplay().getWidth() *
    ((float)mImageView.getDrawable().getIntrinsicHeight() / (float)mImageView.getDrawable().getIntrinsicWidth()));
mImageView.setLayoutParams(lp);

即。你是通过将屏幕宽度*乘以图像高度与宽度之比来为layout_height设置一个新值。

答案 1 :(得分:3)

您可能希望将android:adjustViewBounds设置为true。保持宽度fill_parent和高度wrap_content。您可能仍然需要使用scaleType来使其按预期工作,尽管使用此方法进行扩展会非常棘手。

另一个选择是创建自己的ImageView子类。以下对我有用,但可能需要对您的具体情况进行一些修改。

public class AspectRatioImageView extends ImageView {
    private final boolean horizontal;

    public AspectRatioImageView(Context context) {
        this(context, null);
    }

    public AspectRatioImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AspectRatioImageView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        TypedArray array = context.obtainStyledAttributes(attrs,
                R.styleable.AspectRatioImageView, defStyle, 0);
        int h = array
                .getInt(R.styleable.AspectRatioImageView_fixedDimension, 0);
        horizontal = (h == 0);
        array.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        boolean widthExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
        boolean heightExactly = MeasureSpec.getMode(heightMeasureSpec) ==           MeasureSpec.EXACTLY;

        float ratio;
        try {
            ratio = ((float) ((BitmapDrawable) getDrawable())
                    .getIntrinsicWidth())
                    / ((float) ((BitmapDrawable) getDrawable())
                            .getIntrinsicHeight());
        } catch (ClassCastException e) {
            ratio = MeasureSpec.getSize(widthMeasureSpec)
                    / MeasureSpec.getSize(heightMeasureSpec);
        }

        int heightRatioSpec = MeasureSpec.makeMeasureSpec(
                (int) (MeasureSpec.getSize(widthMeasureSpec) / ratio),
                MeasureSpec.EXACTLY);   

        int widthRatioSpec = MeasureSpec.makeMeasureSpec(
                (int) (MeasureSpec.getSize(heightMeasureSpec) * ratio),
                MeasureSpec.EXACTLY);   

        if (widthExactly) {
            if (heightExactly) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            } else {
                super.onMeasure(widthMeasureSpec, heightRatioSpec);
            }
        } else {
            if (heightExactly) {
                super.onMeasure(widthRatioSpec, heightMeasureSpec);
            } else {
                if (horizontal) {
                    super.onMeasure(widthMeasureSpec, heightRatioSpec);
                } else {
                    super.onMeasure(widthRatioSpec, heightMeasureSpec);
                }
            }
        }
    }
}

您还需要添加

<declare-styleable name="AspectRatioImageView">
    <attr format="enum" name="fixedDimension">
        <enum name="horizontal" value="0" />
        <enum name="vertical" value="1" />
    </attr>
</declare-styleable>

到/values/attr.xml,这样您就可以使用app:fixedDimension=horizontal属性让它知道缩放垂直维度。

答案 2 :(得分:1)

所以你希望你的视图拉伸到与屏幕一样宽,然后在那个宽度保持原始宽高比所需的高度是什么?

我相信设置centerInside的scaleType会使这个工作。如果中心内部不起作用,中心作物值得一试。请参阅:http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

答案 3 :(得分:-1)

而不是在您的imageView android:src上使用XML,请使用android:background。这应该解决规模问题。

见这里:What is the difference between src and background of ImageView