Android 歌词滚动效果(歌词逐个与逐渐变色)可换行
生活随笔
收集整理的這篇文章主要介紹了
Android 歌词滚动效果(歌词逐个与逐渐变色)可换行
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
前言:
最近公司要求實現(xiàn)一個? 訊飛語音閱讀文字,文字根據(jù)閱讀速度逐個變色的功能。先上個圖看下效果。
(由于工作非常緊張,所以就把測試的圖貼過來了,兄弟們將就看)
?
直接上代碼:
ColorTrackView.java(主要就是這個自定義控件) import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View;import com.yiwei.lib_common.R;import java.util.ArrayList; import java.util.List;/*** @param* @author gaoql* @description 邏輯: 主要核心是 canvas.clipRect 裁剪畫布,比如文字 123456 通過裁剪 可以先將1的左前半部分* 變色,同時通過裁剪把不變色的部分也畫出來,這樣就會出現(xiàn)一種歌詞變色的效果(就是裁剪文字的后半部分)* @return* @time 2021/4/12 16:04*/ public class ColorTrackView extends View {private int mTextStartX = 0;private int mTextTopX = 0;//裁剪距頂部的距離private Paint mPaint = new Paint();private String mText;private int mTextSize = 30;private int mTextOriginColor = 0xff000000;private int mTextChangeColor = 0xffff0000;private Rect mTextBound = new Rect();private int mTextWidth = 0;private int mTextTotalWidth = 0;//文字總長度private int mTextHeight = 0;private int mRowHeight = 70;//每行的高度private int currentDrawRowHeight = mRowHeight;//當(dāng)前畫的行高private int mTextBaseLineHeight = 60;//文字繪畫基線高度private int mTextY = mTextBaseLineHeight;public int mProgress = -1;private float stepLength;public enum Direction {LEFT, RIGHT;}private int mDirection = DIRECTION_LEFT;private static final int DIRECTION_LEFT = 0;private static final int DIRECTION_RIGHT = 1;public ColorTrackView(Context context, AttributeSet attrs) {super(context, attrs);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackView);mText = ta.getString(R.styleable.ColorTrackView_text);mTextSize = ta.getDimensionPixelSize(R.styleable.ColorTrackView_text_size, mTextSize);mTextOriginColor = ta.getColor(R.styleable.ColorTrackView_text_origin_color, mTextOriginColor);mTextOriginColor = ta.getColor(R.styleable.ColorTrackView_text_origin_color, mTextOriginColor);mRowHeight = ta.getColor(R.styleable.ColorTrackView_row_height, 70);//mProgress = ta.getFloat(R.styleable.ColorTrackView_progress, mProgress);mDirection = ta.getInt(R.styleable.ColorTrackView_direction, mDirection);ta.recycle();mPaint.setTextSize(mTextSize);mPaint.setAntiAlias(true);mTextTotalWidth = (int) mPaint.measureText(mText);mPaint.getTextBounds(mText, 0, mText.length(), mTextBound);//measureText();stepLength = (float) mTextTotalWidth / 100f;//每段顏色變化長度Rect rect = new Rect();mPaint.getTextBounds(mText, 0, mText.length(), rect);mTextBaseLineHeight = rect.height();//文字高System.out.println("播放總長度:" + mTextTotalWidth);System.out.println("每段播放長度:" + stepLength);System.out.println("文字高度:" + mTextHeight);}/*** @param* @return* @description 測量文字寬和高* @author gaoql* @time 2021/4/13 15:48*//* private void measureText(){//得到文字的寬度mTextWidth = (int) mPaint.measureText(mText);mPaint.getTextBounds(mText, 0, mText.length(), mTextBound);Rect rect = new Rect();mPaint.getTextBounds(mText, 0, mText.length(), rect);mTextHeight = rect.height();//文字高//System.out.println("mTextHeight:"+mTextHeight);}*/private void measureText(String mText) {//得到文字的寬度mTextWidth = (int) mPaint.measureText(mText);//System.out.println("mTextHeight:"+mTextHeight);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);drawText(canvas);}private int nowDrawRow = 0;//當(dāng)前正在畫的行數(shù)private float mTextEndX = 0;//當(dāng)前正在畫的行文字寬度private void drawText(Canvas canvas) {//每行文字String nowDrawText = "";if (rowTextList != null) {nowDrawText = rowTextList.get(nowDrawRow);}//畫出背景文字int bgTextBaseLine = mTextBaseLineHeight;int bgTextX = 0;for(int i=0;i<rowTextList.size();i++){mPaint.setColor(mTextOriginColor);canvas.drawText(rowTextList.get(i), bgTextX, bgTextBaseLine, mPaint);bgTextBaseLine = bgTextBaseLine + mRowHeight;}//測量每行寬度mTextWidth = (int) mPaint.measureText(nowDrawText);/*** 通過for循環(huán) 畫出多行*/if (nowDrawRow > 0) {int overDrawTextY = mTextBaseLineHeight;//之前畫過的 文字yfor (int i = 0; i < nowDrawRow; i++) {mPaint.setColor(mTextChangeColor);canvas.drawText(rowTextList.get(i), 0, overDrawTextY, mPaint);overDrawTextY = overDrawTextY + mRowHeight;}}Rect rect = new Rect();rect.left = 0;rect.top = mTextTopX;rect.right = (int)mTextEndX;rect.bottom = currentDrawRowHeight;//畫帶顏色的文字 根據(jù)mProgress的進度drawText(canvas,nowDrawText,mTextChangeColor,rect);//判斷當(dāng)前行是否畫完if (mTextEndX >= mTextWidth) {//畫下一行數(shù)據(jù)nowDrawRow++;mTextEndX = 0;mTextTopX = currentDrawRowHeight;mTextY = currentDrawRowHeight + mTextBaseLineHeight;currentDrawRowHeight = currentDrawRowHeight + mRowHeight;//增加文字高度 為畫下一行提供數(shù)值}//裁剪長度mTextEndX = mTextEndX + stepLength;}/*** @description 清空帶顏色的繪畫* @param* @return* @author gaoql* @time 2021/4/14 10:56*/private void clearText(){nowDrawRow = 0;mTextEndX = stepLength;mTextY = mTextBaseLineHeight;mTextTopX = 0;currentDrawRowHeight = mRowHeight;}private void drawOriginLeft(Canvas canvas) {//畫除了顏色之外的 字體/* drawText(canvas,"",mTextOriginColor,(int) (mTextStartX + mProgress * mTextWidth),mTextStartX +mTextWidth );*/}private void drawText(Canvas canvas, String drawText, int color, Rect clipRect) {mPaint.setColor(color);canvas.save();canvas.clipRect(clipRect);canvas.drawText(drawText, clipRect.left, mTextY, mPaint);canvas.restore();// canvas.save(); 和 canvas.restore(); 的作用,保存之前畫的效果, 繼續(xù)畫,畫完之后取出之前的效果 合并}private List<String> rowTextList;//每行的數(shù)據(jù)private int viewWidth;//當(dāng)前view的寬度private int viewHeight;//當(dāng)前view的高度@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);viewWidth = measureWidth(widthMeasureSpec);//得到View的寬viewHeight = measureHight(heightMeasureSpec);//得到View的高System.out.println("====width:" + viewWidth);System.out.println("====height:" + viewHeight);setMeasuredDimension(viewWidth, viewHeight);System.out.println("mTextWidth:" + mTextWidth);/*//通過view寬度和文字總寬度 計算出一共可以畫幾行int rowCount = (mTextTotalWidth / viewWidth) + 1;//需要畫的行數(shù)System.out.println("rowCount:" + rowCount);*///對所有的文字進行計算寬度并拆分成行,逐個取出文字計算寬度,如果到達(dá)view的寬度 則為一行,然后開始下一行char[] mTextChars = mText.toCharArray();StringBuilder stringBuilder = new StringBuilder();//一行字符的寬度float textWidth = 0;//保存數(shù)據(jù)行的集合rowTextList = new ArrayList<>();//循環(huán)取出字符for (int i = 0; i < mTextChars.length; i++) {char c = mTextChars[i];//把字符寬度相加textWidth = textWidth + mPaint.measureText(c + "");//把相加后的字符 放到stringBuilder中stringBuilder.append(c);//判斷當(dāng)前保存到stringBuilder中的 字符串是否超過了 view自身的寬度,// 如果超過了就把前sb中的字符保存起來,(這個保存的為一行文字?jǐn)?shù)據(jù))//保存一行后 重新開始計算下一行if (textWidth >= viewWidth) {//已夠一行數(shù)據(jù) 保存到集合中rowTextList.add(stringBuilder.toString());//清空記錄數(shù)據(jù) 重新開始計算其他字符 拼裝新的行數(shù)據(jù)stringBuilder.delete(0, stringBuilder.length());textWidth = 0;}//判斷是否循環(huán)到了最后一個字符if (i == mTextChars.length - 1) {//此時為最后一行rowTextList.add(stringBuilder.toString());}}System.out.println("----rowTextList:" + rowTextList.get(0));System.out.println("----rowTextList:size " + rowTextList.size());}public int getDirection() {return mDirection;}public void setDirection(int mDirection) {this.mDirection = mDirection;}public float getMProgress() {return mProgress;}public void setMProgress(int mProgress) {if(mProgress == 0){//清空數(shù)據(jù)重新畫clearText();}if (this.mProgress != mProgress) {this.mProgress = mProgress;System.out.println("---------mProgress:" + mProgress);invalidate();}}private int measureWidth(int widthMeasureSpec) {int result = 0;int specMode = MeasureSpec.getMode(widthMeasureSpec);int specSize = MeasureSpec.getSize(widthMeasureSpec);if (specMode == MeasureSpec.EXACTLY) {result = specSize;} else {result = 200;if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}private int measureHight(int heightMeasureSpec) {int result = 0;int specMode = MeasureSpec.getMode(heightMeasureSpec);int specSize = MeasureSpec.getSize(heightMeasureSpec);if (specMode == MeasureSpec.EXACTLY) {result = specSize;} else {result = 200;if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}}attr.xml (自定義屬性文件 位置?res -> values ->attr.xml)
<resources><attr name="text" format="string"></attr><attr name="text_size" format="dimension"></attr><attr name="text_origin_color" format="color|reference"></attr><attr name="text_change_color" format="color|reference"></attr><attr name="progress" format="float"></attr><attr name="row_height" format="integer"></attr><attr name="direction"><enum name="left" value="0"></enum><enum name="right" value="1"></enum></attr><declare-styleable name="ColorTrackView"><attr name="text"></attr><attr name="text_size"></attr><attr name="text_origin_color"></attr><attr name="text_change_color"></attr><attr name="progress"></attr><attr name="direction"></attr><attr name="row_height"></attr></declare-styleable> </resources>布局中引用:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/darker_gray"tools:context=".activity.MainActivity"><com.eway.lib_audio.view.ColorTrackViewandroid:id="@+id/show_voice_text2"android:layout_width="200dp"android:layout_height="wrap_content"android:layout_marginTop="30dp"app:text="請您在畫板上,畫出您看到的圖形,一筆只畫一條線,不能折。請您在畫板上,畫出您看到的圖形,一筆只畫一條線,不能折。"app:text_size="14sp"//字體大小app:row_height="30"//這個屬性是 繪制文字的每行的高度app:text_change_color="#08A7FD" //這個是滾動時的顏色app:text_origin_color="@color/white"/>//這個時背景默認(rèn)的顏色 </androidx.constraintlayout.widget.ConstraintLayout>代碼中使用:
@Overrideprotected void onClickImpl(View view) {switch (view.getId()){case R.id.show_voice_text2:ObjectAnimator.ofInt(colorTrackView, "mProgress", 0,100).setDuration(5000).start();break;}這里說明一下,使用原理就是 調(diào)用ColorTrackView自定義控件中的? setMProgress(percent); 方法。
percent值傳0-100最好,可根據(jù)自己需求改。
我是這么用的,訊飛語音在閱讀文字時 會把當(dāng)前的閱讀 進度反饋給我 值時0-100
//這是訊飛語音一個回調(diào)方法 @Overridepublic void onSpeakProgress(int percent, int beginPos, int endPos) {// 播放進度 percent值為0-100 colorTrackView.setMProgress(percent);}總結(jié):
1.自定義ColorTrackView(復(fù)制粘貼過去即可)
2.在layout布局中引用 設(shè)置文字? 文字大小? 行高? 滾動顏色? 文字初始顏色
3.在代碼中分次調(diào)用?colorTrackView.setMProgress(percent); 最好是 0-100次調(diào)用
著急干活,寫的不是很詳細(xì)。
總結(jié)
以上是生活随笔為你收集整理的Android 歌词滚动效果(歌词逐个与逐渐变色)可换行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021年金属非金属矿山(地下矿山)主要
- 下一篇: 时尚html输入框,12款经典时尚的HT