有没有办法让ellipsize =“ marquee”总是滚动?


93

我想在TextView上使用选取框效果,但是仅在TextView获得焦点时才滚动文本。这是一个问题,因为就我而言,这不可能。

我在用:

  android:ellipsize="marquee"
  android:marqueeRepeatLimit="marquee_forever"

有没有办法让TextView始终滚动其文本?我已经在Android Market应用程序中看到了这一点,即使该应用程序名称没有得到关注,该应用程序的名称也会在标题栏中滚动,但是我找不到API文档中提到的内容。


为了使字幕工作正常,应选择TextView而不是集中精力。重点是选择,但不是反向。
丹尼斯·格拉德基

1
始终尝试使用MarqueeTextView stackoverflow.com/a/28806003/3496570
AndroidGeek'3

Answers:


62

我一直在面对这个问题,而我想出的最短的解决方案是创建一个从TextView派生的新类。该类应重写onFocusChangedonWindowFocusChangedisFocused这三种方法,以使TextView全部集中。

@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
    if(focused)
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
}

@Override
public void onWindowFocusChanged(boolean focused) {
    if(focused)
        super.onWindowFocusChanged(focused);
}


@Override
public boolean isFocused() {
    return true;
}

完美-这只是我一直在寻找的解决方案。
杰森

6
如果希望选框在弹出菜单时不会停止,则还应该重写onWindowFocusChanged方法。
virsir 2010年

7
顺便说一句,我们实际上对此解决方案有问题,因为它弄乱了有状态的可绘制对象:如果您用聚焦/聚焦更改了可绘制对象,那么它将中断。我们花了将近一个小时的调试时间,直到我们意识到该漏洞是由它引起的。
马提亚斯(Matthias)2010年

您能否提供有关该问题的更详细描述?我在许多应用程序中都使用了此功能。我也想看看这个问题。
hnviet 2010年

1
这种技巧非常有效,并且只有在同时显示多个TextView时才需要(例如,在ListView中使用时),因为通常只有其中一个可以被聚焦,但是此解决方案通过告诉所有人来“欺骗”系统是:)否则,对于单个TextView,应使用更简单的答案,例如stackoverflow.com/a/3510891/258848
dimsuz 2013年

120

我终于在今天遇到了这个问题,因此hierarchyviewer在Android Market应用程序上启动了。

在应用程序的详细信息屏幕上查看标题时,他们使用的是普通的old TextView。检查其属性表明它没有被聚焦,无法被聚焦并且通常非常普通-除了被标记为selected的事实。

一行代码之后,我开始工作了:)

textView.setSelected(true);

鉴于Javadoc所说的,这是有道理的:

是否可以选择视图。请注意,选择与焦点不同。通常,在ListView或GridView之类的AdapterView上下文中选择视图。

例如,当您在列表视图中滚动某个项目时(例如在Market应用程序中),只有现在选择的文本才开始滚动。并且由于该特定TextView内容不可聚焦或不可单击,因此它将永远不会丢失其选择状态。

不幸的是,据我所知,无法从布局XML预先设置所选状态。
但是上面的一线对我来说很好。


只是想知道:这对于可聚焦的TextViews是否也适用,但是在未聚焦时仍应滚动?现在,即使焦点状态发生变化,选择状态也会“粘住”吗?
Matthias 2010年

大概吧。我不明白为什么将重点放在基本内容上TextView(即未嵌入诸如之类的“可选”内容中ListView)会改变所选状态。
Christopher Orr 2010年

对我来说也很好。谢谢您的回答。有可能改变重复的方式吗?
蒂玛

@Mur:是的,请阅读TextView文档并查看android:marqueeRepeatLimit
Christopher Orr 2010年

1
这种方法比具有焦点的方法要好,因为它不会与视图的焦点混淆。如果您有需要父母关注的观点,则该方法会使焦点混乱。这种方法简单,高效,并且无需依赖黑客即可随时更改焦点。谢谢!
Ionut Negru 2014年

75

只需将这些参数放在您的TextView中。有用 :)

    android:singleLine="true" 
    android:ellipsize="marquee"
    android:marqueeRepeatLimit ="marquee_forever"
    android:scrollHorizontally="true"
    android:focusable="true"
    android:focusableInTouchMode="true" 

1
如果我认为这个答案线程还没有结束,那应该是公认的答案。我将其添加到文本视图的XML定义中,并且在第一张照片上就可以使用。我尝试了其他建议,这是最简单的。-另外,添加“ android:marqueeRepeatLimit =” marquee_forever“使其无限期滚动
布拉克(Brack)2010年

19
如果TextView位于其中,则使用此方法将中断对ListView行的焦点选择。
Tivie 2010年

完美运作。简单而优雅的解决方案。谢谢!
拉比2012年

如何启动和停止TextView选框
-Dwivedi Ji

在尝试其他答案之前,这对我不起作用-textView.setSelected(true);
贾斯汀2014年

13

TranslateAnimation通过将视图沿一个方向“拉”指定的数量来工作。您可以设置从何处开始“拉动”和何处结束。

TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);

fromXDelta设置X轴上运动开始位置的偏移量。

fromXDelta = 0 //no offset. 
fromXDelta = 300 //the movement starts at 300px to the right.
fromXDelta = -300 //the movement starts at 300px to the left

toXDelta定义运动在X轴上的偏移结束位置。

toXDelta = 0 //no offset. 
toXDelta = 300 //the movement ends at 300px to the right.
toXDelta = -300 //the movement ends at 300px to the left.

如果文本的宽度大于fromXDelta和toXDelta之间的差值的模块,则文本将无法在屏幕内完全移动。


假设我们的屏幕尺寸为320x240像素。我们有一个TextView,其文本宽度为700px,我们希望创建一个动画来“拉”文本,以便我们可以看到短语的结尾。

                                       (screen)
                             +---------------------------+
                             |<----------320px---------->|
                             |                           |
                             |+---------------------------<<<< X px >>>>
               movement<-----|| some TextView with text that goes out...
                             |+---------------------------
                             |  unconstrained size 700px |
                             |                           |
                             |                           |
                             +---------------------------+


                             +---------------------------+
                             |                           |
                             |                           |
               <<<< X px >>>>---------------------------+|
movement<----- some TextView with text that goes out... ||
                             ---------------------------+|
                             |                           |
                             |                           |
                             |                           |
                             +---------------------------+

首先我们进行设置fromXDelta = 0,以使运动没有起始偏移。现在我们需要计算toXDelta值。为了达到理想的效果,我们需要将文本“拉”出与屏幕完全相同的px。(在方案中用<<<< X px >>>>表示)由于我们的文本宽度为700,可见区域为320px(屏幕宽度),因此我们设置:

tXDelta = 700 - 320 = 380

以及我们如何计算屏幕宽度和文本宽度?


以Zarah片段为起点:

    /**
     * @param view The Textview or any other view we wish to apply the movement
     * @param margin A margin to take into the calculation (since the view
     *               might have any siblings in the same "row")
     *
     **/
public static Animation scrollingText(View view, float margin){

    Context context = view.getContext(); //gets the context of the view

            // measures the unconstrained size of the view
            // before it is drawn in the layout
    view.measure(View.MeasureSpec.UNSPECIFIED, 
                         View.MeasureSpec.UNSPECIFIED); 

            // takes the unconstrained wisth of the view
    float width = view.getMeasuredWidth();

            // gets the screen width
    float screenWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();


            // perfrms the calculation
    float toXDelta = width - (screenWidth - margin);

            // sets toXDelta to 0 if the text width is smaller that the screen size
    if (toXDelta < 0) {toXDelta = 0; } else { toXDelta = 0 - toXDelta;}

            // Animation parameters
    Animation mAnimation = new TranslateAnimation(0, toXDelta, 0, 0);
    mAnimation.setDuration(15000); 
    mAnimation.setRepeatMode(Animation.RESTART);
    mAnimation.setRepeatCount(Animation.INFINITE);

    return mAnimation;
}

可能有更简单的方法可以执行此操作,但是这种方法适用于您可以想到并且可以重用的每个视图。如果要在ListView中为TextView设置动画而不破坏textView的enabled / onFocus功能,则它特别有用。即使视图未聚焦,它也会连续滚动。


我上面的答案(即添加一行代码textView.setSelected(true);:)在您的情况下不起作用吗?
Christopher Orr 2010年

抱歉不行。我有一个ListView,每行填充了几个TextView(因此,空间危机= P)。textview的每一行都是可单击的,并弹出一个上下文菜单。将setSelected设置为true似乎会中断上下文菜单。
Tivie 2010年

是吗?在大多数情况下,可能有点过头了。对我而言,出于上述原因,这是唯一的解决方案。(可重复使用,顺便说一句!)= P
Tivie

12

我不知道您是否仍然需要答案,但是我找到了一种简便的方法。

像这样设置动画:

Animation mAnimation = new TranslateAnimation(START_POS_X, END_POS_X, 
                START_POS_Y, END_POS_Y);
mAnimation.setDuration(TICKER_DURATION); 
mAnimation.setRepeatMode(Animation.RESTART);
mAnimation.setRepeatCount(Animation.INFINITE);

START_POS_XEND_POS_XSTART_POS_YEND_POS_Yfloat值,而TICKER_DURATIONint我与我的其他常量声明。

然后,您现在可以将此动画应用于TextView:

TextView tickerText = (TextView) findViewById(R.id.ticker);
tickerText.setAnimation(mAnimation);

就是这样。:)

我的动画在屏幕外右侧(300f)开始,在屏幕外左侧(-300f)结束,持续时间为15秒(15000)。


1
这似乎并不简单。但是我认为他仍然不需要答案。请参阅上方接受的答案.. :)
Christopher Orr 2010年

2
但我认为此解决方案比创建新类更简单。:D照原样,您还可以将动画对象重新用于要设置动画的其他视图。;)
Zarah 2010年

虽然效果很好,但是显示长文本该怎么办?现在我的文字将被剪掉
Tima

@Mur Votema:您是否尝试过将TextView的宽度设置为wrap_content?
Zarah 2010年

3
这不是一个很好的解决方案,因为大小和持续时间参数非常依赖于文本大小。此外,即使文本长度小于视图宽度,也会进行动画处理。setSelected(true)确实是最简单的解决方案。
ANM

5

我为带有字幕文本项的ListView编写了以下代码。它基于上述setSelected解决方案。基本上,我将扩展ArrayAdapter类,并在返回它之前重写getView方法以选择TextView:

    // Create an ArrayAdapter which selects its TextViews before returning      
    // them. This would enable marqueeing while still making the list item
    // clickable.
    class SelectingAdapter extends ArrayAdapter<LibraryItem>
    {
        public
        SelectingAdapter(
            Context context, 
            int resource, 
            int textViewResourceId, 
            LibraryItem[] objects
        )
        {
            super(context, resource, textViewResourceId, objects);
        }

        @Override
        public
        View getView(int position, View convertView, ViewGroup parent)
        {
            View view = super.getView(position, convertView, parent);
            TextView textview = (TextView) view.findViewById(
                R.id.textview_playlist_item_title
            );
            textview.setSelected(true);
            textview.setEnabled(true);
            textview.setFocusable(false);
            textview.setTextColor(0xffffffff);
            return view;

        }
    }

1

这是在我的Google搜索顶部弹出的答案,所以我认为我可以在这里发布有用的答案,因为我经常想起这个问题而感到困惑。无论如何,这对我有用,并且需要XML属性和A onFocusChangeListener。

//XML
        <TextView
            android:id="@+id/blank_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:layout_gravity="center_horizontal|center_vertical"
            android:background="#a4868585"
            android:textColor="#fff"
            android:textSize="15sp"
            android:singleLine="true"
            android:lines="1"
            android:ellipsize="marquee"
            android:marqueeRepeatLimit ="marquee_forever"
            android:scrollHorizontally="true"
            android:focusable="true"
            android:focusableInTouchMode="true"
            tools:ignore="Deprecated" />

//JAVA
    titleText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                titleText.setSelected(true);
            }
        }
    });

1

// XML

 <TextView
            android:id="@+id/tvMarque"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:layout_gravity="center_horizontal"
            android:fadingEdge="horizontal"
            android:marqueeRepeatLimit="marquee_forever"
            android:scrollHorizontally="true"
            android:padding="5dp"
            android:textSize="16sp"
            android:text=""
            android:textColor="@color/colorSyncText"
            android:visibility="visible" />

//在Java中

        mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        mtvMarque.setSelected(true);
        mtvMarque.setSingleLine(true);
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.