Recently, the project needs to develop a circular scrolling subtitle function. I found relevant materials and implemented the function in two ways based on my own style;
(Note: I only implement the scrolling effect, and I have not done any processing on text format formatting. The format may be messy and Text Formatting is still under study)
:
The details are as follows;
Method 1: Transverse scrolling Subtitles inherit 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. displaymetri CS; 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) {super (context);} public AutoText (context, attributeset attrs) {super (context, attrs);} private void initview () {painttext = new paint (); painttext. settextsize (50366f); painttext. setcolor (color. black); painttext. settypeface (typeface. default_bold); painttext. setantialias (true); text = gettext (). tostring (); textwidth = painttext. measuretext (text); log. E ("MSG", "textwidth =" + textwid Th); this. speed = textwidth; movedistance = textwidth * 2 + width;} public void initdisplaymetrics (windowmanager) {/* Get screen resolution size */displaymetrics dm = new displaymetrics (); windowmanager. getdefadisplay display (). getmetrics (DM); this. width = DM. widthpixels; this. height = DM. heightpixels; initview (); this. posx = width + textwidth; fontmetrics fm = painttext. getfontmetrics (); float Baseline = FM. descent-FM. ASC Ent; this. posy = height/2-baseline;} public void startscroll () {isstarting = true; invalidate ();} public void stopscroll () {isstarting = false; invalidate ();} @ overrideprotected void ondraw (canvas) {// super. ondraw (canvas); canvas. drawtext (text, posx-speed, Posy, painttext); If (! Isstarting) {return;} speed + = 2.0f; If (speed> movedistance) speed = textwidth; invalidate ();}}
Layout file;
<?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>
Method 2: Inherit sufaceview to implement vertical text scrolling
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. surfacehol Der; 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; /** coordinates of the position when the text starts to appear */private float posx, Posy;/** the distance between the current moving text and the original Moving position of the text in each line */private float [] Step, stepback; private string txtc Ontent;/** store the original ordinate position of each line of text */private float [] tposy;/** store the content of each line of text */private string [] texts; Public scrolltext (context) {super (context); initview ();} public scrolltext (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 (30366f); textpaint. setcolor (color. blue); textpaint. settypeface (typeface. default_bold); textpaint. settextalign (paint. align. left); textpaint. setantialias (true);} public void initdisplaymetrics (windowmanager) {/* Get screen resolution size */displaymetrics dm = new displaymetrics (); windowmanager. getdefadisplay display (). getmet RICS (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 txt00000000this.txt content = 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;}/*** call all painting methods */private void drawall () {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, 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 ();}/*** split text information before drawing text information, text spacing, text Location calculation process * @ 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 () ;}}/*** get the split text information * @ 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;}/*** get the ordinate information of each line of text * @ return */private float [] gettextlineposy () {fontmetrics fm = textpaint. getfontmetrics (); float Baseline = FM. descent-FM. ascent; float y = posy + baseline; // because the system draws text based on the bottom of the font, all the text heights that need to be added, int Len = texts. length; float [] groups = new float [Len]; for (INT I = 0; I <Len; I ++) {groups [I] = y; y = Y + baseline + FM. leading; // Add font row spacing} return groups;}/*** automatically split the text * @ Param content the text to be split * @ Param P paint brush, it is used to measure the text width based on the font * @ Param width the largest printable pixel (usually the width of the Control) * @ return a string array, save the text of each line */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); // calculate the number of rows string [] linetexts = new string [Lines]; while (start <length) {If (P. measuretext (content, start, end)> width) {// when the text width exceeds the control width, linetexts [I ++] = content. substring (START, end); // (string) content. subsequence (START, end); Start = end;} If (END = length) {// text linetexts [I] = content in less than one line. 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 = "promotes the all-round development of young teachers, \ n guides young teachers in colleges and universities to contribute to the Chinese dream of realizing the great rejuvenation of the Chinese nation "+" \ n "+" to promote the all-round development of young teachers, \ n guides young college teachers to contribute to the Chinese dream of realizing the great rejuvenation of the Chinese nation "+" \ 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 ();}}