TextView android:ellipsize="marquee"不能按预期工作的问题

15

我在ListView中有一些自定义元素,每个元素都是一个LinearLayout中的TextView,但目前为止,如果文本过长,TextView中的文本将只显示三个点并被截断。我希望文本能够水平滚动而不是被截断。我阅读了许多有关此问题的帖子,并尝试了一种解决方案,但它没有像预期的那样工作。因此,我需要整个文本可以滚动,而不是只显示三个点。

这是列表项的布局(list_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listItem"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/list_item_selector"
    android:orientation="horizontal"
    android:paddingBottom="7dp"
    android:paddingLeft="15dp"
    android:paddingTop="7dp" >

    <TextView
        android:id="@+id/listText"
        style="@style/Text_View_Style_White"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="marquee"
        android:focusableInTouchMode="true"
        android:marqueeRepeatLimit="marquee_forever" 
        android:padding="3dp"

        android:selectAllOnFocus="true"
        android:singleLine="true"
        android:textColor="@drawable/list_item_text_selector" />


</LinearLayout>

我还尝试使用android:focusable="true"android:scrollHorizontally="true"android:maxLines="1"属性,但它们都没有起作用。在适配器的getView()方法中(该适配器扩展了BaseAdapter),我在返回视图之前对TextView使用setSelected(true)方法。

我无法弄清楚问题出在哪里,请帮我看看。非常感谢您的帮助。


我也有同样的问题!我尝试了很多不同的解决方案,但都没有起作用! - thiagolr
嗨Andre,你能贴出你的getView()吗?谢谢。 - Tom
我认为这里正在发生的事情非常清楚。然而,有两种解决方案,如果没有代码,我无法确定你需要哪一个!所以,请告诉我,如果您通过编程设置了 ListViewsetItemsCanFocus(false),是否可以解决您的问题?如果不行,还有其他方法可以解决它。 - Tom
Tom,感谢您的回复!实际上我已经找到了解决问题的方法。经过一些尝试,我意识到问题出在android:selectAllOnFocus="true"这行代码上。我真的不太明白为什么,但是这行代码导致了我在问题描述中提到的奇怪行为。现在一切都很好,当文本内容过长时,它可以完整地滚动,并且按照预期的方式工作。 - Andre
1
我可以解释一下。这是因为在Listview中的onLayout中,选定的子项“sel”被获取,并且根据一个复杂的条件设置为false,该条件可以有几种方式-其中一种就是上面的方式,另一种就是你的方法。在gtView中设置setSelected是不起作用的,因为这一步在列表视图对元素执行onLayout之前处理。 (需要澄清时,请参见http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/widget/ListView.java/?v=source!) - Tom
@Andre 我也遇到了同样的问题,你对Tom的建议对我很有帮助。请在这里发布你的答案并接受它,以便帮助其他人。 - Shreyash Mahajan
7个回答

42

今天我也遇到了同样的问题,但最终解决了。这里列出的解决方案都不起作用,所以我想分享一下我是如何解决的。

简短版:如果您正在动态设置TextView的文本,请尝试在代码中设置所需的“跑马灯”属性,而不是在布局xml文件中设置。

详细版:在我的情况下,我有一个GridView,它有一个适配器和每个项中的TextView。其中一些项的文本太长,无法适应网格的“单元格”,因此我希望所有太长的项都能滚动几次。由于TextView在具有适配器的GridView中,明显是从适配器的当前项中通过代码设置文本。

通过大量痛苦的调试,我最终想到了在代码中设置所有跑马灯设置,而不是在布局xml文件中设置。这使得TextView上的三个点(...)最终消失,并开始滚动。

这是我的布局文件的样子:

(请注意,上面列出的任何属性都未在此处设置)

<TextView
android:text="Placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dp"
android:id="@+id/name"
/>

这是我的适配器代码:

nameView.setText(name);
nameView.setEllipsize(TextUtils.TruncateAt.MARQUEE);
nameView.setSingleLine(true);
nameView.setMarqueeRepeatLimit(5);
nameView.setSelected(true);

1
幸运的是,我已经解决了,但感谢您分享您的解决方案,这对于其他遇到类似问题的人可能会有用。我个人更喜欢将所有内容保留在xml布局中,并仅以编程方式设置无法在xml中设置的内容(但这当然是个人偏好的问题)。 - Andre
绝对的,我完全同意。我的问题是在xml文件中设置它们没有起作用,并且会导致你上面描述的奇怪行为。(在滚动时显示3个点,而不是完整的文本。)我更愿意在xml文件中设置属性,但由于某种原因,在代码中设置它们(在文本设置之后)解决了我的问题。我猜想,这可能是因为计算省略号和跑马灯动画的数学计算发生得太早,还在文本实际动态设置之前。(在我的情况下,必须在代码中设置文本,因为这是一个重复的视图和适配器。) - kdenney
有趣的是最终结果是随机的,有时候只需设置isSelected(true),有时候则需要将其与代码中的其他参数耦合,而不是每次文本更改时都要修改xml。感谢您的答案,现在我甚至不会考虑,只会盲目地将它们插入到每个预计滚动的TextView之后。 - usernotnull
很棒的回答!如果您使用 tv.setText("MESSAGE"),基本上可以通过编程方式设置所有属性。太好了,发现了这个! - sud007
1
有趣的是,只需在设置文本后在代码中设置setSingleLine(true)setSelected(true)即可。可以在xml中设置ellipsizemarqueeRepeatLimit。其他参数是可选的。行为(或错误)可能与您使用的支持库版本有关,因为它将TextView的出现替换为AppCompatTextView,这可能会覆盖某些行为的部分。 - cybergen
显示剩余2条评论

13

关键是在文本视图上执行 setSelected(true);。当然

android:ellipsize="marquee"
android:scrollHorizontally="true"

必须在xml中设置。如果没有这些,跑马灯将永远无法发生。


我还需要添加singleLine="true",这很奇怪,特别是它已经被弃用了。 - Ollie C

1

正如@iDroid Explorer所指出的,发布和接受答案可以对他人有所帮助。从我的回复Tom的评论中得到启示:

我找到了解决问题的方法。经过几次尝试,我意识到问题在于android:selectAllOnFocus="true"这一行(请阅读@Tom的解释)。我只是删除了那一行,现在一切都很好,当文本太长时,它完整地滚动并像期望的那样工作。


1
我能否得到至少一个关于投票反对的解释?如果所提出的解决方案对任何人都不起作用,这并不意味着解决方案本身是错误的。这可能是由于不同的条件或其他原因... - Andre
专注于对我的布局进行其他视图的处理,将其传递给TextView,然后就大功告成了。谢谢。 - moujib

0

将您的LinearLayoutTextView放入HorizontalScrollView中。这将允许完整显示文本并允许向左和向右滚动。


1
好主意,但我猜那不是跑马灯吧? - Tom
谢谢回复,Mike。请看一下我对Tom建议的评论。事实上,删除 android:selectAllOnFocus="true" 这一行就解决了问题! - Andre

0

尝试将您的layout_width设置为“match_parent”。TextView需要一个特定的宽度才能使省略号起作用,而“wrap_content”则无法实现。


1
谢谢你的回复,chirsbjr。但我已经尝试过你建议的更改,但没有成功。实际上,wrap_content属性对于TextView非常有效。请看我在原问题中对Tom建议的评论。事实上,删除android:selectAllOnFocus="true"这行就解决了问题! - Andre
@chrisbji,在线性布局中是否可以设置跑马灯?我有一个放置在线性布局内的文本,并且想在线性布局中设置跑马灯。 - Amitsharma

0

我也遇到了textView显示结尾“...”的问题,现在知道原因了!

               <TextView
                android:id="@+id/MarqueeText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="2dp"
                android:ellipsize="marquee"
                android:singleLine="true"
                android:maxLines="1"
                android:textColor="@color/text_gray"
                android:textSize="14sp"
                android:text="START | lunch 20.00 | Dinner 60.00 | Travel 60.00 | Doctor 5000.00 | lunch 20.00 | Dinner 60.00 | Travel 60.00 | Doctor 5000.00 | END" />

在我的Activity中初始化后

MarqueeText.setSelected(true);

我找到了解决问题的方法。经过一些尝试,我意识到问题出在 android:textIsSelectable="true" 这一行上。我只需删除这一行,现在一切都很好,当文本太长时,它会完整地滚动并按预期工作。


0
<TextView
    android:text="START | lunch 20.00 | Dinner 60.00 | Travel 60.00 | Doctor 5000.00 | lunch 20.00 | Dinner 60.00 | Travel 60.00 | Doctor 5000.00 | END"
android:id="@+id/MarqueeText" 
android:layout_width="fill_parent"
android:layout_height="wrap_content" 
android:singleLine="true"
android:ellipsize="marquee" 
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true" 
android:paddingLeft="15dip" 
android:paddingRight="15dip" 
android:focusable="true" 
android:focusableInTouchMode="true" 
android:freezesText="true">` 

textView.setSelected(true) // 在您的Activity中添加这些行


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