三种方式实现TextView文字滚动的效果。
第一种:原生的
Android
自带的跑马灯效果。直接申明TextView属性。
第二种:改造TextView,自定义View继承的TextView,利用Runnable循环调用onDraw()方法更新视图。
第三种:利用HorizontalScrollView控件的特性,里面加个TextView,通过定时器让HorizontalScrollView循环滑动,达到跑马灯效果。
三种方法的利弊:
三种方法都有微妙的差别,并对兼容性有要求。
第一种:速度不能控制,焦点不在TextView上时不能滚动。但因为这是
安卓
系统的功能,所以基本不用考虑兼容性。还有,当文本长度小于控件长度时也是没有跑马灯效果的。
第二种:可以控制速度、滚动方向。但是部分设备上会有兼容性问题,比如部分设备上出现闪动,而且很难解决,因为这种方式是通过不断重新图形绘制实现,所以会出现这个问题。
第三种:可以控制速度,方向,但是因为HorizontalScrollView控件的特性限制,从scrollTo(x,y)方法就知道,从x=0到x=”文本长度”的过程中是很顺畅的,但是移动到两端的时候就会出现卡顿的现象,不能很流畅的延一个方向移动。
下面可以看代码:
第一种很简单:
<TextView
android:id="@+id/myTextView"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:ellipsize="marquee"
android:focusable="true"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:text="文本区域"
android:textColor="@android:color/black" >
</TextView>
<?
xml version="1.0" encoding="utf-8"
?>
<
LinearLayout
xmlns:android
="http://schemas.android.com/apk/res/android"
android:orientation
="vertical"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
>
<
TextView
android:layout_width
="fill_parent"
android:layout_height
="wrap_content"
android:text
="@string/hello"
/>
<
TextView
android:layout_width
="100px"
android:layout_height
="wrap_content"
android:text
="234254fadfadffadfadfgfhdgfhjhfjhfjhjfhjfhjfhjfhjtyteytryet"
android:marqueeRepeatLimit
="marquee_forever"
android:ellipsize
="marquee"
android:scrollHorizontally
="true"
android:focusableInTouchMode
="true"
android:focusable
="true"
></
TextView
>
</
LinearLayout
>
android:layout_width="100px" //文字宽度不能是wrap_content(后面更正,可以是!),//这样的跑步起来
android:marqueeRepeatLimit="marquee_forever"//表示滚动回数,这里这么设置,表示一直滚动
android:ellipsize="start" 省略号在开头
android:ellipsize="middle" 省略号在中间
android:ellipsize="end" 省略号在结尾
android:ellipsize="marquee" 跑马灯显示
或者在程序中可通过setEillpsize显式设置。
android:focusable="true" //要显示该跑马灯,view必须要获得焦点,只有在取得焦点的情况下跑马灯才会显示
更新:
用此例在android4.0.3上不能跑起来跑马灯的效果,需加
android:singleLine="true"
当为一行的时候,才有跑马灯效果。
例2:两个TextView,都设置跑马灯效果
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello"
android:singleLine="true" //只有单行才可能有跑马灯效果
android:ellipsize="marquee" //跑马灯效果
android:marqueeRepeatLimit="marquee_forever" //跑马灯重复次数 android:focusable="true" //由于Activity中没有写任何方法,故此处让其获得焦点
android:focusableInTouchMode="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/s1"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:focusable="true"
android:focusableInTouchMode="true"
>
</TextView>
</LinearLayout>
运行结果,只有第一个跑马灯有跑马灯效果。
注意:
(1)纠正之前说的必须要宽度限制,才有跑马灯效果,此处把宽度设为wrap_content一样有跑马灯效果。
(2)Android的缺省行为是在控件获得Focus时才会显示走马灯效果,本例使用的Button,在某一个Button获得焦点时Button上的文字才显示跑马灯效果。
(3)android:marqueeRepeatLimit在ellipsize指定marquee的情况下,设置重复滚动的次数,当设置为 marquee_forever时表示无限次。
也可以设置为1,2.。等。
(4)android:focusableInTouchMode:是否在触摸模式下获得焦点。
android:focusable控件是否能够获取焦点
对于一个大View中有很多子View来说,同一时刻只能有一个子View获得focus!也就是说当前这一屏上,最多只能有一个view能有跑马灯效果,而不能多个View同事都有跑马灯效果。
这段代码就可以实现跑马灯的效果。
第二种:
public class MarqueeTextView extends TextView implements Runnable {
private int currentScrollX;
private boolean isStop = false;
private int textWidth;
private boolean isMeasure = false;
public MarqueeTextView(Context context) {
super(context);
}
public MarqueeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!isMeasure) {
getTextWidth();
isMeasure = true;
}
}
/**
* 获取文字宽度
*/
private void getTextWidth() {
Paint paint = this.getPaint();
String str = this.getText().toString();
textWidth = (int) paint.measureText(str);
}
@Override
public void run() {
currentScrollX -= 1;
scrollTo(currentScrollX, 0);
if (isStop) {
return;
}
if (getScrollX() <= -(this.getWidth())) {
scrollTo(textWidth, 0);
currentScrollX = textWidth;
}
postDelayed(this, 10);
}
public void startScroll() {
isStop = false;
this.removeCallbacks(this);
post(this);
}
public void stopScroll() {
isStop = true;
}
public void startFor0() {
currentScrollX = 0;
startScroll();
}
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
startScroll();
}
@Override
public void destroyDrawingCache() {
super.destroyDrawingCache();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
这个自定义控件只要在layout文件中引用即可:
<com.example.test.MarqueeTextView
android:id="@+id/marqueeTextView"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="tesja;eao;ffjidaofjieloafj.afiaeofjidk.afjie"
android:layout_centerHorizontal="true"
android:layout_below="@+id/scrollTextView"
/>
第三种:
public class HorizontalScorllTextView extends HorizontalScrollView implements Runnable{
int currentScrollX = 0;
TextView tv;
public HorizontalScorllTextView(Context context) {
super(context);
initView(context);
}
public HorizontalScorllTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public HorizontalScorllTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
void initView(Context context){
View v = LayoutInflater.from(context).inflate(R.layout.scroll_layout, null);
tv = (TextView)v.findViewById(R.id.tv_video_name);
this.addView(v);
}
public void setText(String text){
tv.setText(text);
startScroll();
}
private void startScroll(){
this.removeCallbacks(this);
post(this);
}
@Override
public void run() {
currentScrollX ++;
scrollTo(currentScrollX, 0);
if (currentScrollX >= tv.getWidth()) {
scrollTo(0, 0);
currentScrollX = 0;
}
postDelayed(this, 50);
}
}
这种方法跟第二种差不多,只是文本是在构造函数中加进来一个layout文件,就是引进了textview,然后跟第二种方式一样循环滚动scrollview。
还有一个需要注意的地方就是第三种方法必须要在Java代码中使用setText()方法,因为这控件中是在setText中使能滑动功能的。
还有一种方法是用平移动画无限循环移动view的方式,没试了。另外附上demo的下载地址:
http://download.csdn.net/detail/luozhi3527/8608239