【问题标题】:Make TextView as wide as possible without crowding out other views在不挤占其他视图的情况下使 TextView 尽可能宽
【发布时间】:2014-12-12 04:23:19
【问题描述】:

我希望在我的应用中进行以下布局处理:

如您所见,文本可以尽可能宽,而不会将出现在其右侧的其他视图推离屏幕,并根据需要进行省略。色样永远不会超过 3 个,并且不得少于 1 个,并且所有色样和圆圈中的 x 必须始终可见。 当文本很短时,它的行为应该与最后 2 行(蕨类植物)中看到的一样

我尝试将文本和图像放在LinearLayout 中,但是当文本太长时,图像不可见(或不完全可见)。我认为有某种方法可以表明图像应始终占用所需的空间,TextView 占用其余空间或所需空间,但我似乎无法弄清楚如何。我不知道RelativeLayout 是否会更好地解决这个问题,或者TableLayout/TableRowGridLayout,尽管我读过的任何内容似乎都没有涵盖这种情况。

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

<TextView
    android:id="@+id/plant_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:maxLines="1"
    android:singleLine="true"
    android:ellipsize="end"
    android:layout_marginRight="3dp"/>

<LinearLayout
    android:id="@+id/color_0"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="2dp"
    android:layout_marginRight="2dp">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/btn_remove_plant"
        android:visibility="invisible"/>
</LinearLayout>

<LinearLayout
    android:id="@+id/color_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="2dp"
    android:layout_marginRight="2dp"
    android:visibility="gone">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/btn_remove_plant"
        android:visibility="invisible"/>
</LinearLayout>

<LinearLayout
    android:id="@+id/color_2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="2dp"
    android:layout_marginRight="2dp"
    android:visibility="gone">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/btn_remove_plant"
        android:visibility="invisible"/>
</LinearLayout>

<ImageView
    android:id="@+id/remove_plant"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/btn_remove_plant"
    android:layout_marginLeft="3dp"/>

</LinearLayout>

【问题讨论】:

  • @TimCastelijns 我明白了。我忽略了这一点。
  • 您可以使用RelativeLayout,从右侧开始,随着您的视图向左移动。首先调用 layout_alignParentRight="true",然后为以下每个视图调用 layout_toLeftOf="@id/id_of_view_to_the_right"。对于最后一个视图,使宽度 match_parent 并将布局设置为最终颜色视图的左侧。
  • @zgc7009 你将如何处理最右边的视图未锚定到右边缘的底部 2 行?
  • @TimCastelijns 误读了这个问题,认为问题在于最后两个应该看起来像其余的(除了文本之外的所有内容)。
  • 这是 ListView 还是固定布局?

标签: android android-layout


【解决方案1】:

这是一个工作布局。正在发生的两件事。一,行使用LinearLayoutlayout_width="wrap_content"。这可以防止LinearLayout 扩展到其内容之外,使所有内容保持对齐(您的底部两个示例)。二,TextView 使用android:layout_weight="1"android:layout_width="0dp" 告诉LinearLayout 它应该扩展这个TextView 以填充剩余的可用空间但不推出其他视图(你的前三个例子)。注意:这并不是layout_weight 所做的全部,只是它在这种情况下正在做的事情。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

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

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ellipsize="end"
            android:lines="1"
            android:text="This is a long line of text and is testing something. This is a long line of text and is testing something. This is a long line of text and is testing something." />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#F00" />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#0F0" />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#00F" />

        <Button
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp" />
    </LinearLayout>

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

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ellipsize="end"
            android:lines="1"
            android:text="This is a long line of text and is testing something. This is a long line of text and is testing something. This is a long line of text and is testing something." />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#F00" />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#0F0" />

        <Button
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp" />
    </LinearLayout>


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

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ellipsize="end"
            android:lines="1"
            android:text="This is some line of text." />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#F00" />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#00F" />

        <Button
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp" />
    </LinearLayout>

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

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ellipsize="end"
            android:lines="1"
            android:text="This is short" />

        <View
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:background="#F00" />

        <Button
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp" />
    </LinearLayout>

</LinearLayout>

【讨论】:

  • 具有长名称的行有效,但我看到图像对于具有短名称的行是正确的。我确实将水平 LinearLayout 上的 layout_width 更改为 wrap_content,但没有骰子(这样做很有意义)。我在您的示例中看到的与我所看到的 1 个不同之处在于您的其他视图的宽度是固定大小的。我也对此进行了实验,但没有发现任何区别。顺便说一句,我以前使用过 layout_weight ,但我很惊讶它在这里做了什么。 (似乎将一个视图设置为 1 而在其他视图上根本不设置,如果有的话,会让事情变得更糟......)
  • 我可能不得不接受正确对齐的图像,这真的没什么大不了的。关键是现在当文本很长时会显示尽可能多的文本(我猜这也可以通过切换到RelativeLayout来完成,正如其他人指出的那样)。谢谢。
  • 我有点惊讶于让某些东西工作起来有多么困难。 wrap_content 与 match_parent 与 layout_weight 的交互很有趣。
  • 欢迎来到 Android,总是很难让某些东西工作:-)
【解决方案2】:

此代码为您提供以 dp 和像素为单位的屏幕尺寸。将图像设置为您喜欢的固定尺寸,例如 30dp 或 Math.min(screenWidth,screenHeight)/100 以相对于显示尺寸进行设置。 之后,因为您知道将显示多少图像,所以从总 screenWidth 中提取 (number of images) * imageSize 并将其设置为 textview 宽度

WindowManager wm2 = (WindowManager) con.getSystemService(Context.WINDOW_SERVICE);
Display display = wm2.getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();   display.getMetrics(outMetrics);
float density  = getResources().getDisplayMetrics().density;
dpHeight  = (int) (outMetrics.heightPixels / density); 
dpWidth  = (int) (outMetrics.widthPixels / density);
screenWidth=outMetrics.widthPixels; 
screenHeight=outMetrics.heightPixels;

这是您以编程方式设置文本视图宽度的方式

LinearLayout.LayoutParams params=(LinearLayout.LayoutParams)textView.getLayoutParams();
params.width=/calculated size/; 
textView.setLayoutParams(params);

【讨论】:

  • 谢谢。我宁愿尝试测量图像尺寸而不是将它们设置为固定尺寸,因为后者似乎有点冒险和hacky,即使尺寸相对于屏幕尺寸也是如此。不过,根据我的经验,在 Android 中测量视图大小通常是一个挑战。另一个问题是我不想将所有剩余空间分配给 TextView:在我的示例的最后 2 行中,我只希望它根据需要使用尽可能多的空间,然后让图像立即位于其右侧.不过,我也许可以先检查文本的长度,然后做一些条件格式。
  • 1) 我提到了图像尺寸相对于显示尺寸的选项。您可以将其设置为固定数量的 dp,正如我已经在代码 sn-p 中向您展示的那样。 2)这种方法的重点是限制文本视图的宽度,以防它推出图像。否则你不必设置任何东西。所以.. if(textview_width> space_left){limit_textview_width()}
  • 我更关心的是通常将 TextView 设置为固定大小,相对于屏幕大小与否,因为我的偏好是让 Android 处理大小调整,尽管这绝对是一个选项。我可能会尝试按照您的建议进行操作,或者将图像放在 LinearLayout 中,尝试对其进行测量,然后按照您在上一条评论的第二部分中的建议进行操作。不过,我真的希望 Android 的一种布局(或组合)能让我完成我想做的事情。
  • 另外,“if(textview_width&gt;...”需要测量 TextView,因此测量视图仍然存在挑战(尽管这是可行的)。
【解决方案3】:

当文本很短时,它的行为应该与最后 2 行(蕨类植物)中看到的一样。

我不认为标准布局会给你想要的东西。我的猜测是您必须创建一个自定义的ViewGroup 来满足您的要求。 Qberticus 的实现可能与您使用开箱即用的布局一样接近。

话虽如此,我不能排除 GridLayout 能够以某种方式完成此任务。

就我个人而言,我会选择TableLayout,其中四列用于颜色样本和 X 图标,第五列用于文本。您可以动态构造表格行以使文本填充不会被色板使用的列,并且您可以使用android:strechColums="0" 将所有额外空间分配给文本所在的最左侧列。与 Qberticus 的方法一样,这会为您提供右对齐的样本和图标,恕我直言,这是一个更好的 UI。

如果您对右对齐色板和图标的担忧是文本和色板/图标之间存在空白间隙,请使文本具有正确的gravity(或end,如果您支持 RTL 语言)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-09
    • 2020-03-14
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多