记录一个Android中简单实现垂直跑马灯功能的方法:实现了垂直跑马灯的功能。记录一下以便日后查看:

首先在MainActivity下新建一个名为ScrollTextView的.java 文件
ScrollTextView.java代码如下:
其中判断分行结束符以  "\n"  为准。。。
package com.example.chenhy.pmd;import java.util.ArrayList;import android.content.Context;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.TextView;/*** ??????????* @author HeJx**/
public class ScrollTextView extends TextView {/*** ??е??????*/ArrayList<String> lineStrings;/*** ?????λ??*/float currentY;/*** ??????????*/Handler handler;/*** ??????text*/String scrollText="";/*** ??????,??????width="xxdp"????????*/private int exactlyWidth = -1;/*** ??????,??????height="xxdip"???????? */private int exactlyHeight = -1;private float index = 0;public String getScrollText() {return scrollText;}public void setScrollText(String scrollText) {this.scrollText = scrollText;reset();}/*** ????*/private void reset() {if(lineStrings!=null)lineStrings.clear();stop();currentY = 0;absloutHeight = 0;this.setText("");if(handler!=null){handler.removeMessages(0);handler.removeMessages(1);handler.removeMessages(2);handler.removeMessages(3);}requestLayout();invalidate();}public ScrollTextView(Context context, AttributeSet attrs) {super(context, attrs);init();}public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}public ScrollTextView(Context context) {super(context);init();}/*** ????????*/boolean scrolling = false;/*** ?????????????????????????*/float absloutHeight = 0;/*** handler????????????*/private  int delayTime = 10;  //???????private   int stopTime = 0;  //??????public int getDelayTime() {return delayTime;
}public void setDelayTime(int delayTime) {this.delayTime = delayTime;
}public int getStopTime() {return stopTime;
}public void setStopTime(int stopTime) {this.stopTime = stopTime;
}/*** ??ι????????*/float speed = 0.5f;/*** ?????*/void init() {handler = new Handler() {@Overridepublic void handleMessage(Message msg) {if (absloutHeight <= getHeight()) {currentY = 0;stop();return;}switch (msg.what) {case 0: {currentY = currentY - speed;//resetCurrentY();invalidate();boolean flag = true;if (currentY >= absloutHeight || currentY <= -absloutHeight) {flag = false;handler.sendEmptyMessageDelayed(3, stopTime);}if(flag){if (currentY >=  index|| currentY <= -index || getHeight() <= 0) {handler.sendEmptyMessageDelayed(2, stopTime);}else{handler.sendEmptyMessageDelayed(0, delayTime);}}break;}case 1: {currentY += msg.arg1;resetCurrentY();invalidate();}break;case 2:{index = index+absloutHeight/lineStrings.size();stop();handler.sendEmptyMessageDelayed(0, delayTime);}break;case 3:{currentY = 0;index = absloutHeight/lineStrings.size();;stop();handler.sendEmptyMessageDelayed(0, delayTime);}}}/*** ????currentY????currentY????absloutHeight????????????0??*/private void resetCurrentY() {if (currentY >= absloutHeight || currentY <= -absloutHeight || getHeight() <= 0) {currentY = 0;}}};}/*** ??δ???????????y????*/float lastY = 0;/*** ?true????????????*/boolean needStop;public void pause() {if (scrolling) {stop();needStop = true;}}public void goOn() {if (needStop) {play();needStop = false;}}/* @Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:distanceY = lastY = event.getY();distanceX = event.getX();pause();return true;case MotionEvent.ACTION_MOVE:float dy = event.getY() - lastY;lastY = event.getY();// currentY = currentY + dy;Message msg = Message.obtain();msg.what = 1;msg.arg1 = (int)dy;handler.sendMessage(msg);return true;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:goOn();float y = event.getY() - distanceY;float x = event.getX() - distanceX;if (Math.sqrt(y * y + x * x) < performUpScrollStateDistance) {updateScrollStatus();}return true;}return super.onTouchEvent(event);}
*//*** ???????????С??????????????????????????????????????????????????*/public static final long performUpScrollStateDistance = 5;public float distanceY = 0;public float distanceX = 0;/*** ?????????*/public void updateScrollStatus() {if (scrolling) {stop();} else {play();}}/*** ???????*/public void play() {if (!scrolling) {handler.sendEmptyMessage(0);scrolling = true;}}/*** ??????*/public void stop() {if (scrolling) {handler.removeMessages(0);scrolling = false;}}@Overrideprotected 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_contentif (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() + getPaddingBottom() + getPaddingTop();index = absloutHeight/lines;// ?????wrap_contentif (mode == MeasureSpec.AT_MOST) {height = (int)Math.min(absloutHeight, height);exactlyHeight = -1;} else if (mode == MeasureSpec.EXACTLY) {exactlyHeight = height;}return height;}/*** ????????????????* * @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;}/*** ?????е????* * @param MaxWidth* @param str* @return*/private String getLineText(int MaxWidth, String str) {// ?????StringBuffer trueStringBuffer = new StringBuffer();// ?????StringBuffer tempStringBuffer = new StringBuffer();boolean isLine;for (int i = 0; i < str.length(); i++) {isLine = false;char c = str.charAt(i);String add = "";// ???c????????????????????й???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 {if(c=='\n') { //?ж????????е?????isLine = true;add = "" + c;}elseadd = "" + c;}tempStringBuffer.append(add);String temp = tempStringBuffer.toString();float width = getPaint().measureText(temp.toString());if(isLine)break;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 == '\n') {return j;}}return -1;}/*** ?????????????б?* * @param MaxWidth*/public void generateTextList(int MaxWidth) {lineStrings = new ArrayList<String>();// String remain = scrollText;String[] contenx = scrollText.split("\n");                   //这里的"\n" 是标志for (String string : contenx) {lineStrings.add(string);}/*   while (!remain.equals("")) {String line = getLineText(MaxWidth, remain);lineStrings.add(line);remain = remain.substring(line.length(), remain.length());}*/};@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);float x = getPaddingLeft();float y = getPaddingTop();float lineHeight = getLineHeight();float textSize = getPaint().getTextSize();for (int i = 0; i < lineStrings.size(); i++) {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) {//???????????????????????????????????????canvas.drawText(lineStrings.get(i), x, y + absloutHeight, getPaint());}if (y >= absloutHeight) {//???????????????????????????????????????canvas.drawText(lineStrings.get(i), x, y, getPaint());y = y - absloutHeight;}canvas.drawText(lineStrings.get(i), x, y, getPaint());}}/*** ?ж?????????* * @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;}}



布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.example.chenhy.pmd.MainActivity"><com.example.chenhy.pmd.ScrollTextViewandroid:id="@+id/marqueeview"android:layout_width="match_parent"android:layout_height="match_parent"android:textSize="10sp"></com.example.chenhy.pmd.ScrollTextView>
</LinearLayout>
最后是mainactivity中的代码
package com.example.chenhy.pmd;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ScrollTextView marqueeView = (ScrollTextView) findViewById(R.id.marqueeview);marqueeView.setScrollText("塞纳河畔 左岸的咖啡\n" +"我手一杯 品尝你的美\n" +"留下唇印的嘴\n" +"花店玫瑰 名字写错谁\n" +"告白气球 风吹到对街\n" +"微笑在天上飞\n" +"你说你有点难追 想让我知难而退\n" +"礼物不需挑最贵 只要香榭的落叶\n" +"喔 营造浪漫的约会 不害怕搞砸一切\n" +"拥有你就拥有 全世界\n" +"亲爱的 爱上你 从那天起\n" +"甜蜜的很轻易\n" +"亲爱的 别任性 你的眼睛\n" +"在说我愿意\n" +"塞纳河畔 左岸的咖啡\n" +"我手一杯 品尝你的美\n" +"留下唇印的嘴\n" +"花店玫瑰 名字写错谁\n" +"告白气球 风吹到对街\n" +"微笑在天上飞\n" +"你说你有点难追 想让我知难而退\n" +"礼物不需挑最贵 只要香榭的落叶\n" +"喔 营造浪漫的约会 不害怕搞砸一切\n" +"拥有你就拥有 全世界\n" +"亲爱的 爱上你 从那天起\n" +"甜蜜的很轻易\n" +"亲爱的 别任性 你的眼睛\n" +"在说我愿意\n" +"亲爱的 爱上你 恋爱日记\n" +"飘香水的回忆\n" +"一整瓶 的梦境 全都有你\n" +"搅拌在一起\n" +"亲爱的别任性 你的眼睛\n" +"在说我愿意"+"塞纳河畔 左岸的咖啡\n" +"我手一杯 品尝你的美\n" +"留下唇印的嘴\n" +"花店玫瑰 名字写错谁\n" +"告白气球 风吹到对街\n" +"微笑在天上飞\n" +"你说你有点难追 想让我知难而退\n" +"礼物不需挑最贵 只要香榭的落叶\n" +"喔 营造浪漫的约会 不害怕搞砸一切\n" +"拥有你就拥有 全世界\n" +"亲爱的 爱上你 从那天起\n" +"甜蜜的很轻易\n" +"亲爱的 别任性 你的眼睛\n" +"在说我愿意\n" +"塞纳河畔 左岸的咖啡\n" +"我手一杯 品尝你的美\n" +"留下唇印的嘴\n" +"花店玫瑰 名字写错谁\n" +"告白气球 风吹到对街\n" +"微笑在天上飞\n" +"你说你有点难追 想让我知难而退\n" +"礼物不需挑最贵 只要香榭的落叶\n" +"喔 营造浪漫的约会 不害怕搞砸一切\n" +"拥有你就拥有 全世界\n" +"亲爱的 爱上你 从那天起\n" +"甜蜜的很轻易\n" +"亲爱的 别任性 你的眼睛\n" +"在说我愿意\n" +"亲爱的 爱上你 恋爱日记\n" +"飘香水的回忆\n" +"一整瓶 的梦境 全都有你\n" +"搅拌在一起\n" +"亲爱的别任性 你的眼睛\n" +"在说我愿意");}
}
最后,上一张效果图

Android 中一个简单垂直跑马灯的实现相关推荐

  1. java 垂直走马灯多行,Android实现图文垂直跑马灯效果

    最近在维护老项目,老项目有一个地方需要修改,就是垂直跑马灯的问题,之前的垂直跑马灯是只有文字跑马灯,新版需要加上. 之前是用的MarqueeView,看了下源代码是只支持文字的,于是我就改了下原作者的 ...

  2. android linearlayout最大高度,Android中最简单最常用的LinearLayout线性布局

    原标题:Android中最简单最常用的LinearLayout线性布局 良好的布局设计对于UI界面至关重要,在前面也简单介绍过,目前Android中的布局主要有6种,创建的布局文件默认为Relativ ...

  3. 初识Android 制作一个简单的记账本

    初识Android 制作一个简单的记账本 主要功能 实现一个记账本页面 可以添加数据并更新到页面中 主要步骤 运行截图 主页面 点击红色按钮弹出添加页面 完成后自动更新到目录下 主要功能 实现一个记账 ...

  4. android新闻列表,Android中实现简单的新闻列表

    Android中实现简单的新闻列表 在刚开始写CSDN的时候,写过一篇 Android中通过ListView实现简单的新闻列表 最近看到有很多刚开始学习Android的同学需要源码.不好意思的是,那个 ...

  5. Android 实现一个简单的文件下载工具

    下载应该是每个App都必须的一项功能,不采用第三方框架的话,就需要我们自己去实现下载工具了.如果我们自己实现可以怎么做呢? 首先如果服务器文件支持断点续传,则我们需要实现的主要功能点如下: 多线程.断 ...

  6. Android中绘制简单几何图形和路径Path

    背景 我的博客:http://zhangsunyucong.top 马上就到2018年过年了,然后我又刚好有兴致,就来玩玩Android中的简单几何图形的绘制和使用Path类来绘制路径. Path和C ...

  7. 7.纯 CSS 创作一个 3D 文字跑马灯特效

    7.纯 CSS 创作一个 3D 文字跑马灯特效 原文地址:https://segmentfault.com/a/1190000014663038 感想:简单的从右到左动画 HTML代码: <di ...

  8. android实现计算器功能吗,利用Android实现一个简单的计算器功能

    利用Android实现一个简单的计算器功能 发布时间:2020-11-20 16:25:01 来源:亿速云 阅读:90 作者:Leah 今天就跟大家聊聊有关利用Android实现一个简单的计算器功能, ...

  9. android 时间戳 转日期格式,在Android中转换为简单日期格式或Unix时间戳日期?

    我收到日期(2015-03-20T06:34:01.831183 + 01:00)从服务器这不是简单的日期格式,我想这种类型的日期转换为简单的日期格式一样(yyyyMMddHHmmssSSSS)在An ...

最新文章

  1. idl结果显示窗口如何缩小_科学网—IDL 创建窗口 - 钱磊的博文
  2. Maven入门教程(一)
  3. python遍历链表_Python;链表和遍历!
  4. TCP/UDP的小事情
  5. android 个人理财系统,基于Android的个人理财系统的设计与实现
  6. 将 ext_net 连接到 router - 每天5分钟玩转 OpenStack(145)
  7. MySQL 5.6.20-enterprise-commercial的参数文件位置问题
  8. dbms数据库管理系统_DBMS中的数据库语言
  9. 20155210 网络攻防技术 实验三 免杀原理与实践
  10. Eureka的自我保护模式
  11. 在ubuntu20.04中安装MATLAB时常见问题及解决方法
  12. 卸载xftp7 安装xftp5后,点击xshell中打开xftp快捷按钮,提示“无法打开xftp”
  13. Jenkins企业应用
  14. Dubbo跟Spring Cloud哪个更好用?“微服务”第二代又赢了!
  15. 神经网络参数个数计算,神经网络的参数设置
  16. jme-旋转的双子星
  17. 欧姆定理验证,电阻的电压/电流/功率,电阻串联,电阻并联,电阻分压
  18. linux系统应用实验DNS的安装,DNS配置实验小结
  19. gazebo入门教程(二)建立简单模型
  20. uniapp 保存base64图片

热门文章

  1. U盘制作成启动盘后容量变小怎么恢复
  2. bmcl java_BMCL启动器
  3. 从细节最初判断一家公司
  4. PS安装插件提示无法加载扩展未正确签署解决方式(适用于mac/win)
  5. 个性化设置背景单机版五子棋(含可运行JS代码)
  6. struct page
  7. 小实战项目之——吃货联盟订餐系统
  8. RFID基础---频率、卡类型
  9. Docker-- 提高下载速度的方法
  10. c语言程序设计wav,WAV音频格式解析C代码