首页 > 代码库 > 自动滚动的Textview

自动滚动的Textview

   又到了写博博的时候了!大家还好吧!

   开始做机顶盒了,所以这里就有很多的界面需要做成一个自动化的界面。因为遥控盒手机触摸毕竟不一样咯!这里而且要方便大众的视觉体验的话,我们必须要考虑到这些因素。当然,我觉着,这次的自动滚动效果一定对大家也很有帮助的哦!

  我们只要写一个类来继承我布局文件里面写的一个TextView就ok啦。









package
com.example.myscroltextview.view; import java.util.ArrayList; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.widget.TextView; /** * 垂直滚动的textview * * @author Catherine.Brian.William * */ public class VertailScrollTextView extends TextView { public VertailScrollTextView(Context context) { super(context); init(); } public VertailScrollTextView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public VertailScrollTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } Handler handler; /** * 是否在滚动 */ boolean scrolling = false; /** * 当前的位移 */ float currentY; /** * 每次滚动的距离 */ float speed = 0.2f; /** * 要显示的text */ String scrollText = ""; /** * 真实宽度,在配置width="xxdp"里起作用 */ private int exactlyWidth = -1; /** * 真实高度,在配置height="xxdip"里起作用 */ private int exactlyHeight = -1; /** * 实际高度:所有字显示完全需要的高度 */ float absloutHeight = 0; /** * handler发消息的时间间隔 */ int delayTime = 50; /** * 每行的字符串 */ ArrayList<String> lineStrings; Paint mPaint; private static final int DY = 20; // 每一行的间隔 /** * 初始化 */ private void init() { // 非高亮部分 mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setTextSize(20); mPaint.setColor(Color.WHITE); mPaint.setTypeface(Typeface.SERIF); handler = new Handler() { @Override public void handleMessage(Message msg) { if (absloutHeight <= getHeight()) { currentY = 0; stop(); return; } switch (msg.what) { case 0: currentY = currentY - speed; resetCurrentY(); invalidate(); handler.sendEmptyMessageDelayed(0, delayTime); break; } super.handleMessage(msg); } /** * 重置currentY(当currentY超过absolutHeight时,让它重置为0) */ private void resetCurrentY() { if (currentY >= absloutHeight || currentY <= -absloutHeight || getHeight() <= 0) { currentY = 0; } } }; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureWidth(widthMeasureSpec); int height = MeasureHeight(width, heightMeasureSpec); setMeasuredDimension(width, height); currentY = 0; if (height < absloutHeight) { play(); } else { stop(); } } /** * 测量宽度 * * @param widthMeasureSpec * @return */ private int MeasureWidth(int widthMeasureSpec) { int mode = MeasureSpec.getMode(widthMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); // 如果时候wrap_content if (mode == MeasureSpec.AT_MOST) { double abwidth = getPaint().measureText(scrollText); width = Math.min((int) Math.rint(abwidth), width); exactlyWidth = -1; } // 精确宽度 if (mode == MeasureSpec.EXACTLY) { exactlyWidth = width; } return width; } /** * 测量高度 * * @param width * @param heightMeasureSpec * @return */ private int MeasureHeight(int width, int heightMeasureSpec) { int mode = MeasureSpec.getMode(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); generateTextList(width); int lines = lineStrings.size(); absloutHeight = lines * (getLineHeight() + DY) + getPaddingBottom() + getPaddingTop(); // 如果是wrap_content if (mode == MeasureSpec.AT_MOST) { height = (int) Math.min(absloutHeight, height); exactlyHeight = -1; } else if (mode == MeasureSpec.EXACTLY) { exactlyHeight = height; } return height; } /** * 生成多行字符串列表 * * @param MaxWidth */ public void generateTextList(int MaxWidth) { lineStrings = new ArrayList<String>(); String remain = scrollText; while (!remain.equals("")) { String line = getLineText(MaxWidth, remain); lineStrings.add(line); remain = remain.substring(line.length(), remain.length()); } } /** * 获取一行的字符 * * @param MaxWidth * @param remain * @return */ private String getLineText(int MaxWidth, String str) { // 真实行 StringBuffer trueStringBuffer = new StringBuffer(); // 临时行 StringBuffer tempStringBuffer = new StringBuffer(); for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); String add = ""; if (!isChinese(c) && isENWordStart(str, i)) { int place = getNextSpecePlace(i, str); // 找到下一个空格 if (place > -1) { add = str.substring(i, place) + " "; if (getPaint().measureText(add) > MaxWidth) { add = "" + c; } else { i = place; } } else { add = "" + c; } } else { add = "" + c; } tempStringBuffer.append(add); String temp = tempStringBuffer.toString(); float width = getPaint().measureText(temp.toString()); if (width <= MaxWidth) { trueStringBuffer.append(add); } else { break; } } return trueStringBuffer.toString(); } /** * 找到下一个空格的地方 * * @param i * @param str * @return */ int getNextSpecePlace(int i, String str) { for (int j = i; j < str.length(); j++) { char c = str.charAt(j); if (c == ‘ ‘) { return j; } } return -1; } /** * 是否为英文单词的首字母 * * @param str * @param i * @return */ boolean isENWordStart(String str, int i) { if (i == 0) { return true; } else if (str.charAt(i - 1) == ‘ ‘) { return true; } return false; } /** * 设置textview的文字 * * @param scrollText */ public void setScrollText(String scrollText) { this.scrollText = scrollText; // setText(scrollText); reset(); } public String getScrollText() { return scrollText; } /** * 重置 */ private void reset() { requestLayout(); invalidate(); currentY = 0; } /** * 开始滚动 */ public void play() { if (!scrolling) { handler.sendEmptyMessage(0); scrolling = true; } } /** * 停止滚动 */ public void stop() { if (scrolling) { handler.removeMessages(0); scrolling = false; } } /** * 更改滚动状态 */ public void updateScrollStatus() { if (scrolling) { stop(); } else { play(); } } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); float x = getPaddingLeft(); float y = getPaddingTop(); float lineHeight = getLineHeight() + DY; float textSize = getPaint().getTextSize(); for (int i = 0; i < lineStrings.size(); i++) { // currentY+=50; y = lineHeight * i + textSize + currentY; float min = 0; if (exactlyHeight > -1) { min = Math.min(min, exactlyHeight - absloutHeight); } if (y < min) { y = y + absloutHeight; } else if (y >= min && y < textSize + min) { // 如果最顶端的文字已经到达需要循环从下面滚出的时候 System.out.println("x:" + x + "y:" + y); } if (y >= absloutHeight) { // 如果最底端的文字已经到达需要循环从上面滚出的时候 System.out.println("x:" + x + "y:" + y); y = y - absloutHeight; } canvas.drawText(lineStrings.get(i), x, y, mPaint); } } /** * 判断是否为中文 * * @param c * @return */ private static final boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { return true; } return false; } }