Android实现字幕滚动程序并优化
2017-05-19 14:17
417 查看
Android实现字幕滚动,不使用内置的属性,而是重新定义一个类继承自AppCompatTextView来实现,可以控制文字滚动速度且让其匀速滚动,首先定义一个方法得到屏幕宽度和文本长度
在activity_main中需定义一个自定义控件,两个button和两个EditText,自定义控件需要标注完整的包名。
在MainActivity中实现调用,并实现定时器决定刷新时间间隔
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(); } } };
相关文章推荐
- Android编程实现类似天气预报图文字幕垂直滚动效果的方法
- android TextView 垂直自动滚动字幕实现
- android TextView 垂直自动滚动字幕实现
- 微信小程序scroll-view实现字幕滚动
- Android实现字幕滚动的方法
- android TextView 垂直自动滚动字幕实现TextSwitcher
- Android 滚动字幕实现
- android TextView 垂直自动滚动字幕实现
- Android程序开发之ListView实现横向滚动(带表头与固定列)
- android TextView 垂直自动滚动字幕实现
- Android 滚动字幕实现
- android TextView 垂直自动滚动字幕实现
- Android之如何用TextView实现滚动字幕的效果【跑马灯】
- Android 滚动字幕实现
- android TextView 垂直自动滚动字幕实现
- 微信小程序实现自上而下字幕滚动
- android TextView 垂直自动滚动字幕实现
- WinForm程序实现滚动字幕与背景音乐
- Android下实现程序关闭后,监听取消
- c# 滚动字幕的实现