效果图:

在layout中这样来声明:

	<com.kaixin001.view.ScrollText android:id="@+id/news_statustxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:layout_gravity="center_vertical"
android:textColor="#000000"
android:textSize="16sp"
android:hint="@string/news_state_hint"
android:inputType="text"/>

activity这样来调用:

   private void initStatus(){
ivState = (ImageView) findViewById(R.id.news_statusinput);
//必须使text长度比控件的宽度大
String s = "dsafsdfsdf(#开心)fsgfdg(#闭嘴)fdgdfgdfgdfgdfgdfgfdgfdgfdgfdgdfg";
newsModel.setStatus(s);
String strModel = newsModel.getStatus();
setStateText(strModel); } private void setStateText(String strModel){
if(!TextUtils.isEmpty(strModel)){
tvState.setStateList(newsModel.getStateList());
tvState.setText(strModel);
tvState.init(getWindowManager(), handler);
tvState.startScroll();
tvState.start();
}
}
<pre name="code" class="java"> <span style="white-space:pre"> </span> public void setStatus(String status){
this.status = status;
if(!TextUtils.isEmpty(status)){
stateList = ParseNewsInfoUtil.parseStr(status);
}
<span style="white-space:pre"> </span>}

private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case ScrollText.TEXT_TIMER:if(tvState != null){tvState.scrollText();}break;default:break;}}};


import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.WindowManager;
import android.widget.TextView;
import com.kaixin001.item.LinkInfo;
import com.kaixin001.model.StateFaceModel; public class ScrollText extends TextView { public static final int TEXT_TIMER = 100;
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;// 用于计算的暂时变量
private boolean isStarting = false;// 是否開始滚动
private int left = 0;
private int right = 0;
private Paint paint = null;// 画图样式
private String text = "";// 文本内容
private Bitmap txtBmp;
private Canvas txtCanvas;
private FontMetrics fontMetrics;
private Timer timer = new Timer();
private ArrayList<LinkInfo> stateList; Handler handler; TimerTask task = new TimerTask() {
public void run() {
if (handler != null && isStarting) {
Message msg = Message.obtain();
msg.what = TEXT_TIMER;
handler.sendMessage(msg);
}
}
}; public ScrollText(Context context) {
super(context);
} public ScrollText(Context context, AttributeSet attrs) {
super(context, attrs);
} public ScrollText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} /** */
/**
* 文本初始化,每次更改文本内容或者文本效果等之后都须要又一次初始化一下
*/
public void init(WindowManager windowManager, Handler handler) {
try {
this.handler = handler;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Style.STROKE);
paint.setTextSize(getTextSize());
paint.setColor(getCurrentTextColor());
text = getText().toString();
textLength = 0;
// textLength = paint.measureText(text);
int len = stateList.size();
for (int i = 0; i < len; i++) {
LinkInfo info = stateList.get(i);
if (info.isFace()) {// 表情符排版
Bitmap faceBmp = StateFaceModel.getInstance()
.getSmallFaceIcon(info.getContent());
int xLen = faceBmp.getWidth();
textLength += xLen + 4;
continue;
}
String strContent = info.getContent();
float xLen = paint.measureText(strContent);
textLength += xLen;
}
left = this.getPaddingLeft();
right = this.getPaddingRight();
step = textLength;
fontMetrics = paint.getFontMetrics(); y = getPaddingTop();// getTextSize() + getPaddingTop();
txtBmp = null;
} catch (Exception ex) {
ex.printStackTrace();
}
} public void scrollText() {
if (!isStarting) {
return;
}
invalidate();
if (viewWidth < textLength) {
step += 0.5;
if (step > temp_view_plus_two_text_length) {
step = textLength;
}
}
} public void setStateList(ArrayList<LinkInfo> stateList) {
this.stateList = stateList;
} private void setTxtBmp() {
if (txtBmp == null && fontMetrics != null) {
y = -paint.ascent();// fontMetrics.bottom -
// fontMetrics.ascent;//(this.getHeight() -
// (int)fontMetrics.ascent)/2;
viewWidth = getWidth() - left - right;
temp_view_plus_text_length = viewWidth + textLength;
temp_view_plus_two_text_length = viewWidth + textLength * 2;
txtCanvas = new Canvas(); int width = (int) viewWidth;
float height = getHeight();
txtBmp = Bitmap.createBitmap(width, (int) height, Config.ARGB_8888);
txtCanvas.setBitmap(txtBmp); }
} /** */
/**
* 開始滚动
*/
public void startScroll() {
isStarting = true;
} /** */
/**
* 停止滚动
*/
public void stopScroll() {
isStarting = false;
// invalidate();
} public void start() {
timer.schedule(task, 10, 20);
} public void stop() {
timer.cancel();
} @Override
public void onDraw(Canvas canvas) {
try {
setTxtBmp();
if (txtBmp == null) {
return;
}
Paint txtPaint = new Paint();
txtPaint.setColor(Color.WHITE);
txtPaint.setStyle(Style.FILL);
txtCanvas.drawRect(0, 0, txtBmp.getWidth(), txtBmp.getHeight(),
txtPaint);
txtPaint.setAntiAlias(true);
txtPaint.setStyle(Style.STROKE);
txtPaint.setTextSize(getTextSize());
txtPaint.setColor(getCurrentTextColor());
float x = 0;
// step为text的宽度
if (viewWidth < textLength) {
x = temp_view_plus_text_length - step;
}
int len = stateList.size();
float curLen = x;
for (int i = 0; i < len; i++) {
LinkInfo info = stateList.get(i);
if (info.isFace()) {// 表情符排版
Bitmap faceBmp = StateFaceModel.getInstance()
.getSmallFaceIcon(info.getContent());
int xLen = faceBmp.getWidth();
txtCanvas.drawBitmap(faceBmp, curLen + 2, 0, txtPaint);
curLen += xLen + 4;
continue;
}
String strContent = info.getContent();
strContent = strContent.replaceAll("\n", " ");
float xLen = txtPaint.measureText(strContent);
//由于x的值一直降低,所以文字能够滚动
txtCanvas.drawText(strContent, curLen, y, txtPaint); //<span style="font-family: Arial, Helvetica, sans-serif;">txtCanvas早drawtext.txtBmp上也自然也带有这些text</span> curLen += xLen;
}
canvas.drawBitmap(txtBmp, left, 0, paint);
} catch (Exception ex) {
ex.printStackTrace();
}
} @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
txtBmp = null;
setTxtBmp();
}
}

代码:http://download.csdn.net/detail/baidu_nod/7736733

android怎样写一个循环文字滚动的TextView的更多相关文章

  1. android 开发 写一个RecyclerView布局的聊天室,并且添加RecyclerView的点击事件

    实现思维顺序: 1.首先我们需要准备2张.9的png图片(一张图片为左边聊天泡泡,一个图片为右边的聊天泡泡),可以使用draw9patch.bat工具制作,任何图片导入到drawable中. 2.需要 ...

  2. Android 自己写一个打开图片的Activity

    根据记忆中eoe的Intent相关视频,模仿,写一个打开图片的Activity 1.在主Activity的button时间中,通过设置action.category.data打开一个图片.这时代码已经 ...

  3. 【Vue.js】代码优化:在dom中加一行v-if就可少写一个循环类方法

    [问题描述] 把当前用户的购物车中(cartList),商品(good)选中字段checked = true的商品在订单页面中进行展示出来. [一般做法](两次循环) 首先取出当前用户的购物车列表,循 ...

  4. 自己写一个jQuery垂直滚动栏插件(panel)

    html中原生的滚动栏比較难看,所以有些站点,会自己实现滚动栏,导航站点hao123在一个側栏中,就自己定义了垂直滚动栏,效果比較好看,截图例如以下: watermark/2/text/aHR0cDo ...

  5. 在Android 下写一个检测软件版本号 以自动升级APP 的插件

    直接上图上代码: 1.插件类的编写 工程目录结构图: 代码如下: package org.apache.cordova.versionupdate; import org.apache.cordova ...

  6. Android学习--写一个发送短信的apk,注意布局文件的处理过程!!!

    刚开始写Android程序如图发现使用了findViewById方法之后输出的话居然是null(空指针错误),也就是说这个方法没有成功.网上说这样写是在activity_main .xml去找这个ID ...

  7. 用android去写一个小程序

    前言: 软工的一个小作业:实现"黄金分割小游戏", 需要结对编程,队友:陈乐云    共用时两天. 早期思路设计: 采用键值对的形式,以Map作为存储结构.优点:能够将数据与用户对 ...

  8. Android下写一个永远不会被KILL掉的进程/服务

    Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用.当系统觉得当前的资源非常有限的时候,为了保证一些优先级高的程序能运行,就会杀掉一些 ...

  9. Android Studio 制作一个循环播报的效果

    这个就是用到了一个TextView 控件,直接上代码. <TextView android:id="@+id/tv_7" android:layout_width=" ...

随机推荐

  1. android获取在res文件下的图片资源

    //得到该图片的id(name 是该图片的名字,"drawable" 是该图片存放的目录,getPackageName()是应用程序的包) int resID = getResou ...

  2. 利用FTP将Linux文件备份到Windows

    windows:Windows Server 2008 linux: CentOS release 5.5 (Final)       首先在windows上安装好FTP,本人使用的是Windows ...

  3. 完整版的strcpy函数

    char *strcpy(char *strDest,const char *strSrc) { assert((strDest!=NULL) && (strSrc!=NULL)); ...

  4. Mysql 5.7.9 cmake boost.cmake 处理

    环境Centos 6.7 x64 mininal 今天突然编译Mysql 5.7.9 按之前的cmake .的方式 发现报错了..提示 需要boost -- BOOST_INCLUDE_DIR /us ...

  5. CClientDC

    CClientDC(客户区设备上下文)用于客户区的输出,它在构造函数中封装了GetDC(),在析构函数中封装了ReleaseDC()函数.一般在响应非窗口重画消息(如键盘输入时绘制文本.鼠标绘图)绘图 ...

  6. 1.1 语言与平台 [Java]

    Java语言是静态类型.面向对象的语言: Java平台是提供运行时环境的软件: 生产和使用Java代码的整个过程:.java (javac) .class (类加载器) 转换后的.class (解释器 ...

  7. redis常见命令

    一.介绍 1.Redis是什么 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统.Redis提供了一些丰富 ...

  8. scrapy1.1入门用例简介-2

    写一个小的scrapy project,爬取相关网页内容并保存为.json文件 0.创建project,genspider等. 1.修改items.py,内容如下: 2.修改dmoz.py,内容如下: ...

  9. vim编辑器中撤销和恢复操作

    在VIM编辑器下切换至命令行模式: 撤销: u 恢复: ctrl + r

  10. Cocos2d粒子系统二

    粒子系统的属性: 粒子的发射速度 重力模式(模式A): 重力 方向 速度 +- 变动 切向加速度 +- 变动 径向加速度 +- 变动 半径模式(模式B): 开始半径 +- 变动 结束半径 +- 变动 ...