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

发布于 2024-08-13 02:21:50 字数 300 浏览 6 评论 0原文

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

我正在使用:

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

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

I want to use the marquee effect on a TextView, but the text is only being scrolled when the TextView gets focus. That's a problem, because in my case, it can't.

I am using:

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

Is there a way to have the TextView always scroll its text? I've seen this being done in the Android Market app, where the app name will scroll in the title bar, even if it doesn't receive focus, but I couldn't find this being mentioned in the API docs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

梦年海沫深 2024-08-20 02:21:50

我今天终于遇到了这个问题,因此启动了 hierarchyviewer< Android Market 应用程序上的 /code>

查看应用详细信息屏幕上的标题,他们使用普通的旧 TextView。检查其属性表明它没有聚焦,无法聚焦并且通常非常普通 - 除了它被标记为已选择这一事实。

一行代码之后,我就让它工作了:)

textView.setSelected(true);

考虑到 Javadoc 说

可以选择或不选择视图。请注意,选择与焦点不同。通常在 AdapterView(例如 ListView 或 GridView)的上下文中选择视图。

即,当您在列表视图中滚动某个项目(例如在“市场”应用程序中)时,只有此时现在选择的文本才会开始滚动。由于这个特定的 TextView 不可聚焦或可点击,因此它永远不会丢失其选择状态。

不幸的是,据我所知,没有办法从布局 XML 中预先设置选定的状态。
但上面的一句话对我来说效果很好。

I finally came up against this problem today and so fired up hierarchyviewer on the Android Market application.

Looking at the title on an app's detail screen, they use a plain old TextView. Examining its properties showed that it wasn't focused, couldn't be focused and was generally very ordinary — except for the fact that it was marked as selected.

One line of code later and I had it working :)

textView.setSelected(true);

This makes sense, given what the Javadoc says:

A view can be selected or not. Note that selection is not the same as focus. Views are typically selected in the context of an AdapterView like ListView or GridView.

i.e. When you scroll over an item in a list view (like in the Market app), only then does the now-selected text start scrolling. And since this particular TextView isn't focusable or clickable, it will never lose its selection state.

Unfortunately, as far as I know there is no way to pre-set the selected state from the layout XML.
But the one-liner above works fine for me.

断肠人 2024-08-20 02:21:50

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

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

Just put these parameters in your TextView. It works :)

    android:singleLine="true" 
    android:ellipsize="marquee"
    android:marqueeRepeatLimit ="marquee_forever"
    android:scrollHorizontally="true"
    android:focusable="true"
    android:focusableInTouchMode="true" 
波浪屿的海角声 2024-08-20 02:21:50

我一直面临这个问题,我想出的最短的解决方案是创建一个从 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;
}

I have been facing the problem and the shortest solution I have come up with is to create a new class derived from TextView.
The class should override three methods onFocusChanged, onWindowFocusChanged and isFocused to make the TextView all focused.

@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;
}
孤独难免 2024-08-20 02:21:50

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 值。为了达到预期的效果,我们需要将文本“拉”出与屏幕外完全相同的像素。 (在方案中用<<<<>>表示)由于我们的文本宽度为700,可见区域为320px(屏幕宽度),我们设置

tXDelta = 700 - 320 = 380

:计算屏幕宽度和文本宽度?


代码

以 Zarah Snippet 为起点的

    /**
     * @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 的启用/焦点功能,那么它特别有用。即使视图未聚焦,它也会连续滚动。

TranslateAnimation works by "pulling" the View in one direction by a specified amount. You can set where to start this "pulling" and where to end.

TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);

fromXDelta set the offset of the starting position of the movement in the X axis.

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 defines the offset ending position of the movement in the X axis.

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

If the width of your text is greater that the module of the difference between fromXDelta and toXDelta, the text won't be able to totaly and compeltely move within the screen.


Example

Let's assume our screen size is 320x240 pxs. We have a TextView with a text that has 700px width and we wish to create an animation that "pulls" the text so that we can see the end of the phrase.

                                       (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... ||
                             ---------------------------+|
                             |                           |
                             |                           |
                             |                           |
                             +---------------------------+

First we set fromXDelta = 0 so that the movement doesn't have a starting offset. Now we need to figure the toXDelta value. To achieve the desired effect we need to "pull" the text the exact same px that it spans out of the screen. (in the scheme is represented by <<<< X px >>>>) Since our text has 700 width, and the visible area is 320px (screen width) we set:

tXDelta = 700 - 320 = 380

And how do we figure the Screen Width and the text Width?


Code

Taking the Zarah Snippet as a starting point:

    /**
     * @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;
}

There might be easier ways to perform this, but this works for every view you can think of and is reusable. It is specially usefull if you want to animate a TextView in a ListView without breaking the enabled/onFocus abilities of the textView. It also scrolls continuously even if the View is not focused.

明媚殇 2024-08-20 02:21:50

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

像这样设置动画:

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_DURATION 是我用其他常量声明的 int

然后您现在可以将此动画应用到您的 TextView:

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

就是这样。 :)

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

I don't know if you still need the answer, but I found an easy way to do this.

Set up your animation like so:

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_X, END_POS_X, START_POS_Y and END_POS_Y are float values, while TICKER_DURATION is an int I declared with my other constants.

Then you can now apply this animation to your TextView:

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

And that's it. :)

My animation starts on the right side off-screen (300f) and ends on the left side off-screen(-300f), with a duration of 15s (15000).

孤独难免 2024-08-20 02:21:50

我为带有选取框文本项的 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;

        }
    }

I wrote the following code for a ListView with marquee text items. It is based on the setSelected solution described above. Basically, I am extending the ArrayAdapter class and override the getView method to select the TextView before returning it:

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

        }
    }
拥醉 2024-08-20 02:21:50

这是我的谷歌搜索顶部弹出的答案,所以我想我可以在这里发布一个有用的答案,因为我经常很难记住这个答案。
无论如何,这对我有用,并且需要 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);
            }
        }
    });

This is the answer that pops up at the top of my google search so I thought I could post a useful answer here since I struggle with remembering this fairly often.
Anyway, this works for me and requires XML attributes and A an 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);
            }
        }
    });
海之角 2024-08-20 02:21:50

// 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);

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

// In Java

        mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        mtvMarque.setSelected(true);
        mtvMarque.setSingleLine(true);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文