15

I have some custom elements in a ListView and each element is, up to know, just a TextView in a LinearLayout. I would like the text inside the TextView to be a single line scrolling horizontally when the text is too long. I read many posts on this and I came up with a solution that was supposed to work, but instead of having the full text scrolling I have the text cut to the length of the containing View and ended with the three dots. I don't want the three dots but the entire text needs to be scrolled.

This is the layout of the items in the list (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>

I tried also with android:focusable="true", android:scrollHorizontally="true" and android:maxLines="1" attributes but none of them is working. In the getView() method of the adapter (which extends a BaseAdapter) I use the setSelected(true) method on the TextView, before returning the View.

I can't figure out what the problem is. Any help will be highly appreciated.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Andre
  • 489
  • 1
  • 6
  • 17
  • I also have the same problem! I tried lots of different solutions and none of them worked! – thiagolr Jul 01 '13 at 12:02
  • Hi Andre, could you post your getView() please? Thanks. – Tom Jul 01 '13 at 13:01
  • I think it's pretty clear what's happening here. However, there are two solutions and I can't tell which one you need without code! So, tell me, if you programatically set your `ListView` s.t. `setItemsCanFocus(false)`, does this solve your problem? If not, there's something else that'll fix it. – Tom Jul 01 '13 at 13:39
  • Tom, thanks for your reply! Actually I found the solution to my problem. After some attempts I've realized that the problem was the `android:selectAllOnFocus="true"` line. I can't really understand why, but this line gave the strange behavior I described in the question. Now everything is working very well, the text is complete and scrolling like desired when it is too long for the containing view. – Andre Jul 01 '13 at 14:48
  • 1
    I can probably explain. it's because in `onLayout` in Listview, the selected child `sel` is gotten, and `setSelected` is set false given a complicated condition which can be broken a few ways- one is the above, one is your way. Setting `setSelected` in `gtView` doesn't work as that step is processed *before* the listview performs `onLayout` on the element. (See http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/widget/ListView.java/?v=source whenever you need clarification!) – Tom Jul 01 '13 at 15:03
  • @Andre i have same problem and your suggestion to Tom works for me. Please put your answer here and accept it so that it can help others. – Shreyash Mahajan Jan 05 '15 at 10:43

7 Answers7

42

I had the same problem today and was able to figure it out. None of the listed solutions here worked so I thought I'd share what fixed it for me.

TL;DR: If you are dynamically setting the text of the TextView, try setting the required "marquee" properties in code instead of in the layout xml file.

Longer version: In my case, I had a GridView with an adapter and a TextView in each item. Some of the item's had text that was too long to fit in its "cell" of the grid, and thus I wanted all items that were too long to scroll a few times. Being that the TextView is in a GridView with an adapter, the text was obviously being set in code, from the current item of the adapter.

Through much painful debugging, I finally had the idea to set all of the marquee settings in code instead of in the layout xml file. This caused the 3 dots (...) to finally go away from the TextView and begin scrolling instead.

Here's what my layout file looks like now: (note that none of the properties listed above are set here)

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

And here's what my adapter code looks like:

nameView.setText(name);
nameView.setEllipsize(TextUtils.TruncateAt.MARQUEE);
nameView.setSingleLine(true);
nameView.setMarqueeRepeatLimit(5);
nameView.setSelected(true);
kdenney
  • 18,343
  • 4
  • 31
  • 27
  • 1
    Fortunately I've already solved, but thanks for sharing your solution, it could be useful for anyone else having similar problems. I personally prefer to leave everything in the xml layout and programmatically set only what is not possible to set in xml (but this is of course a matter of personal preferences). – Andre Apr 02 '14 at 07:21
  • Absolutely, I completely agree. My problem was that setting them in the xml was not working and was causing the odd behavior you described above. (Showing the 3 dots while scrolling, instead of the full text.) I would have preferred to set the properties in the xml but for some reason, setting them in code (after the text is set) solved my problem. I'm guessing because the math to do the ellipsize and marquee animation was being calculated too early and before the text was actually set dynamically. (In my case, the text must be set in code because this was a repeated view and an adapter.) – kdenney Apr 02 '14 at 13:42
  • Not nice that unexpected things happen to your XML setup when calling something as innocent as `.setText()`. :( – Diederik Aug 15 '14 at 11:20
  • It's funny how the end result is random, sometimes if works just by setting isSelected(true), sometimes when coupling it with the rest of the parameters in code rather than xml every time the text changes. Thanks for your answer, now I won't even think i'll just blindly plug those after each textview which is expected to scroll – usernotnull Jul 23 '16 at 08:49
  • Beautiful answer! Basically set all attributes programatically if you are using `tv.setText("MESSAGE")`. Great Finding! – sud007 Aug 01 '16 at 09:58
  • `nameView.setSelected(true);` is required to make marquee work thru code – DeltaCap019 Nov 28 '16 at 11:37
  • Funny enough it's sufficient to just set `setSingleLine(true)` and `setSelected(true)` in code after setting the text. `ellipsize` and `marqueeRepeatLimit` may be set in xml. Other parameters are optional. The behavior (or bugs) maybe relate to the support library version you use, as it replaces occurences of `TextView` with `AppCompatTextView` which may override some parts of the behavior. – cybergen Feb 14 '17 at 01:10
13

Key is here to do setSelected(true); on text view.. Of course

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

need to be set in xml as well. Without all of this marquee will not happen. Ever.

Ewoks
  • 12,285
  • 8
  • 58
  • 67
1

As @iDroid Explorer pointed out, posting and accepting the answer can be of help to someone else. Adapting from my reply to Tom's comment:

I found the solution to my problem. After some attempts I've realized that the problem was the android:selectAllOnFocus="true" line (Read @Tom's explanation for probabale reason). I just removed that line and now everything is working very well, the text is complete and scrolling like desired when it is too long for the containing view.

Andre
  • 489
  • 1
  • 6
  • 17
  • 1
    May I receive at least an explanation for a downvote? If the proposed solution doesn't work for anyone it doesn't mean the solution itself is wrong. It may be due to different conditions or other reasons... – Andre Jan 28 '15 at 15:52
  • Focus was taking by an other view on my layout , gave it to the textview and voilà , it's working as expected.Thank you. – moujib Feb 23 '16 at 11:02
0

Either put your LinearLayout or your TextView inside of a HorizontalScrollView. This will allow the text to be displayed in full and allow for scrolling right and left.

BC2
  • 892
  • 1
  • 7
  • 23
  • 1
    Great idea, but I guess that'd not the same as a marquee...? – Tom Jul 01 '13 at 13:19
  • Thanks for the reply Mike, see my comment to Tom's suggestion. Actually, removing the `android:selectAllOnFocus="true"` line solved the problem! – Andre Jul 01 '13 at 14:54
0

Try setting your layout_width to "match_parent". The TextView needs a specific width for the ellipsis to work and won't work with "wrap_content".

chrisbjr
  • 628
  • 4
  • 10
  • 1
    Thanks for the reply chirsbjr, but I had already tried the change you suggested without success. Indeed the `wrap_content` attribute works well for the TextView. See my comment to Tom's suggestion in the original question. Actually, removing the `android:selectAllOnFocus="true"` line solved the problem! – Andre Jul 01 '13 at 14:57
  • @chrisbji can it is possible in Linear layout i have text inside Linearlayout and i want to set marquee in linearlayout ?? – Amitsharma Jan 02 '17 at 06:44
0

I was Facing Same Issue With my textView Now got reason why it is showing ...at the end of text.!

               <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" />

and After Initialization In my Activity

MarqueeText.setSelected(true);

I found the solution to my problem. After some attempts I've realized that the problem was the android:textIsSelectable="true". I just removed that line and now everything is working very well, the text is complete and scrolling like desired when it is too long for the containing view.

Atif AbbAsi
  • 5,633
  • 7
  • 26
  • 47
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) // Add these line in Your Activity

Ganesan J
  • 539
  • 7
  • 12