zoukankan      html  css  js  c++  java
  • android实现文字渐变效果和歌词进度的效果

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

    LinearGradient的参数解释

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

    它有两个构造函数

    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);

    这里写图片描述
    再实现文字的垂直渐变效果:

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

    这里写图片描述
    接下来来实现文字的颜色动态渐变效果:

    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);//刷新
            }
        }
    }
    

    这里写图片描述

    实现歌词进度效果

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

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

    这里写图片描述

    // 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);
        }
    }

    这里写图片描述

    ProgressBar实现歌词播放效果

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

    <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);
        }

    效果也是不错的:
    这里写图片描述

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

    demo可下载:TextViewGradient.rar
    接下来都会去写一下文字特效的,下一篇我们就来实现仿京东垂直新闻栏

  • 相关阅读:
    服务器 container
    oracle误操作表数据--回退(闪回)被提交后的数据
    在线笔记类
    idea maven项目使用过程中遇到的问题
    程序员提升网站
    检索网站
    公开课
    语言学习
    超强/超全面计算网站
    临时邮箱申请
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/9238004.html
Copyright © 2011-2022 走看看