【问题标题】:ImageView doesn't scale on large screen devicesImageView 不能在大屏幕设备上缩放
【发布时间】:2012-03-02 20:52:15
【问题描述】:

这是我的基本布局:

<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 的预览器和物理设备上都尝试了新布局

我已经浏览了 StackOverflow 大约 1.5 小时,查看了数百个与我相似的帖子,但似乎没有一个可以在 Galaxy Nexus 上运行。我正在拼命努力成为一名优秀的开发人员,并将我的东西扩展到新手机,但事实证明这很困难。

【问题讨论】:

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


    【解决方案1】:

    结合使用布局标记和代码来进行缩放:

    保留你的 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 设置一个新值。

    【讨论】:

    • mImageView.getLayoutParams() 在 onCreate 和 onStart 中都返回 null,是否应该将它放在其他地方?
    • 它必须在视图膨胀后的某个地方。在视图膨胀之前,不会设置布局参数。您应该在常规活动的 onResume 或片段中的 onCreateView 中获得非空布局参数。这个答案会起作用,但你应该能够在 xml 中得到相同的结果(然后这又是 android...)
    【解决方案2】:

    您可能希望将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 属性让它知道缩放垂直尺寸。

    【讨论】:

      【解决方案3】:

      所以您希望您的视图拉伸到与屏幕一样宽,然后在该宽度下保持原始纵横比所需的高度?

      我相信设置 centerInside 的 scaleType 将使这项工作。如果中心内部不起作用,中心裁剪值得一试。见:http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

      【讨论】:

      • 是否启用了adjustViewBounds?
      【解决方案4】:

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

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

      【讨论】:

      • 当我这样做时,图像不会保持纵横比,它只是保持相同的高度并水平拉伸。
      猜你喜欢
      • 1970-01-01
      • 2017-07-04
      • 2011-07-04
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多