使用'layout_weight'和'maxWidth'创建灵活的水平布局

6
我有一个TextView和一个正方形ImageView,我想在水平线性布局中显示它们。每个应该占据父视图宽度的一半,并且高度应适合内容(即图片)。文本应该垂直居中。
额外的限制是图像不应超过给定的maxWidth(= maxHeight),超出的宽度应该提供给TextView。显然,这与上面的50/50规则冲突。是否有一种方法可以优先考虑约束条件,即允许图像占据空间的一半,除非它超出了给定的大小?

desired outcome

这些是我尝试过的布局:
第一个布局能够很好地将左侧部分拉伸到可用空间。但是,由于图像的layout_weight未指定(如下图所示),因此图像占据了超过一半的宽度。
<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Some text."/>
    </LinearLayout>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxWidth="200dp"
        android:adjustViewBounds="true"
        android:src="@drawable/image" />
</LinearLayout>

without <code>layout_weight</code>

当我给ImageView添加layout_weight属性时,它总是占据一半的宽度并忽略maxWidth属性(见下图)。
    <ImageView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:maxWidth="200dp"
        android:adjustViewBounds="true"
        android:src="@drawable/image" />

with <code>layout_weight</code>

ImageView包含在另一个LinearLayout中可以再次启用maxWidth,但是包含的LinearLayout仍然占用可用空间的一半(请参见下面的图像)。

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="right">

        <ImageView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:maxWidth="200dp"
            android:adjustViewBounds="true"
            android:src="@drawable/image" />
    </LinearLayout>

using enclosing <code>LinearLayout</code>

我发现类似情况的另一个选择是使用RelativeLayout,并将一个不可见视图作为中心分隔器,但这将锁定分割线为50/50(或分隔器所在位置)。

TextView 填充另一个屏幕很容易,但是当每个 ViewTextView 和 ImageView)占据父级宽度的一半时,就会出现冲突条件,这使得情况变得困难。 - AL.
3个回答

2

好的,我要继续发布我创建的XML,它非常简单,可以满足大多数条件... 我遇到的一个问题是每个视图占用父视图宽度的一半。希望这仍然能在某种程度上帮助您。

sample_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="2dp"
    android:background="@android:color/darker_gray">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/img_sample"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="2dp"
        android:layout_toLeftOf="@id/img_sample"
        android:background="@color/colorPrimary"
        android:gravity="center_vertical"
        android:text="Some text." />

    <ImageView
        android:id="@id/img_sample"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="2dp"
        android:adjustViewBounds="true"
        android:maxWidth="200dp"
        android:src="@drawable/sample_img" />

</RelativeLayout>

这里是一个示例截图: 输入图像描述

如果你找到了如何处理每个部分的一半的方法,请在此处评论,这对于可能的将来使用会很有帮助。:)

PS:您考虑过以编程方式实现每个部分的一半吗?比如检查LayoutParams,然后动态设置weightSumlayout_weight

示例图像从此处检索链接


1
感谢您的努力和精彩的说明。您成功地简化了我的第一个示例并得到相同的结果,让我可以直接应用它。但是,正如您所指出的那样,它并不完全符合要求。我现在解决此问题的方法是通过为横向和纵向创建不同的视图来避免问题。当然,这也可以通过编程实现。也许我期望过高了。 :) - user3386180
1
除非有人提出一种使用XML的方法来完成这个任务,否则我认为通过编程处理是正确的答案:如果容器的宽度超过两倍的maxWidth,则设置ImageViewlayout_weight。在我打勾之前,我会再给它几天时间。 - user3386180
1
@jerry 不用担心。祝你好运。 :) 尽可能地,我也想看到仅通过xml实现的实现,也许将来可以用到它。 :D - AL.
1
将其标记为答案,以简化原始布局并得出最后一位可能确实需要以编程方式完成的结论。或者 - 如在我的特定情况下 - 为不同屏幕方向创建单独的布局。 - user3386180

0
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <ImageView
        android:id="@id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentTop="true"
        android:layout_weight="1"
        android:adjustViewBounds="true"
        android:background="@color/blue"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_margin="5dp"
        android:layout_toStartOf="@id/imageView"
        android:background="@color/colorPrimary"
        android:padding="10dp"
        android:text="Some text. " />
</RelativeLayout>

Here's what it looks like


嗯,但实际上只有一种情况。布局应该适应父视图的宽度。 - user3386180
尝试使用RelativeLayout作为父布局,然后为您的ImageView设置layout_weight=1,alignparentRight=true。 - shibapoo
我最初使用相对布局以及隐藏的分割视图View,就像我链接到的答案所描述的一样。这给了我几乎与我的第三次尝试相同的结果。我从那里开始,现在删除了分隔符,并应用了 Layout_weight=1alignParentRight=true。可能还有其他问题,但是现在图片几乎占据了整个宽度,在两侧具有相等的边距,覆盖了文本。大小可能受到图片本身大小的限制。 - user3386180
一个替代方案(也是我目前正在做的)在某种程度上与你在答案中所说的有关。主要是我想解决纵向和横向视图的问题。由于我无法轻松地找到一种动态适应单个布局的方法,所以有点沮丧。因此,最终我为两种方向定义了不同的布局。幸运的是,这对于Android来说非常容易。 - user3386180
抱歉,我错过了那个更新。尝试过了但是不起作用。我怀疑当图像定义了layout_weight时,这里缺少的maxWidth属性会被忽略。 - user3386180
你的截图看起来不一样,可能是因为你使用了一个较小的图像? - user3386180

0

从性能方面来看,这不会是一个完美的解决方案。但是您可以通过使用FrameLayout和ImageView来实现它。

以下是输出结果: 在此输入图片描述在此输入图片描述

Layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/textGray"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/skyBlue">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <FrameLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="@android:color/white">

                <ImageView
                    android:id="@+id/imageView4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:maxWidth="200dp"
                    android:src="@drawable/ic_settings"
                    android:visibility="invisible" />

                <TextView
                    android:id="@+id/TextView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="center"
                    android:text="!" />
            </FrameLayout>

            <ImageView
                android:id="@+id/imageView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:maxWidth="200dp"
                android:src="@drawable/ic_settings" />
        </LinearLayout>
    </FrameLayout>
</LinearLayout>

为了实现所需的行为,您需要将相同的图像设置到此布局中的两个图像视图中。其中一个是不可见的,它只是帮助我们创建具有相同宽度和高度的父级,从而导致我们创建具有相同尺寸的TextView。
注意: 如果您想要更改textView的对齐方式,可以使用layout_gravity或gravity。


谢谢。这是一个有趣的方法。我直接将您的代码放入我的视图中 - 只更改了颜色和图像名称。存在两个问题:1. 当有空间时,文本部分不会扩展(它应该占用超过50%)。2. 使用较大的图像时,整个组的高度由源图像大小设置,而每侧的宽度仍为50%。 - user3386180
  1. 你可以通过调整TextView及其父视图的重力来实现该行为。
  2. 我们正在使用maxWidth=200dp来设置ImageView的宽度。如果您添加maxHeight的值,它将不会扩展到完整的高度。
- Ahmad Raza
@jerry:这个示例可以让你了解如何实现所需的功能。我建议你尝试操作并根据需要进行修改。愉快编码 :) - Ahmad Raza
谢谢。在这个布局中,maxWidthmaxHeight没有任何影响。所以我不太确定,但我会继续尝试。 :) - user3386180
请注意:在此布局中,您需要设置两个imageView的maxWidth和maxHeight,否则它将无法正常工作。 - Ahmad Raza
发现这里实际缺少的是 adjustViewBounds="true"。添加后,最大尺寸就能正常工作了。不过,layout-weight 修复了分割为50/50的问题。 - user3386180

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接