Android实现歌词渐变色和进度的效果

作者:Losileeya 时间:2023-09-24 02:33:17 

要用TextView使用渐变色,那我们就必须要了解LinearGradient(线性渐变)的用法。

LinearGradient的参数解释

LinearGradient也称作线性渲染,LinearGradient的作用是实现某一区域内颜色的线性渐变效果,看源码你就知道他是shader的子类。

Android实现歌词渐变色和进度的效果

它有两个构造函数


public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
public LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile);

其中,参数x0表示渐变的起始点x坐标;参数y0表示渐变的起始点y坐标;参数x1表示渐变的终点x坐标;参数y1表示渐变的终点y坐标;color0表示渐变开始颜色;color1表示渐变结束颜色;参数tile表示平铺方式。

Shader.TileMode有3种参数可供选择,分别为CLAMP、REPEAT和MIRROR:

CLAMP的作用是如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色

REPEAT的作用是在横向和纵向上以平铺的形式重复渲染位图

MIRROR的作用是在横向和纵向上以镜像的方式重复渲染位图

LinearGradient的简单使用

先实现文字效果的水平渐变:


Shader shader_horizontal= new LinearGradient(btWidth/4, 0, btWidth, 0, Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
tv_text_horizontal.getPaint().setShader(shader_horizontal);

Android实现歌词渐变色和进度的效果 

再实现文字的垂直渐变效果:


Shader shader_vertical=new LinearGradient(0, btHeight/4, 0, btHeight, Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
tv_text_vertical.getPaint().setShader(shader_vertical);

Android实现歌词渐变色和进度的效果 

接下来来实现文字的颜色动态渐变效果:


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* Created on 2016/3/13.
*/
public class GradientHorizontalTextView extends TextView {
private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;//渐变矩阵
private Paint mPaint;//画笔
private int mViewWidth = 0;//textView的宽
private int mTranslate = 0;//平移量
private boolean mAnimating = true;//是否动画
private int delta = 15;//移动增量
public GradientHorizontalTextView(Context ctx)
{
this(ctx,null);
}
public GradientHorizontalTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
mPaint = getPaint();
String text = getText().toString();
int size;
if(text.length()>0)
{
size = mViewWidth*2/text.length();
}else{
size = mViewWidth;
}
mLinearGradient = new LinearGradient(-size, 0, 0, 0,
new int[] { 0x33ffffff, 0xffffffff, 0x33ffffff },
new float[] { 0, 0.5f, 1 }, Shader.TileMode.CLAMP); //边缘融合
mPaint.setShader(mLinearGradient);//设置渐变
mGradientMatrix = new Matrix();
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mAnimating && mGradientMatrix != null) {
float mTextWidth = getPaint().measureText(getText().toString());//获得文字宽
mTranslate += delta;//默认向右移动
if (mTranslate > mTextWidth+1 || mTranslate<1) {
delta = -delta;//向左移动
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
postInvalidateDelayed(30);//刷新
}
}
}

Android实现歌词渐变色和进度的效果

实现歌词进度效果

Canvas 作为绘制文本时,使用FontMetrics对象,计算位置的坐标。它的思路和java.awt.FontMetrics的基本相同。
FontMetrics对象它以四个基本坐标为基准,分别为:

FontMetrics.top
FontMetrics.ascent
FontMetrics.descent
FontMetrics.bottom

Android实现歌词渐变色和进度的效果


// FontMetrics对象
FontMetrics fontMetrics = textPaint.getFontMetrics();
String text = "abcdefghijklmnopqrstu";
// 计算每一个坐标
float baseX = 0;
float baseY = 100;
float topY = baseY + fontMetrics.top;
float ascentY = baseY + fontMetrics.ascent;
float descentY = baseY + fontMetrics.descent;
float bottomY = baseY + fontMetrics.bottom;

下面是具体实现代码:


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* Created on 2016/3/13.
*/
public class SongTextView extends View {
private int postIndex;
private Paint mPaint;
private int delta = 15;
private float mTextHeight;
private float mTextWidth;
private String mText="梦 里 面 看 我 七 十 二 变";
private PorterDuffXfermode xformode;
public SongTextView(Context ctx)
{
this(ctx,null);
}
public SongTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SongTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init()
{
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xformode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
mPaint.setColor(Color.CYAN);
mPaint.setTextSize(60.0f);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setXfermode(null);
mPaint.setTextAlign(Paint.Align.LEFT);
//文字精确高度
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
mTextHeight = fontMetrics.bottom-fontMetrics.descent-fontMetrics.ascent;
mTextWidth = mPaint.measureText(mText);
}
/**
*计算 控件的宽高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int mWidth;
final int mHeight;
/**
* 设置宽度
*/
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY)// match_parent , accurate
mWidth = widthSize;
else
{
// 由图片决定的宽
int desireByImg = getPaddingLeft() + getPaddingRight()
+ getMeasuredWidth();
if (widthMode == MeasureSpec.AT_MOST)// wrap_content
mWidth = Math.min(desireByImg, widthSize);
else
mWidth = desireByImg;
}
/***
* 设置高度
*/
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY)// match_parent , accurate
mHeight = heightSize;
else
{
int desire = getPaddingTop() + getPaddingBottom()
+ getMeasuredHeight();
if (heightMode == MeasureSpec.AT_MOST)// wrap_content
mHeight = Math.min(desire, heightSize);
else
mHeight = desire;
}
setMeasuredDimension( mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Bitmap srcBitmap = Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas srcCanvas = new Canvas(srcBitmap);
srcCanvas.drawText(mText, 0, mTextHeight, mPaint);
mPaint.setXfermode(xformode);
mPaint.setColor(Color.RED);
RectF rectF = new RectF(0,0,postIndex,getMeasuredHeight());
srcCanvas.drawRect(rectF, mPaint);
canvas.drawBitmap(srcBitmap, 0, 0, null);
init();
if(postIndex<mTextWidth)
{
postIndex+=10;
}else{
postIndex=0;
}
postInvalidateDelayed(30);
}
}

Android实现歌词渐变色和进度的效果

ProgressBar实现歌词播放效果

然后接下来的这种歌词播放进度效果是2张图片实现的,忘记是哪个那里看来的,压根以前也没有想过还可以这么样的实现。
只需要准备2张图即可:

Android实现歌词渐变色和进度的效果
Android实现歌词渐变色和进度的效果


<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@android:id/background"
android:drawable="@drawable/normal" />
<item
android:id="@android:id/progress"
android:drawable="@drawable/grandient" />
</layer-list>

看见没就是2张图片,一张作为背景图一张作为进度图,是不是感觉很神奇,然后放入ProgressBar


<ProgressBar
android:id="@+id/pb1"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="300dp"
android:layout_height="40dp"
android:max="100"
android:maxHeight="2dp"
android:minHeight="2dp"
android:progress="20"
android:progressDrawable="@drawable/m_progress_horizontal"
android:secondaryProgress="30"
android:visibility="gone"/>

再加上代码动态改变progress就能实现进度的变化了:


ProgressBar pb1= (ProgressBar) findViewById(R.id.pb1);
//设置滚动条可见
setProgressBarIndeterminateVisibility(true);
progress=pb1.getProgress();//获取初始进度
timer=new Timer();
task=new TimerTask() {
@Override
public void run() {
progress+=10;
if(progress>100){
progress=0;
}
handler.sendEmptyMessage(0);
}
};
timer.schedule(task,1000,300);

实现及进度的改变:


Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
pb1.setProgress(progress);
}
};
@Override
protected void onDestroy() {
super.onDestroy();
timer=null;
task=null;
handler.removeCallbacksAndMessages(null);
}

效果也是不错的:

Android实现歌词渐变色和进度的效果

能力有限,感觉写一篇博客要弄好久,网速卡的一笔,就写到这了,其实项目里面也没有用到,休息2天了也写点东西,就觉得还是要学一点东西作为备用知识。

以上内容是小编给大家介绍的Android实现歌词渐变色和进度的效果,希望对大家有所帮助!

标签:android,渐变色,进度条
0
投稿

猜你喜欢

  • C#实现一键换IP、重置DNS、网关及掩码的方法

    2021-10-03 00:32:33
  • Java数据结构 递归之迷宫回溯案例讲解

    2023-04-01 11:16:38
  • mybatis-plus 返回部分字段的解决方式

    2023-03-25 14:45:04
  • C#使用GET、POST请求获取结果

    2023-04-20 13:35:43
  • SpringBoot如何进行参数校验实例详解

    2022-10-24 03:39:33
  • android开发去除标题栏的方法

    2021-06-30 19:11:29
  • C#可用于登录验证码的四位随机数生成方法

    2021-08-01 00:31:01
  • IOS开发向右滑动返回前一个页面功能(demo)

    2021-09-23 04:30:11
  • springboot使用GuavaCache做简单缓存处理的方法

    2022-12-04 22:43:02
  • Android以对话框形式制作数字软键盘示例

    2022-12-07 07:37:03
  • Java 反转带头结点的单链表并显示输出的实现过程

    2022-06-08 18:34:39
  • UE4 Unlua 调用异步蓝图节点AIMoveTo函数示例详解

    2022-04-12 05:35:41
  • 创建execl导入工具类的步骤

    2022-03-11 11:41:09
  • android自定义组件实现仪表计数盘

    2023-12-23 21:27:41
  • Spring Security 中如何让上级拥有下级的所有权限(案例分析)

    2022-01-28 16:55:26
  • 基于C#实现的端口扫描器实例代码

    2022-04-29 20:21:56
  • Winform实现调用asp.net数据接口实例

    2021-12-16 09:12:48
  • 解决IntelliJ IDEA中鼠标拖动选择为矩形区域问题

    2022-04-03 21:08:51
  • C#中Socket与Unity相结合示例代码

    2022-09-15 23:24:15
  • 猜数游戏java实现代码

    2023-01-05 18:39:28
  • asp之家 软件编程 m.aspxhome.com