Android 有没有办法让 ellipsize="marquee" 始终滚动?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1827751/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to make ellipsize="marquee" always scroll?
提问by Matthias
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.
我想在 TextView 上使用选取框效果,但只有在 TextView 获得焦点时才会滚动文本。这是一个问题,因为在我的情况下,它不能。
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.
有没有办法让 TextView 始终滚动其文本?我已经在 Android Market 应用程序中看到了这一点,即使它没有获得焦点,应用程序名称也会在标题栏中滚动,但我找不到 API 文档中提到的这一点。
采纳答案by hnviet
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, onWindowFocusChangedand isFocusedto make the TextView all focused.
我一直面临这个问题,我想出的最短的解决方案是创建一个从 TextView 派生的新类。该类应覆盖三个方法onFocusChanged、onWindowFocusChanged和isFocused以使 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;
}
回答by Christopher Orr
I finally came up against this problem today and so fired up hierarchyviewer
on the Android Market application.
我今天终于遇到了这个问题,于是开始hierarchyviewer
使用 Android Market 应用程序。
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'tbe focused and was generally very ordinary — except for the fact that it was marked as selected.
查看应用程序详细信息屏幕上的标题,他们使用普通的旧TextView
. 检查它的属性表明它没有聚焦,无法聚焦并且通常非常普通——除了它被标记为selected。
One line of code later and I had it working :)
一行代码之后,我让它工作了:)
textView.setSelected(true);
This makes sense, given what the Javadoc says:
考虑到 Javadoc 所说的,这是有道理的:
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.
可以选择或不选择视图。请注意,选择与焦点不同。视图通常在 AdapterView 的上下文中选择,如 ListView 或 GridView。
i.e. When you scroll over an item in a list view (like in the Market app), only then does the now-selectedtext start scrolling. And since this particular TextView
isn't focusable or clickable, it will never lose its selection state.
即当您在列表视图中滚动某个项目时(如在 Market 应用程序中),只有此时选择的文本才会开始滚动。并且由于此特定TextView
对象不可聚焦或不可点击,因此它永远不会丢失其选择状态。
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.
不幸的是,据我所知,无法从布局 XML 中预先设置选定状态。
但是上面的单线对我来说很好用。
回答by Vinayak
Just put these parameters in your TextView. It works :)
只需将这些参数放在您的 TextView 中即可。有用 :)
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit ="marquee_forever"
android:scrollHorizontally="true"
android:focusable="true"
android:focusableInTouchMode="true"
回答by Tivie
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
通过在一个方向上按指定量“拉”视图来工作。您可以设置从哪里开始“拉”以及从哪里结束。
TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
fromXDelta set the offset of the starting position of the movement in the X axis.
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 defines the offset ending position of the movement in the X axis.
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.
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.
如果您的文本宽度大于 fromXDelta 和 toXDelta 之间的差异模块,则文本将无法在屏幕内完全和完全移动。
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.
假设我们的屏幕尺寸是 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... ||
---------------------------+|
| |
| |
| |
+---------------------------+
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:
首先,我们设置fromXDelta = 0
以便运动没有起始偏移。现在我们需要计算 toXDelta 值。为了达到预期的效果,我们需要将文本“拉”到与它跨越屏幕完全相同的像素。(方案中用<<<< X px >>>>表示)由于我们的文本宽度为700,可见区域为320px(屏幕宽度),我们设置:
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:
以 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;
}
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.
可能有更简单的方法来执行此操作,但这适用于您能想到的每个视图并且是可重用的。如果您想在不破坏 textView 的启用/onFocus 功能的情况下为 ListView 中的 TextView 设置动画,它特别有用。即使视图未聚焦,它也会连续滚动。
回答by Zarah
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.
START_POS_X
, END_POS_X
,START_POS_Y
和END_POS_Y
是float
值,而ITICKER_DURATION
是int
用其他常量声明的。
Then you can now apply this animation to your TextView:
然后您现在可以将此动画应用于您的 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).
我的动画从屏幕右侧 (300f) 开始,在屏幕左侧 (-300f) 结束,持续时间为 15 秒 (15000)。
回答by smichak
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:
我为带有选取框文本项的 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;
}
}
回答by Thunderstick
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 属性和一个 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);
}
}
});
回答by Soni Kumar
// xml
// 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
// 在 Java 中
mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE);
mtvMarque.setSelected(true);
mtvMarque.setSingleLine(true);