最近項目需求做個迴圈滾動字幕功能,自己找了相關資料,根據自己的風格用兩種方法實現了該功能;
(備忘:本人只實現了滾動效果,對於文字的格式排版沒做處理,格式可能會亂,文字排版還在研究中)
:
具體如下;
方法一:橫向滾動字幕繼承TextView
package com.example.playpic;import com.example.playpic.AutoScrollTextView.SavedState;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Typeface;import android.graphics.Paint.FontMetrics;import android.os.Parcel;import android.os.Parcelable;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.WindowManager;import android.view.View.BaseSavedState;import android.widget.TextView;public class AutoText extends TextView {private int width,height;private Paint paintText;private float posx,posy;private float speed=0.0f;private String text="hello haha";private float textWidth=0;private float moveDistance=0.0f;private boolean isStarting=false;public AutoText(Context context) {super(context);}public AutoText(Context context, AttributeSet attrs) {super(context, attrs);}private void initView(){paintText=new Paint();paintText.setTextSize(50.0f);paintText.setColor(Color.BLACK);paintText.setTypeface(Typeface.DEFAULT_BOLD);paintText.setAntiAlias(true);text=getText().toString();textWidth=paintText.measureText(text);Log.e("msg", "textWidth= "+textWidth);this.speed=textWidth;moveDistance=textWidth*2+width;}public void initDisplayMetrics(WindowManager windowManager){ /* 取得螢幕解析度大小 */ DisplayMetrics dm=new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(dm); this.width=dm.widthPixels; this.height=dm.heightPixels; initView(); this.posx=width+textWidth; FontMetrics fm = paintText.getFontMetrics(); float baseline = fm.descent - fm.ascent; this.posy=height/2-baseline; }public void startScroll() {isStarting = true;invalidate();}public void stopScroll() {isStarting = false;invalidate();}@Overrideprotected void onDraw(Canvas canvas) {//super.onDraw(canvas);canvas.drawText(text, posx-speed, posy, paintText);if (!isStarting) {return;}speed += 2.0f;if (speed > moveDistance)speed = textWidth;invalidate();}}
布局檔案;
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.playpic.AutoText android:id="@+id/autoTxt" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:textColor="#00ff00" android:textSize="35sp" /></LinearLayout>
方法二:繼承sufaceView實現縱向文字滾動功能
package com.example.playpic;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.FontMetrics;import android.graphics.Rect;import android.graphics.Typeface;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.WindowManager;public class ScrollText extends SurfaceView implements SurfaceHolder.Callback ,Runnable{private int width,height;private SurfaceHolder sfh;private Thread th;private boolean flag;private Paint backPaint,textPaint;/**文字開始出現的位置座標*/private float posx,posy;/**每行文本 當前移動文本距離以及文本的原始移動位置*/private Float[] step,stepBack;private String txtContent;/**儲存每行文本原始縱座標位置*/private Float[] tposy;/**儲存每行常值內容*/private String[] texts;public ScrollText(Context context) {super(context);initView();}public ScrollText(Context context, AttributeSet attrs) {super(context, attrs);initView();}private void initView(){sfh=this.getHolder();sfh.addCallback(this);this.setKeepScreenOn(true);this.setFocusable(true);//this.setFocusableInTouchMode(true);backPaint=new Paint();backPaint.setColor(Color.BLACK);textPaint=new Paint();textPaint.setTextSize(30.0f);textPaint.setColor(Color.BLUE);textPaint.setTypeface(Typeface.DEFAULT_BOLD);textPaint.setTextAlign(Paint.Align.LEFT);textPaint.setAntiAlias(true);}public void initDisplayMetrics(WindowManager windowManager){ /* 取得螢幕解析度大小 */ DisplayMetrics dm=new DisplayMetrics(); windowManager.getDefaultDisplay().getMetrics(dm); this.width=dm.widthPixels; this.height=dm.heightPixels; this.posx=width/6; /* FontMetrics fm = textPaint.getFontMetrics(); float baseline = fm.descent - fm.ascent;*/ this.posy=height-100; }public void setTxtContent(String txt){this.txtContent=txt;}@Overridepublic void surfaceCreated(SurfaceHolder holder) {this.flag=true;if(th==null||!th.isAlive()){th=new Thread(this);th.start();}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {this.flag=false;}/** * 調用所有繪製方法 */private void drawAll(){Canvas canvas=null;try{canvas=sfh.lockCanvas();drawText(canvas, txtContent);}catch(Exception e){e.printStackTrace();}finally{if(canvas!=null){sfh.unlockCanvasAndPost(canvas);}}}private void drawText(Canvas canvas,String text){//clear screencanvas.drawRect(new Rect(0,0,getWidth(),getHeight()), backPaint);initDrawText(text);int len=tposy.length;// draw text contentfor(int n=0;n<len;n++){if(texts[n]==null)return;float ty=tposy[n]-step[n];canvas.drawText(texts[n], posx, ty, textPaint);step[n]+=5.0f;if(n==len-1&&ty<0){step=stepBack.clone();}/*if (ty<0){Log.e("msgreset", "back step");step[n] = stepBack[n].floatValue();}*/}postInvalidate();}/** * 在文字資訊繪製前對文本資訊進行文字分割,文字間距,文字位置計算處理 * @param text */private void initDrawText(String text){if(texts==null){texts=getTexts(text);}if(tposy==null){tposy=getTextLinePosy();}if(stepBack==null){stepBack=new Float[tposy.length];int i=0;float interval=0.0f;FontMetrics fm = textPaint.getFontMetrics(); float baseline = fm.descent - fm.ascent;while(i<stepBack.length){stepBack[i]=interval;interval-=baseline;i++;}}if(step==null){step=stepBack.clone();}}/** * 擷取分割後的文本資訊 * @param text * @return */private String[] getTexts(String text){List<String> totalList=new ArrayList<String>(10);String[] str=text.split("\n");int len=str.length;for(int i=0;i<len;i++){String[] ss=autoSplit(str[i], textPaint, getWidth()/3*2);for(String s:ss){totalList.add(s);}}if(texts==null)texts=(String[]) totalList.toArray(new String[0]);/*if(texts==null) texts = autoSplit(text, textPaint, getWidth()/3*2); */return texts;}/** * 擷取每行文本的縱座標資訊 * @return */private Float[] getTextLinePosy(){ FontMetrics fm = textPaint.getFontMetrics(); float baseline = fm.descent - fm.ascent; float y = posy+baseline; //由於系統基於字型的底部來繪製文本,所有需要加上字型的高度 int len=texts.length; Float[] groups=new Float[len]; for(int i=0;i<len;i++) { groups[i]=y; y =y+ baseline + fm.leading; //添加字型行間距 } return groups;}/** * 自動分割文本 * @param content 需要分割的文本 * @param p 畫筆,用來根據字型測量文本的寬度 * @param width 最大的可顯示像素(一般為控制項的寬度) * @return 一個字串數組,儲存每行的文本 */private String[] autoSplit(String content, Paint p, float width) { /* String[] lineTexts = new String[1000]; int lenStr=0; int lineNum=0,w=0,start=0,end=1,n=0; lenStr=content.length(); for(int j=0;j<lenStr;j++){ char ch=content.charAt(j); String str_ch=String.valueOf(ch); float[] ch_w=new float[1]; p.getTextWidths(str_ch, ch_w); if(str_ch=="\n"){ lineNum++; //start=j+1; end=j+1; w=0; lineTexts[n++] = (String) content.subSequence(start, end); start=end; }else{ w+=(int)(Math.ceil(ch_w[0])); if(w>width){ lineNum++; //start=j; end=j; j--; w=0; lineTexts[n++] = (String) content.subSequence(start, end); start=end; }else{ if(j==(lenStr-1)){ lineNum++; lineTexts[n++] = (String) content.subSequence(start, end); break; } } } } Log.e("msg", "lineNum= "+lineNum);*/ float textWidth = p.measureText(content); if(textWidth <= width) { return new String[]{content}; } int length = content.length(); int start = 0, end = 1, i = 0; int lines = (int) Math.ceil(textWidth / width); //計算行數 String[] lineTexts = new String[lines]; while(start < length) { if(p.measureText(content, start, end) > width) { //文本寬度超出控制項寬度時 lineTexts[i++] = content.substring(start, end);//(String) content.subSequence(start, end); start = end; } if(end == length) { //不足一行的文本 lineTexts[i] = content.substring(start, end);//(String) content.subSequence(start, end); break; } end += 1; } return lineTexts;}@Overridepublic void run() {while(flag){drawAll();try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}}
package com.example.playpic;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.InputStreamReader;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.text.method.ScrollingMovementMethod;import android.util.Log;import android.widget.TextView;import com.sample.fun.R;public class ScrollTextActivity extends Activity{String str="";String str11="促進青年教師全面發展,\n引導廣大高校青年教師為實現中華民族偉大複興的中國夢貢獻力" +"\n"+"促進青年教師全面發展,\n引導廣大高校青年教師為實現中華民族偉大複興的中國夢貢獻力"+"\n"+" djsdnhkshdfjks \n\r\t ";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);scroll3();}void scroll2(){ScrollText v=new ScrollText(getApplicationContext());setContentView(v);v.setTxtContent(str11);v.initDisplayMetrics(getWindowManager());}void scroll3(){setContentView(R.layout.scrollview1);AutoText auto=(AutoText)findViewById(R.id.autoTxt);auto.setText(str11);auto.initDisplayMetrics(getWindowManager());auto.startScroll();}}