随笔-348  评论-598  文章-0  trackbacks-0
先说声 大家新年快乐哈,明天就要进入2010年了,对我来说是很意义的一年,同时也是很重要的一年。新的气象,新的工作,新的挑战。保佑自己,相信自己!不啰嗦了,切入正题。

最近在开发一个应用,需要用到文本的跑马灯效果,图省事,在网上找,但老半天都找不到,后来自己写了一个,很简单,代码如下:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.TextView;

/**
 * 
 * TODO 单行文本跑马灯控件
 *
 * 
@author tianlu
 * 
@version 1.0
 * Create At : 2010-2-16 下午09:35:03
 
*/

public class AutoScrollTextView extends TextView implements OnClickListener {
    
public final static String TAG = AutoScrollTextView.class.getSimpleName();
    
    
private float textLength = 0f;//文本长度
    private float viewWidth = 0f;
    
private float step = 0f;//文字的横坐标
    private float y = 0f;//文字的纵坐标
    private float temp_view_plus_text_length = 0.0f;//用于计算的临时变量
    private float temp_view_plus_two_text_length = 0.0f;//用于计算的临时变量
    public boolean isStarting = false;//是否开始滚动
    private Paint paint = null;//绘图样式
    private String text = "";//文本内容

    
    
public AutoScrollTextView(Context context) {
        
super(context);
        initView();
    }


    
public AutoScrollTextView(Context context, AttributeSet attrs) {
        
super(context, attrs);
        initView();
    }


    
public AutoScrollTextView(Context context, AttributeSet attrs, int defStyle) {
        
super(context, attrs, defStyle);
        initView();
    }

    
    
/**
     * 初始化控件
     
*/

    
private void initView()
    
{
        setOnClickListener(
this);
    }

    
    
/**
     * 文本初始化,每次更改文本内容或者文本效果等之后都需要重新初始化一下
     
*/

    
public void init(WindowManager windowManager)
    
{
        paint 
= getPaint();
        text 
= getText().toString();
        textLength 
= paint.measureText(text);
        viewWidth 
= getWidth();
        
if(viewWidth == 0)
        
{
            
if(windowManager != null)
            
{
                Display display 
= windowManager.getDefaultDisplay();
                viewWidth 
= display.getWidth();
            }

        }

        step 
= textLength;
        temp_view_plus_text_length 
= viewWidth + textLength;
        temp_view_plus_two_text_length 
= viewWidth + textLength * 2;
        y 
= getTextSize() + getPaddingTop();
    }

    
    @Override
    
public Parcelable onSaveInstanceState()
    
{
        Parcelable superState 
= super.onSaveInstanceState();
        SavedState ss 
= new SavedState(superState);
        
        ss.step 
= step;
        ss.isStarting 
= isStarting;
        
        
return ss;
        
    }

    
    @Override
    
public void onRestoreInstanceState(Parcelable state)
    
{
        
if (!(state instanceof SavedState)) {
            
super.onRestoreInstanceState(state);
            
return;
        }

        SavedState ss 
= (SavedState)state;
        
super.onRestoreInstanceState(ss.getSuperState());
        
        step 
= ss.step;
        isStarting 
= ss.isStarting;

    }

    
    
public static class SavedState extends BaseSavedState {
        
public boolean isStarting = false;
        
public float step = 0.0f;
        SavedState(Parcelable superState) 
{
            
super(superState);
        }


        @Override
        
public void writeToParcel(Parcel out, int flags) {
            
super.writeToParcel(out, flags);
            out.writeBooleanArray(
new boolean[]{isStarting});
            out.writeFloat(step);
        }



        
public static final Parcelable.Creator<SavedState> CREATOR
                
= new Parcelable.Creator<SavedState>() {
            
            
public SavedState[] newArray(int size) {
                
return new SavedState[size];
            }


            @Override
            
public SavedState createFromParcel(Parcel in) {
                
return new SavedState(in);
            }

        }
;

        
private SavedState(Parcel in) {
            
super(in);
            
boolean[] b = null;
            in.readBooleanArray(b);
            
if(b != null && b.length > 0)
                isStarting 
= b[0];
            step 
= in.readFloat();
        }

    }


    
/**
     * 开始滚动
     
*/

    
public void startScroll()
    
{
        isStarting 
= true;
        invalidate();
    }

    
    
/**
     * 停止滚动
     
*/

    
public void stopScroll()
    
{
        isStarting 
= false;
        invalidate();
    }

    

    @Override
    
public void onDraw(Canvas canvas) {
        canvas.drawText(text, temp_view_plus_text_length 
- step, y, paint);
        
if(!isStarting)
        
{
            
return;
        }

        step 
+= 0.5;
        
if(step > temp_view_plus_two_text_length)
            step 
= textLength;
        invalidate();

    }


    @Override
    
public void onClick(View v) {
        
if(isStarting)
            stopScroll();
        
else
            startScroll();
        
    }


}

实现了宽度的判断,文本自动滚动及开始和停止滚动等功能。

在UI xml中的配置如下:
    <cn.tigertian.ui.AutoScrollTextView android:id="@+id/TextViewNotice"
        android:layout_height
="30px" android:layout_width="fill_parent"
        android:text
="@string/test_notice_1" android:textColor="#000" android:inputType="text"
        android:background
="#EEE" android:textSize="20px"></cn.tigertian.ui.AutoScrollTextView>

在Activity中的使用方法如下:
        //启动公告滚动条
        autoScrollTextView = (AutoScrollTextView)findViewById(R.id.TextViewNotice);
        autoScrollTextView.init(getWindowManager());
        autoScrollTextView.startScroll();
如果想改变跑马灯的文字内容或者文字效果,则在调用完setText方法之后,需要再调用一下init(WindowManager windowManager)方法,重新进行初始化和相关参数的计算。


---------------------------------------------------------
专注移动开发

Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
posted on 2010-02-13 14:35 TiGERTiAN 阅读(10671) 评论(17)  编辑  收藏 所属分类: JavaAndroid

评论:
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-02-13 16:40 | altchen
请问下性能如何?不断的invalidate->onDraw  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-02-13 16:42 | TiGERTiAN
@altchen
性能么得什么降低,跑马灯实现都是要不断重绘的,不可避免。  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-18 15:40 | herbertD
请问一下,怎么才能改变textColor? 我设置的gravity="center"也不起作用,是为什么呢? 谢谢@TiGERTiAN
  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-18 15:41 | herbertD
我显示的文字显示一直是黑色的,不知道想显示为红色如何写代码?谢谢!@herbertD
  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-18 15:43 | TiGERTiAN
@herbertD
gravity="center" 这个加的没有意义,因为是整行滚动。
改颜色你需要把XML中该控件的配置信息中的textColor改一下,看我文章的下面xml示例  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-19 09:23 | herbertD
Hi, 我改了android:textColor="B11",想改为红色,但是颜色没有改变,我改了android:background="#EEE",为"#11B",背景变为蓝色了,很奇怪,呵呵 
  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-19 09:31 | herbertD
p.s 我在init() 中, this.setTextColor(0xffff0000)也不起作用,谢谢!  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-19 09:33 | TiGERTiAN
@herbertD
B11前面少了个#  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-19 09:33 | TiGERTiAN
@herbertD
这个只是设置一下,改颜色要靠Paint  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-05-19 11:27 | herbertD


paint.setColor(0xff00bb00);

搞定了:)

Thanks!!  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2010-09-16 21:40 | ixihaha
强悍谢了  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2011-09-18 22:57 | 罗晓雁
在Activity中的代码写到哪里呢?  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2011-10-11 21:10 | 济南-mu
博主你好 为什么 我在模拟器上运行,文字的滚动效果 并不均匀呢?不是 平滑的滚动!  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2013-01-22 16:19 | 麻仓叶
在代码里面改 代码里面他没处理字体颜色,init()里面加个 paint.setColor(Color.RED); 就行了@herbertD
  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件)[未登录] 2014-05-14 10:04 | et
好像会报空指针异常啊,有没有人遇到  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2014-08-16 10:12 | ptt
做不成功啊  回复  更多评论
  
# re: Android文字跑马灯控件(文本自动滚动控件) 2015-12-08 15:31 | 学鸟
如何让滚动的速度快一点啊??  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: