ImageView-是否具有高度匹配的宽度?


166

我有一个imageview。我希望它的宽度为fill_parent。我希望它的高度等于宽度最终的大小。例如:

<ImageView
  android:layout_width="fill_parent"
  android:layout_height="whatever the width ends up being" />

不必创建自己的视图类就可以在布局文件中实现类似的功能吗?

谢谢


你知道怎么做吗?我假设您希望长宽比保持不变。这些答案大多数都假设您希望图像为正方形。
亚当,

@Joe Blow这是一个非常糟糕的方法
侵略者

Answers:


170

更新:2017年9月14日

根据下面的评论,自Android支持库26.0.0起,不支持百分比支持库。这是新方法:

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1" />

</android.support.constraint.ConstraintLayout>

这里

不推荐使用:

根据Android开发人员的这篇文章,您现在要做的就是将所需的内容包装在PercentRelativeLayout或PercentFrameLayout中,然后指定其比率,如下所示

<android.support.percent.PercentRelativeLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        app:layout_widthPercent="100%"
        app:layout_aspectRatio="100%"/>

</android.support.percent.PercentRelativeLayout>

8
该答案的链接提供了Google提供的最精美的解决方案。就我而言,无论原始图像的宽高比是多少,我都希望图像以16:9的比例显示。效果很好。谢谢!
LETs 2016年

IM我的情况下,解决方案,例如这一个没有工作,这个人做!
Gooey

5
不要忘记在您的依赖项中添加“ compile com.android.support:percent:23.3.0”
Milad Faridnia,2016年

看起来这种方法在WrappedViewPager上存在问题,后者根据其子内容计算高度。来源WrappedViewPager类似gist.github.com/egslava/589b82a6add9c816a007

1
自Android支持库26.0.0起,不推荐使用Percent Support模块。来源:developer.android.com/topic/libraries/support-library/…–
MHogge

97

也许这会回答您的问题:

<ImageView
    android:id="@+id/cover_image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true" />

您可以忽略scaleType此特定情况的属性。


12
是的,这没用
Fattie

4
这并不是不必要的。这对我的使用效果很好,标题栏上有一个图标,我想缩放以填充高度,同时保持正方形。
Anubian Noob 2015年

3
也解决了我的问题。
Dielson Sales 2015年

最简单的方法!这应该标记为最佳答案。
H. Farid

30

一旦知道运行时的Views宽度,就可以使用LayoutParams动态设置Views的高度。您需要使用Runnable线程才能在运行时获取Views的宽度,否则您将在未确定View宽度之前尝试设置Height,因为尚未绘制布局。

我如何解决问题的示例:

final FrameLayout mFrame = (FrameLayout) findViewById(R.id.frame_id);

    mFrame.post(new Runnable() {

        @Override
        public void run() {
            RelativeLayout.LayoutParams mParams;
            mParams = (RelativeLayout.LayoutParams) mFrame.getLayoutParams();
            mParams.height = mFrame.getWidth();
            mFrame.setLayoutParams(mParams);
            mFrame.postInvalidate();
        }
    });

LayoutParams必须是您的视图所在的父视图的类型。我的FrameLayout在xml文件的RelativeLayout内部。

    mFrame.postInvalidate();

被调用以强制视图在与UI线程不同的单独线程上重绘


4
很棒的答案,特别是与Runnable一起,谢谢!
jesses.co.tt 2014年

1
尽管这可行,但并不理想。在后期运行意味着视图在布局更改之前呈现一次。在正确绘制之前,可以允许以错误的高度闪烁内容。最好早点解决。最早可能要解决的问题是在习俗中onMeasure,如瑞吉斯的回答所示。Matt的答案GridView是一种替代方法,但仅适用于通过适配器(例如在内部)呈现的视图。
ToolmakerSteve

1
很好,它仅requestLayout()在设置参数后调用后才对我有用。为什么会这样呢?
Divins Mathew

mFrame.postInvalidate(); 是这样做的,没有它,我的视线就错了。
Jacolack

17

我无法获得David Chu的答案来为RecyclerView项目工作,并且发现我需要将ImageView约束到父对象。将ImageView的宽度设置为,0dp并将其起点和终点约束到父级。我不确定在某些情况下是否将width设置为wrap_contentmatch_parent有效,但是我认为这是使ConstraintLayout的子项填充其父项的更好方法。

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintDimensionRatio="1:1"/>

</android.support.constraint.ConstraintLayout>

13

在这里,我做了一个具有始终等于其高度的宽度的ImageButton的操作(并避免在一个方向上出现愚蠢的空白边距...我认为这是SDK的错误...):

我定义了一个从ImageButton扩展的SquareImageButton类:

package com.myproject;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageButton;

    public class SquareImageButton extends ImageButton {

        public SquareImageButton(Context context) {
        super(context);


        // TODO Auto-generated constructor stub
    }

    public SquareImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub

    }

    public SquareImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub

    }

    int squareDim = 1000000000;

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


        int h = this.getMeasuredHeight();
        int w = this.getMeasuredWidth();
        int curSquareDim = Math.min(w, h);
        // Inside a viewholder or other grid element,
        // with dynamically added content that is not in the XML,
        // height may be 0.
        // In that case, use the other dimension.
        if (curSquareDim == 0)
            curSquareDim = Math.max(w, h);

        if(curSquareDim < squareDim)
        {
            squareDim = curSquareDim;
        }

        Log.d("MyApp", "h "+h+"w "+w+"squareDim "+squareDim);


        setMeasuredDimension(squareDim, squareDim);

    }

}

这是我的xml:

<com.myproject.SquareImageButton
            android:id="@+id/speakButton"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:scaleType="centerInside"
            android:src="@drawable/icon_rounded_no_shadow_144px"
            android:background="#00ff00"
            android:layout_alignTop="@+id/searchEditText"
            android:layout_alignBottom="@+id/searchEditText"
            android:layout_alignParentLeft="true"
           />

奇迹般有效 !


是的,这是最好的答案。(也是唯一一个与OPs问题完全匹配的问题)
Twometer

6

在Android 26.0.0中,不建议使用PercentRelativeLayout

解决此问题的最佳方法是ConstraintLayout这样的:

<android.support.constraint.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

    <ImageView android:layout_width="match_parent"
               android:layout_height="0dp"
               android:scaleType="centerCrop"
               android:src="@drawable/you_image"                       
               app:layout_constraintDimensionRatio="1:1"/>


</android.support.constraint.ConstraintLayout>


这是有关如何添加到项目中的教程ConstraintLayout


6

如果图像视图在约束布局内,则可以使用以下约束来创建正方形图像视图

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:id="@+id/ivImageView"
    app:layout_constraintDimensionRatio="W,1:1"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"/>

5

我试过了,仅靠布局是无法做到的。我最终编写了一个非常简单的类来处理它,您可以在github上查看它。SquareImage.java它是一个较大项目的一部分,但一点点复制和粘贴都无法解决(在Apache 2.0下获得许可)

本质上,您只需要将高度/宽度设置为等于其他尺寸(取决于您要缩放的方式)

注意:您可以使用scaleType属性将其设置为正方形,而无需使用自定义类,但视图的边界会超出可见图像的范围,如果在其附近放置其他视图,则会使其成为问题。


3

要将ImageView设置为屏幕的一半,您需要在ImageView的XML中添加以下内容:

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:scaleType="fitXY"
    android:adjustViewBounds="true"/>

然后将高度设置为等于该宽度,您需要在代码中进行设置。在适配器的getView方法中GridView,将ImageView高度设置为等于其测量的宽度:

mImageView.getLayoutParams().height = mImageView.getMeasuredWidth();

3

对于现在过世的人们,在2017年,实现您想要的新的最佳方法是使用ConstraintLayout,如下所示:

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scaleType="centerCrop"
    app:layout_constraintDimensionRatio="1:1" />

并且不要忘记根据布局需要将约束添加到所有四个方向。

使用ConstraintLayout构建响应式UI

此外,到目前为止,PercentRelativeLayout已被弃用(请参阅Android文档)。


1

这是我解决该问题的方法:

int pHeight =  picture.getHeight();
int pWidth = picture.getWidth();
int vWidth = preview.getWidth();
preview.getLayoutParams().height = (int)(vWidth*((double)pHeight/pWidth));

预览-imageView的宽度设置为“ match_parent”,scaleType设置为“ cropCenter”

图片-要在imageView src中设置的位图对象。

对我来说这很好。


您尚未说明此代码必须放在何处。您也没有解释您为什么这样做,= vw*ph/pw而不是更简单= vw。(我认为您这样做是为了保留源图像的长宽比,而不是强制进行正方形预览。)
ToolmakerSteve

0

我认为您无法在XML布局文件中进行任何操作,并且我认为android:scaleType属性不会像您希望的那样工作。
唯一的方法是以编程方式执行此操作。您可以将宽度设置为fill_parent,可以将屏幕宽度作为的高度,View也可以使用View.getWidth()方法。


0

ImageView的“ scaleType”功能可以在这里为您提供帮助。

此代码将保持宽高比并将图像放置在顶部:

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitStart"

这是一篇很棒的文章,展示了使用scaleType带来的可能性和外观。

ImageView scaleType示例


“ scaleType”在这里没有帮助。目标是使ImageView本身始终是正方形的,而不仅仅是内部的图像。使用scaleType,ImageView可能大于图像。
ToolmakerSteve

0

我确实喜欢这样-

layout.setMinimumHeight(layout.getWidth());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.