您的位置:首页 > 移动开发 > Android开发

Android实现字幕滚动程序并优化

2017-05-19 14:17 417 查看
  Android实现字幕滚动,不使用内置的属性,而是重新定义一个类继承自AppCompatTextView来实现,可以控制文字滚动速度且让其匀速滚动,首先定义一个方法得到屏幕宽度和文本长度
public void scrollTextView(WindowManager windowManager, String text) {
// 获取画笔paint
paint = this.getPaint();
//paint.setColor(Color.BLACK);
//使用抗锯齿效果,使文本更加平滑
paint.setSubpixelText(true);
paint.setAntiAlias(true);
//设置文字大小和颜色
paint.setTextSize(50);
this.setTextColor(Color.BLACK);
// 得到文字
this.text = text;
textLength = paint.measureText(text);// 获得当前文本字符串长度
viewWidth = this.getWidth();// 获取view的宽度;
if (viewWidth == 0) {
if (windowManager != null) {
// 获取当前屏幕的属性
Display display = windowManager.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
viewWidth = size.x;// 获取屏幕宽度
}
}
xPos = textLength;
currentLength = viewWidth + textLength;
changeLength = viewWidth + textLength * 2;// 使文字到最左边
// 文字的大小+距顶部的距离
yPos = this.getTextSize() + this.getPaddingTop();
}
  重写onDraw方法
@Override
protected void onDraw(Canvas canvas) {
/**
* 两次进入onDraw函数的时间间隔
*/
time1 =System.currentTimeMillis();
if (time2!=0){
timeDesc=time1-time2;
}
speed=getSpeed();
TIME=getTIME();
//文字从最右边开始滚动
if (isStarting) {
canvas.drawColor(Color.WHITE);
canvas.drawText(text, currentLength - xPos, yPos, paint);
//每次滚动速度
if (timeDesc!=0){
if (TIME!=0){
xPos += speed/TIME*timeDesc;//根据时间差计算滚动距离
}
else {
xPos =xPos+ 0;
}
}
else {
xPos += speed;
}
// 当文字滚动到屏幕的最左边
if (xPos >= changeLength) {//最后一个文字到达最左边时
// 把文字设置到最右边开始
xPos = currentLength - viewWidth;
}

}
time2 = time1;
super.onDraw(canvas);
}
然后在MainActivity中实现一个定时器,控制刷新时间
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
// handler自带方法实现定时器
try {
handler.postDelayed(this, TIME);
marquee.invalidate();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
MainActivity中的onCreate方法控制刷新时间和速度
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
marquee = (MarqueeView) findViewById(R.id.scrollView);
//设置刷新时间
timeChange = (EditText) findViewById(R.id.time_text1);
timeButton = (Button) findViewById(R.id.time_button1);
timeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
timeText = timeChange.getText().toString();
try {
timeTxt = Integer.parseInt(timeText);
if (timeTxt != 0) {
marquee.setTIME(timeTxt);
} else {
marquee.setTIME(0);
Log.i("speed", speedChange.getText() + "");
}
} catch (Exception e) {
marquee.setTIME(0);
//marquee.setSpeed(0);
Log.i("speed", speedChange.getText() + "");
}
}
});

//设置滚动速度
speedChange = (EditText) findViewById(R.id.speed_text1);
speedButton = (Button) findViewById(R.id.speed_button1);
speedButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
speedText = speedChange.getText().toString();
try {
speedTxt = Integer.parseInt(speedText);
if (speedTxt != 0) {
marquee.setSpeed(speedTxt);
Log.i("speed", speedChange.getText() + "");
} else {
marquee.setSpeed(0);
}
} catch (Exception e) {
marquee.setTIME(3);
marquee.setSpeed(0);
}
}
});
//intent所附带的额外数据
String path = this.getIntent().getStringExtra("path");
if (path != null) {
marquee.scrollTextView(this.getWindowManager(),
path);
marquee.startScroll();
} else {
marquee.scrollTextView(this.getWindowManager(),
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
marquee.startScroll();
}
handler.postDelayed(runnable, TIME);
}

在activity_main中需定义一个自定义控件,两个button和两个EditText,自定义控件需要标注完整的包名。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.sun.scrollwords.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.sun.scrollwords.MarqueeView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#CCCCCC"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="#000000"
android:textSize="50sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/time_text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="刷新时间是13"
android:maxLines="1"
android:textSize="30sp" />
<Button
android:id="@+id/time_button1"
android:layout_wi
4000
dth="wrap_content"
android:layout_height="wrap_content"
android:text="更改时间"
android:textSize="30sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/speed_text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="速度为3"
android:maxLines="1"
android:textSize="30sp" />
<Button
android:id="@+id/speed_button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="更改速度"
android:textSize="30sp" />
</LinearLayout>
</LinearLayout>
以上代码可以控制速度和刷新时间,为了进一步优化程序,可以将文字转变为图片格式,这样不用每次都计算文字的位置,可以减少CPU的占用率。将文字转为图片格式的方法为:
public static Bitmap textToBitmap(String text, int textSize) {
TextPaint textPaint = new TextPaint();
textPaint.setColor(Color.BLACK);
//使用抗锯齿效果,使文本更加平滑
textPaint.setSubpixelText(true);
textPaint.setAntiAlias(true);
textPaint.setTextSize(textSize);
textLen = textPaint.measureText(text);
//textLen是文本的宽度,必须以文本宽度分割,否则文本过长时会导致换行
StaticLayout layout = new StaticLayout(text, textPaint, Math.round(textLen),
Layout.Alignment.ALIGN_NORMAL, 1.3f, 0.0f, true);
Bitmap bitmap = Bitmap.createBitmap(layout.getWidth() + 10,
layout.getHeight() + 10, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.translate(10, 10);
canvas.drawColor(Color.WHITE);
layout.draw(canvas);
return bitmap;
}
然后需要实现图片自动滚动,定义方法startMarquee,并使用ValueAnimator创建过程并不断更新位置
public void startMarquee(int startLeft, int startTop, int toLeft, int toTop, long duration) {
mStartLeft = startLeft;
mStartTop = startTop;
mToLeft = toLeft;
mToTop = toTop;
// 使用ValueAnimator创建一个过程
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(duration);
//使图片匀速滚动
 valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
// 不断重新计算上下左右位置
float fraction = (Float) animator.getAnimatedValue();
int currentLeft = (int) ((mToLeft - mStartLeft) * fraction + mStartLeft);
int currentTop = (int) ((mToTop - mStartTop) * fraction + mStartTop);
if (mDestRect == null) {
mDestRect = new Rect(currentLeft, currentTop, currentLeft + mBitWidth,
currentTop + mBitHeight);
}
mDestRect.left = currentLeft;
mDestRect.right = currentLeft + mBitWidth;
mDestRect.top = currentTop;
mDestRect.bottom = currentTop + mBitHeight;
Log.i("currentLeft", currentLeft + "");
}
});
valueAnimator.setRepeatCount(valueAnimator.INFINITE);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.start();
}
public void startMarquee() {
startTranslate(screenWidth, 0, -mBitWidth, 0, 3500);

}


在MainActivity中实现调用,并实现定时器决定刷新时间间隔
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawBitmapView = new DrawBitmapView(this);
setContentView(drawBitmapView, new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,
ActionBar.LayoutParams.MATCH_PARENT));
drawBitmapView.startMarquee();
handler2.postDelayed(runnable2, TIME2);
}
Handler handler2 = new Handler();
Runnable runnable2 = new Runnable() {
@Override
public void run() {
// handler自带方法实现定时器
try {
handler2.postDelayed(this, TIME2);
try {
drawBitmapView.invalidate();
Log.i("TIME", System.currentTimeMillis() + "");
} catch (NullPointerException e) {
e.printStackTrace();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.i("runnable", "exception... ");
}
}
};
如果需要在界面添加EditText和Button,由于布局是手动加载完成的,所以添加控件也需要Java代码实现,最后的onCreate代码如下:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout myLayout = new RelativeLayout(this);
myLayout.setBackgroundColor(Color.WHITE);
drawBitmapView = new BitmapView(this);

timeButton2 = new Button(this);
timeButton2.setText("更改刷新时间");
timeText2= new EditText(this);
timeText2.setHint("刷新时间为13");
//为空间设置ID,需要在res/values下新建一个文件,添加控件id
timeButton2.setId(R.id.timeButton2);
timeText2.setId(R.id.timeText2);
drawBitmapView.setId(R.id.drawBitmapView);
//定义好父容器并设置相关属性
final RelativeLayout.LayoutParams bitmapParams =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
bitmapParams.addRule(RelativeLayout.BELOW,timeButton2.getId());
bitmapParams.addRule(RelativeLayout.CENTER_HORIZONTAL);

//设置Button的布局参数
RelativeLayout.LayoutParams buttonParams =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);

buttonParams.addRule(RelativeLayout.CENTER_VERTICAL);
buttonParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
//设置EditText的布局参数
RelativeLayout.LayoutParams speedParams =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);

speedParams.addRule(RelativeLayout.LEFT_OF, timeButton2.getId());
speedParams.addRule(RelativeLayout.ALIGN_TOP,timeButton2.getId());

//将布局添加到父容器中
myLayout.addView(drawBitmapView, bitmapParams);
myLayout.addView(timeButton2, buttonParams);
myLayout.addView(timeText2,speedParams);

//设置显示父容器
setContentView(myLayout);
timeButton2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
timeTxt2 = timeText2.getText().toString();
try {
time2= Integer.parseInt(timeTxt2);
if (time2 != 0) {
TIME2=time2;
} else {
TIME2=0;
}
} catch (Exception e) {
TIME2=0;
}
}
});
drawBitmapView.startMarquee();
handler2.postDelayed(runnable2, TIME2);
}

Handler handler2 = new Handler();
Runnable runnable2 = new Runnable() {
@Override
public void run() {
// handler自带方法实现定时器
try {

handler2.postDelayed(this, TIME2);
try {
drawBitmapView.invalidate();
} catch (NullPointerException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息