【问题标题】:Why do I need to wrap an ImageView into a FrameLayout?为什么我需要将 ImageView 包装到 FrameLayout 中?
【发布时间】:2014-08-30 07:27:35
【问题描述】:

这是一个简单的布局:

      <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/companyIcon"
                android:layout_width="wrap_content"
                android:layout_height="40dp" <!-- notice I've limited a height -->
                android:scaleType="fitStart"
                android:adjustViewBounds="true"
                android:layout_alignParentLeft="true" />

            <TextView
                android:id="@+id/companyName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/companyIcon"
                android:layout_marginLeft="3dp"
                android:layout_centerVertical="true"
                android:textStyle="bold"
                android:textColor="#20526d" />
        </RelativeLayout>

我将由setImageBitmap() 设置的图像高度超过 40dp。 使用这种布局我在ImageViewTextView 之间有一个额外的空间,它是从哪里来的?

但是在我用FrameLayout 包裹ImageView 之后,我就没有这个不必要的额外空间了:

<RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <FrameLayout
                android:id="@+id/image_container"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <ImageView
                    android:id="@+id/companyIcon"
                    android:layout_width="wrap_content"
                    android:layout_height="40dp"
                    android:scaleType="fitStart"
                    android:adjustViewBounds="true"
                    android:layout_alignParentLeft="true" />
            </FrameLayout>

            <TextView
                android:id="@+id/companyName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@id/image_container"
                android:layout_marginLeft="3dp"
                android:layout_centerVertical="true"
                android:textStyle="bold"
                android:textColor="#20526d" />
        </RelativeLayout>

结果:

你们能解释一下为什么我要将ImageView 放入FrameLayout 以达到预期效果吗?非常感谢。

【问题讨论】:

  • 您可以尝试使用 LinearLayout 而不是 Relativelayout 作为父级。很多情况下,RelativeLayout 都被证明是错误的。
  • 您必须将 android:layout_width="80dp or 100dp" 分配给您的 ImageView。不要担心您的图像不会拉伸/压缩

标签: android android-layout


【解决方案1】:

我将通过 setImageBitmap() 设置的图像高度超过 40dp。使用这个布局我在 ImageView 和 TextView 之间多了一个空间,它是从哪里来的?

由于android:layout_height="40dp"android:scaleType="fitStart",图像被缩小(向左/开始)以适应高度,所以这个“额外空间”实际上是图像的原始宽度,因为你的android:layout_width="wrap_content"。我用我自己的大于40dp 的图像重新创建了您的布局。当您选择ImageView 时,您可以看到它的边界拉伸到图像的原始宽度。

为了进一步证明这一点,如果我设置android:scaleType="center",则不应用任何拟合,您可以看到ImageView 的原始宽度。

你们能解释一下为什么我要将 ImageView 放入 FrameLayout 以达到预期的效果吗?

看来,由于您的FrameLayout 使用android:layout_width="wrap_content",因此在由于android:adjustViewBounds="true" 而缩放后,它会从您的ImageView 获得正确的缩小宽度。奇怪的是ImageView 本身使用android:layout_width="wrap_content",但显示的是原始图像的宽度,而不是缩放后的宽度。我的 预感ImageViews 的高度和宽度在应用缩放之前 被设置,所以 ImageView 获得原始图像的宽度,但父 @ 987654339@ 获取其ImageView应用缩放后的缩放宽度。这可能不是真的,但在我看来是这样的。

但是,您可以通过在ImageView 上使用android:maxHeight="40dp" 来解决未缩放的宽度问题(不使用FrameLayout)。然后您可以设置android:layout_height="wrap_content",这样您的图像可以小于40dp(如果图像较小)。

<ImageView
    android:id="@+id/companyIcon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:adjustViewBounds="true"
    android:maxHeight="40dp"
    android:scaleType="fitStart" />

【讨论】:

    【解决方案2】:

    这几乎适用于所有观点,但答案是专门考虑ImageView

    设置高度和宽度的指南

    只选择这三个选项之一。

    1. both高度和宽度设置为“WRAP_CONTENT
    2. 设置两者高度和 宽度为“FILL_PARENT
    3. both 高度和宽度设置为“FIXED SIZE

      *避免混合使用它们说Width=WRAP_CONTENT and Height=FILL_PARENT

    为 ImageView 设置 SCALETYPE 的指南

    ScaleType 有什么作用?

    它缩放您设置到 ImageView 的图像,它不缩放 ImageView 因此,当您将其设置为 fitStart 时,它将缩放您的图像并 显示在右侧,但您的 imageView 将保持不变 高度和宽度为您指定的值。

    就像您使用 WRAP_CONTENT 来表示高度和宽度一样,您不需要指定 ScaleType,因为您的 ImageView 会自动与您的图像一样大。

    就像您使用 FILL_PARENT 来显示高度和宽度一样,您可以选择在中心、开始、结束或全视图中显示图像。所以 您可以在此基础上选择您的比例类型。

    就像您使用FIXED_SIZE fpr 高度和宽度一样,您应该选择 scaletype=FITXY


    将 Image 设置为 ImageView 的指南

    就像您在 XML 中静态地设置图像一样,您手上只有一张图像,因此您可以根据您的布局设计创建您希望大小的图像,然后 继续WRAP_CONTENT

    好像你是在 runtime 从某个地方下载图像后设置图像,那个时候下载图像并创建你喜欢大小的位图,然后将其设置为 ImageView


    具体情况

    你可以看到你的图片被拉伸了,文本不可读,这是因为你已经下载并设置了图片,但高度和宽度更小了。而不是你应该这样做,

    在 XML 文件中将 ImageView 的高度和宽度设置为 WRAP_CONTENT

                        <ImageView
                        android:id="@+id/companyIcon"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_alignParentLeft="true" />
    

    下载所需尺寸的图片,例如 50X100,例如查看此代码

    class LoadPics extends AsyncTask<Void, Bitmap, Bitmap> {
        String urlStr;
        ImageView iv;
        int width, height;
    
        public LoadPics(ImageView iv, String url, int width, int height) {
            this.iv = iv;
            this.urlStr = url;
            this.width = width;
            this.height = height;
        }
    
        @Override
        protected Bitmap doInBackground(Void... params) {
            try {
                    InputStream in = null;
                    try {
                        URL url = new URL(urlStr);
                        URLConnection urlConn = url.openConnection();
                        HttpURLConnection httpConn = (HttpURLConnection) urlConn;
                        httpConn.connect();
                        in = httpConn.getInputStream();
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
                    BitmapFactory.Options o = new BitmapFactory.Options();
                    o.inJustDecodeBounds = true;
    
                    int scale = 2;
                    if (o.outHeight > width || o.outWidth > height) {
                        scale = 2 ^ (int) Math.ceil(Math.log(width
                                / (double) Math.max(o.outHeight, o.outWidth))
                                / Math.log(0.5));
                    }
    
                    if (scale <= 1 && o.outHeight > 150) {
                        scale = 5;
                    }
    
                    BitmapFactory.Options o2 = new BitmapFactory.Options();
                    o2.inSampleSize = scale;
                    Bitmap b1 = BitmapFactory.decodeStream(in, null, o2);
                    b1 = Bitmap.createScaledBitmap(b1, width, height, true);
                    loader.addToCache(urlStr, b1);
                    publishProgress(b1);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        @Override
        protected void onProgressUpdate(Bitmap... values) {
            super.onProgressUpdate(values);
            iv.setImageBitmap(values[0]);
        }
    }
    

    并使用您的参数调用此方法,

    new LoadPics(ivUser,imgURL,100,50).execute();
    

    【讨论】:

    • 说得很好,对 ImageView 的解释很好。虽然我认为真正的问题是:“为什么添加 FrameLayout 可以解决问题?”
    • 是的.. 使用 framelayout 如何正常工作.. 我无法理解.. 但这是我遵循的方式.. 所以我发布了.. @SherifelKhatib BTW 感谢 +1
    【解决方案3】:

    尝试用这个android:scaleType="fitXY" 替换android:scaleType="fitStart"


    编辑

    在您的图像视图中,您应该将 imagView 的宽度设置为 wrap-content 这将采用图像的大小。如果您硬编码 imageView's 宽度(就像您通过将宽度设置为 40dp 来完成的那样),那么这在其他 android 移动设备中看起来不会那么好。

    如果您想这样做,请尝试加载分辨率较低的图像。如果此图像的分辨率为200X100,则尝试在您的ImageView 中加载100X50 的图像

    【讨论】:

    • 如果我设置fitXY,比例不会保留,所以它会被拉伸。
    【解决方案4】:

    如果您使用android:scaleType="FIT_END",而没有FrameLayout,是否会将地铁图像放在“地铁”文本附近?我想知道,因为那里有android:layout_alignParentLeft="true"。我在想ImageView 在缩放之前的原始大小是没有FrameLayout 的布局。

    这可能并不重要,但它确实需要一些处理来缩放和调整图像的大小以达到您想要的效果。如果它对您想要做的事情是可行的,我会自己调整图像大小而不是依赖 XML。如果我想迎合多种尺寸,我会制作几种不同的布局。对于你的目的来说,这当然可能是矫枉过正,我不知道。

    【讨论】:

    • android:adjustViewBounds="true" 应该在缩放后重新调整 View 的边界,尽管看起来它并没有按照它说的那样做。
    【解决方案5】:

    第一个图像中出现了额外的空间,因为您在图像容器布局中设置了匹配父级。但第二次你在 FrameLayout 中使用了包装内容,这是图像容器。

    我建议做这些事情创建线性布局内部相对布局并应用 layout_weight 属性,因此两个视图中的比率将相同。

    【讨论】:

      【解决方案6】:

      尝试将比例类型设置为 center_inside。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-17
        • 2011-01-09
        • 2018-01-02
        • 2013-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多