Java 在Android中显示类似字幕的滚动文本
我正在开发Android应用程序,主要目的是在底部显示CNN突发新闻样式的栏和一些图片。我创建了两个自定义视图,一个用于显示照片,另一个用于显示工具栏。它在指定的时间内一次显示一张图片,并将当前图片与队列中的下一张图片交换 我使用canvas、onDraw()和handler.postDelayed为底部栏中的文本设置动画。这种解决办法效果不佳。文本移动不平滑,尤其是在交换图像时 我应该用什么来代替画布?是否有任何基于OpenGL的库可以使此任务相对轻松?我曾尝试使用AndEngine,但它缺乏文档和线程问题使我不再使用它Java 在Android中显示类似字幕的滚动文本,java,android,opengl-es,android-canvas,Java,Android,Opengl Es,Android Canvas,我正在开发Android应用程序,主要目的是在底部显示CNN突发新闻样式的栏和一些图片。我创建了两个自定义视图,一个用于显示照片,另一个用于显示工具栏。它在指定的时间内一次显示一张图片,并将当前图片与队列中的下一张图片交换 我使用canvas、onDraw()和handler.postDelayed为底部栏中的文本设置动画。这种解决办法效果不佳。文本移动不平滑,尤其是在交换图像时 我应该用什么来代替画布?是否有任何基于OpenGL的库可以使此任务相对轻松?我曾尝试使用AndEngine,但它缺乏
public class Infobar extends View {
private List<Message> messages;
private Handler handler;
private Paint boxPaint;
private Paint defaultTextPaint;
private Paint importantTextPaint;
private long offset = 0;
private long maxOffset = 1000;
private int textWidth = 1000;
private int textHeight = 50;
private int measuredWidth;
private int measuredHeight;
private Runnable animateRunnable = new Runnable() {
public void run() {
animateMessage();
}
};
long startTime = new Date().getTime();
private int backgroundCol = Color.parseColor("#ffff00");
private int textColor = Color.parseColor("#000000");
private static final int FRAME_DELAY = 10;
private static final int FRAME_SHIFT = 3;
private static final int EMPTY_SPACE = 2;
private static final String SEPARATOR = " ✩ ";
private static final int TEXT_SIZE = 35;
public Infobar(Context context, AttributeSet attrs) {
super(context, attrs);
handler = new Handler();
messages = new ArrayList<Message>();
boxPaint = new Paint();
defaultTextPaint = new Paint();
defaultTextPaint.setColor(getResources().getColor(R.color.info_bar_default_text_color));
importantTextPaint = new Paint();
importantTextPaint.setColor(getResources().getColor(R.color.info_bar_important_text_color));
handler.postDelayed(animateRunnable, FRAME_DELAY);
}
public void setMessagesList(List<Message> list) {
messages = list;
}
public void setBackgroundColor(String color) {
backgroundCol = Color.parseColor(color);
}
public void setTextColor(String color) {
textColor = Color.parseColor(color);
}
public List<Message> getMessagesList() {
return messages;
}
private String getMessagesString() {
StringBuilder builder = new StringBuilder();
for(Message message : messages) {
builder.append(message.content);
if(messages.indexOf(message) != (messages.size() - 1)) {
builder.append(SEPARATOR);
}
}
return builder.toString();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measuredWidth = getMeasuredWidth();
measuredHeight = getMeasuredHeight();
}
@Override
protected void onDraw(Canvas canvas) {
drawBackground(canvas, false);
drawMessage(canvas, getMessagesString());
super.onDraw(canvas);
}
private void drawBackground(Canvas canvas, boolean important) {
boxPaint.setColor(backgroundCol) ;
canvas.drawRect(0, 0, measuredWidth, measuredHeight, boxPaint);
}
private void drawMessage(Canvas canvas, String message) {
defaultTextPaint.setTextSize(TEXT_SIZE);
Rect bounds = new Rect();
defaultTextPaint.getTextBounds(message, 0, message.length(), bounds);
defaultTextPaint.setColor(textColor);
textWidth = bounds.width();
textHeight = bounds.height();
int positionX = measuredWidth - (int)offset;
int positionY = measuredHeight - textHeight/2;
if(offset > (measuredWidth + textWidth)) {
offset = 0;
positionX = measuredWidth;
}
canvas.drawText(message, positionX, positionY, defaultTextPaint);
}
private void animateMessage() {
offset += FRAME_SHIFT;
//offset = Math.round((new Date().getTime() - startTime) * 0.2) % (measuredWidth + textWidth);
invalidate();
handler.removeCallbacks(animateRunnable);
handler.postDelayed(animateRunnable, FRAME_DELAY);
}
}
公共类信息栏扩展视图{
私人列表消息;
私人经办人;
私人涂料;
私人涂料;
私人涂料;重要涂料;
专用长偏移=0;
专用长最大偏移量=1000;
私有int textWidth=1000;
私有整数文本高度=50;
测量宽度;
测量高度;
private Runnable animaterunable=new Runnable(){
公开募捐{
动画消息();
}
};
long startTime=new Date().getTime();
private int backgroundCol=Color.parseColor(“#ffff00”);
private int textColor=Color.parseColor(“#000000”);
专用静态最终整数帧延迟=10;
私有静态最终整数帧_移位=3;
私有静态最终int空_空间=2;
专用静态最终字符串分隔符=”✩ ";
私有静态最终整型文本大小=35;
公共信息栏(上下文、属性集属性){
超级(上下文,attrs);
handler=新的handler();
messages=newarraylist();
boxPaint=新油漆();
defaultTextPaint=新绘制();
defaultTextPaint.setColor(getResources().getColor(R.color.info\u bar\u default\u text\u color));
importantTextPaint=新油漆();
importantTextPaint.setColor(getResources().getColor(R.color.info\u bar\u important\u text\u color));
postDelayed(animateRunnable,FRAME_DELAY);
}
公共无效设置消息列表(列表){
消息=列表;
}
公共void setBackgroundColor(字符串颜色){
backgroundCol=Color.parseColor(Color);
}
公共void setTextColor(字符串颜色){
textColor=Color.parseColor(Color);
}
公共列表getMessagesList(){
返回消息;
}
私有字符串getMessagesString(){
StringBuilder=新的StringBuilder();
用于(消息:消息){
builder.append(message.content);
if(messages.indexOf(message)!=(messages.size()-1)){
builder.append(分隔符);
}
}
返回builder.toString();
}
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
超级测量(宽度测量、高度测量);
measuredWidth=getMeasuredWidth();
measuredHeight=getMeasuredHeight();
}
@凌驾
受保护的void onDraw(画布){
牵引地面(帆布,假);
drawMessage(canvas,getMessagesString());
super.onDraw(帆布);
}
私有void退税场(画布,布尔值重要){
boxPaint.setColor(背景色);
画布.drawRect(0,0,测量宽度,测量高度,boxPaint);
}
私有void drawMessage(画布、字符串消息){
defaultTextPaint.setTextSize(文本大小);
Rect bounds=new Rect();
defaultTextPaint.getTextBounds(message,0,message.length(),bounds);
defaultTextPaint.setColor(textColor);
textWidth=bounds.width();
textHeight=bounds.height();
int位置X=测量宽度-(int)偏移量;
int位置Y=测量高度-文本高度/2;
如果(偏移量>(测量宽度+文本宽度)){
偏移量=0;
位置X=测量的宽度;
}
canvas.drawText(消息、位置X、位置Y、defaultTextPaint);
}
私有void animateMessage(){
偏移+=帧移位;
//offset=Math.round((new Date().getTime()-startTime)*0.2)%(measuredWidth+textWidth);
使无效();
handler.removeCallbacks(animateRunnable);
postDelayed(animateRunnable,FRAME_DELAY);
}
}
除非有特殊原因,否则您可以使用TextView的内置字幕功能:
<LinearLayout>
<TextView
android:id="@+id/myText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="Your long text goes here. You can also change it programmatically" />
</LinearLayout>
发布你的代码,应该没有理由这么慢。检查TextView的代码,有字幕滚动,它没有那么复杂。基本上它是关于画布的。translateI将删除对getMessagesString()和其他函数的不必要调用,这些函数的输出应存储在变量中,我会让你知道它是否有改进。
TextView myText=(TextView) findViewById(R.id.myText);
myText.setSelected(true); //needs this to work