Android 仿QQ控件变色的EditText/TextView

来源:互联网 发布:php页游源码 编辑:程序博客网 时间:2024/06/06 06:42

本人纯属博客小白,不会使用 Markdown 来编写博客,Android也才入门,可能实现起来存在缺陷,各位看官将就着看,一起交流。


最近QQ空间添加了一个新的功能,说说可以自动变色,看起来还不错的样子,于是打算模仿看看。

它变色有两种形式,一种是整体颜色渐变;另一种是线性渐变,也就是文字的头尾颜色发生变化

现在先说第一种,整体的颜色渐变。(线性渐变使用LinearGradient线性渲染实现,感兴趣可以自己去试试

编程先说思路:

1.既然是类似EditText/TextView,那肯定要画出用户指定的文字

2.既然要颜色渐变,那肯定是不断改变画笔的颜色


如果只是想模仿QQ空间的效果。后面有更简单的方法,前面先说最初的思路,自定义程度也是最高的。


首先,先在自定义view里面开放方法让用户设置需要显示的文字,同时在onDraw里面画出来就行了,大致代码如下:

    public void setText(String text){        content=text;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.save();        canvas.drawText(content,w,h,mPaint);        canvas.restore();    }

第一步,非常简单是不是,但是问题来了,万一用户没有调用setText,那么content就是null,会报空指针异常。那么解决方法有两个。

一个是初始化content="";一个实在drawText前加判断:

if (content==null){            return;        }
当然,除了这个之外你们还可以开放其他方法来设置字体、字体大小、字体显示位置等。也可以自定义attr,直接在XML设置就不用使用java代码设置了。


第二步无非是设置颜色,当然也需要开放方法或者定义attr。既然是渐变,我们肯定需要两种颜色。

public void setTextTransitionColor(int startColor,int endColor){        this.startColor=startColor;        this.endColor=endColor;    }

起初我是这么想的,在这两种颜色中变化,直接一个属性动画不就行了么?变化范围就在这两种颜色之间就行了。然后我就这么写了

 private void startTransition() {        ValueAnimator colorAnim =ValueAnimator.ofInt(startColor,endColor);        colorAnim.setDuration(repeatTime);        colorAnim.setRepeatMode(ValueAnimator.REVERSE);        colorAnim.setRepeatCount(ValueAnimator.INFINITE);        colorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                mPaint.setColor((Integer) animation.getAnimatedValue());                invalidate();            }        });        colorAnim.start();        isAnim=true;    }

然后...那颜色变化简直就是闪瞎眼啊,就算装有钛合金狗眼也瞎了,根本不是那种缓和的渐变效果,而是快速变化!举个例子,你设置开始颜色值0X000000,结束颜色值0xFFFFFF,那么值就会从0X000000变化到0xFFFFFF,在短短一两秒内,什么颜色都出现了,并不是我们需要的效果。


那么怎么样才能实现渐变?以下就是最主要的颜色渐变算法了。

既然这样子不行,我们仔细想想,QQ空间那颜色的变化的感觉只在设定的两种颜色中变化,就像是现实中把两种颜色按不同的比例进行调和,从1:0--0:1,不就是这种效果么

?那么我们也来“调和”一下好了。

既然要调和,我们用什么来调整两种颜色比例呢?没错,就是透明度。把两种颜色覆盖在一起,通过不断调整深度值,不就达到了我们的效果了么?

首先需要先把用户设定的颜色分解成ARGB,然后通过调整深度值,再把两种颜色相加,就完成了调和的效果,深度从0%-100%,也就是0-->1:

 private void startTransition() {        ValueAnimator colorAnim =ValueAnimator.ofFloat(0,1);        colorAnim.setDuration(repeatTime);        colorAnim.setRepeatMode(ValueAnimator.REVERSE);        colorAnim.setRepeatCount(ValueAnimator.INFINITE);        //颜色分解        sa=Color.alpha(startColor);        sr=Color.red(startColor);        sg=Color.green(startColor);        sb=Color.blue(startColor);        ea=Color.alpha(endColor);        er=Color.red(endColor);        eg=Color.green(endColor);        eb=Color.blue(endColor);        colorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                //随着时间的变化开始颜色的深度 1-->0                float sv = (float)animation.getAnimatedValue();                ////随着时间的变化结束颜色的深度 0-->1                float  ev= 1f-(float)animation.getAnimatedValue();                //就是调用 mPaint.setColor(Color.argb(a,r,g,b)),里面的a,r,g,b是调和后的颜色                //这里需要分别计算颜色深度在想加                mPaint.setColor(Color.argb((int)(ea*ev+sa*sv),(int)(sr*sv+er*ev),(int)(sg*sv+eg*ev),(int)(sb*sv+eb*ev)));                invalidate();            }        });        colorAnim.start();        isAnim=true;    }

这样就实现了我们想要的效果,效果图:

大家还需要注意的是这两行代码:

colorAnim.setRepeatMode(ValueAnimator.REVERSE);        colorAnim.setRepeatCount(ValueAnimator.INFINITE);

要让颜色一直渐变下去,需要设置动画重复次数为无限次,

这样还不行,例如你设置的颜色是红,绿  那么变化就是 红-->绿 立马变化红,在重复红-->绿 也就是从绿到红不是渐变的,看起来十分突兀。所以设置重复Mode为反转即可,就是colorAnim.setRepeatMode(ValueAnimator.REVERSE);


那什么时候开启这个动画呢?当然是用户设置颜色之后了,你在用户设定颜色的方法里面电影这个动画的方法就行了:

  public void setTextTransitionColor(int startColor,int endColor){        this.startColor=startColor;        this.endColor=endColor;        startTransition();    }

那么简单的颜色渐变效果就有了,我之所以说这个自定义程度最高是因为这个View是继承View的,你可以进行其他额外的拓展。

如果你想只是实现QQ空间的效果,并且保留有原生EditText/TextView的属性和方法,更简单的方法就是直接继承EditText/TextView,然后根据我们上面的颜色调和的方法,调用他们的setTextColor就行了,这里以EditText为例:

public class ColorEditText extends AppCompatEditText {    private int repeatTime;    private int sa,sr,sg,sb,ea,er,eg,eb;    public ColorEditText(Context context) {        super(context);    }    public ColorEditText(Context context, AttributeSet attrs) {        super(context, attrs);    }    public ColorEditText(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public void setTextTransitionColor(int startColor,int endColor){        sa= Color.alpha(startColor);        sr=Color.red(startColor);        sg=Color.green(startColor);        sb=Color.blue(startColor);        ea=Color.alpha(endColor);        er=Color.red(endColor);        eg=Color.green(endColor);        eb=Color.blue(endColor);        startTransition();    }    public void setRepeatTime(int repeatTime) {        this.repeatTime = repeatTime;    }    private void startTransition() {        ValueAnimator colorAnim =ValueAnimator.ofFloat(0,1);        colorAnim.setDuration(repeatTime);        colorAnim.setRepeatMode(ValueAnimator.REVERSE);        colorAnim.setRepeatCount(ValueAnimator.INFINITE);        colorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float sv = (float)animation.getAnimatedValue();                float  ev= 1f-(float)animation.getAnimatedValue();                setTextColor(Color.argb((int)(ea*ev+sa*sv),(int)(sr*sv+er*ev),(int)(sg*sv+eg*ev),(int)(sb*sv+eb*ev)));                invalidate();            }        });        colorAnim.start();    }}

非常的简单是不是,也可以不用自定义直接在activity实现这个逻辑也行..

大概实现方法就这样的,预览图暂时没有,经过我测试已经完全可以模仿QQ空间的效果了,大家直接去QQ空间看预览图吧..


至于线性变化,有空再说...也不难,比这个还简单,大家感兴趣自己了解一下LinearGradient线性渲染就会了。


至于demo我在github上有,但是没有任何注释,没什么参考价值,大家有问题直接在下方评论就好了。


到此。

阅读全文
0 0
原创粉丝点击