Android渐变色,文本过长字符串渐变效果

本文首先介绍Android渐变色的基础理论知识,然后自定义一个TextView实现文本过长时字符串颜色渐变效果

一、LinearGradient线性渐变

在android平台中提供了两种重载方式来实例化该类分别为,他们的不同之处为参数中第一种方法可以用颜色数组,和位置来实现更细腻的过渡效果,比如颜色采样int[] colors数组中存放20种颜色,则渐变将会逐一处理。而第二种方法参数仅为起初颜色color0和最终颜色color1。
LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile) 
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile) 
使用实例如下
Paint p=new Paint();
LinearGradient lg=new LinearGradient(0,0,100,100,Color.RED,Color.BLUE,Shader.TileMode.MIRROR);  

参数一为渐变起初点坐标x位置,参数二为y轴位置,参数三和四分辨对应渐变终点,最后参数为平铺方式,这里设置为镜像。

Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变,代码如下:
p.setShader(lg);
canvas.drawCicle(0,0,200,p); //参数3为画圆的半径,类型为float型。

二、 RadialGradient镜像渐变

有了上面的基础,我们一起来了解下径向渐变。和上面参数唯一不同的是,径向渐变第三个参数是半径,其他的和线性渐变相同。
RadialGradient(float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile) 
RadialGradient(float x, float y, float radius, int color0, int color1, Shader.TileMode tile)
三、 SweepGradient角度渐变
对于一些3D立体效果的渐变可以尝试用角度渐变来完成一个圆锥形,相对来说比上面更简单,前两个参数为中心点,然后通过载入的颜色来平均的渐变渲染。

SweepGradient(float cx, float cy, int[] colors, float[] positions)  
//对于最后一个参数SDK上的描述为May be NULL. The relative position of each corresponding color in the colors array, beginning with 0 and ending with 1.0. If the values are not monotonic, the drawing may produce unexpected results. If positions is NULL, then the colors are automatically spaced evenly,所以建议使用下面的重载方法,本方法一般为NULL即可。
SweepGradient(float cx, float cy, int color0, int color1)

Shader类的派生类可以创建允许使用多种固体颜色填充绘图对象的Paint。
对Shader最常见的使用是定义渐变填充;渐变是在2D图像中添加深度和纹理的最佳方式之一。Android包含了一个Bitmap Shader和一个Compose Shader,同时,还包含了三个渐变的Shader。

试图用语言来描述绘图的效果本来就是没有意义的,所以看一下图11-1就应该可以知道每一种Shader是如何工作的。图中从左到右依次代表的是LinearGradient、RadialGradient和 SweepGradient。


下面自定义一个TextView实现类似下面的效果:


package com.example.msgdialog;

import com.example.msgdialog.utils.DisplayParams;
import com.example.msgdialog.utils.DisplayUtil;

import android.util.AttributeSet;
import android.view.View;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.widget.TextView;

/**
 * 
 * @author poplar
 *	
 */
public class MyTextView extends TextView {

	int pressure = 0;
	/** 要显示的文字 */
	private String text;
	/** 文字的颜色 */
	private int textColor;
	/** 文字的大小 */
	private int textSize;
	/** 文字的方位 */
	private int textAlign;
	
	public static final int TEXT_ALIGN_LEFT              = 0x00000001;
	public static final int TEXT_ALIGN_RIGHT             = 0x00000010;
	public static final int TEXT_ALIGN_CENTER_VERTICAL   = 0x00000100;
	public static final int TEXT_ALIGN_CENTER_HORIZONTAL = 0x00001000;
	public static final int TEXT_ALIGN_TOP               = 0x00010000;
	public static final int TEXT_ALIGN_BOTTOM            = 0x00100000;
	
	/** 文本中轴线X坐标 */
	private float textCenterX;
	/** 文本baseline线Y坐标 */
	private float textBaselineY;
	/** 控件的宽度 */
	private int viewWidth;
	/** 控件的高度 */
	private int viewHeight;
	/** 控件画笔 */
	private Paint paint;
	
	private FontMetrics fm;
	/** 场景 */
	private Context context;
	
	public MyTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.context = context;
		init();
	}

	public MyTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		init();
	}

	public MyTextView(Context context) {
		super(context);
		this.context = context;
		init();		
		
	}
	
	/**
	 * 变量初始化
	 */
	private void init() {
		paint = new Paint();
		paint.setAntiAlias(true);
		paint.setTextAlign(Align.CENTER);
		this.setTextSize(18);
		this.setText("The Office - FirstSeason");
		textAlign = TEXT_ALIGN_LEFT | TEXT_ALIGN_CENTER_VERTICAL;
		this.textColor = Color.WHITE;
	}
	
	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		viewWidth = getWidth();
		viewHeight = getHeight();
		super.onLayout(changed, left, top, right, bottom);
	}
	
	/**
	 *  canvas: 画布、画板,所有东西都会被画在这个上边
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		//绘制控件内容
				setTextLocation();
				RadialGradient rg=new RadialGradient(0, 0, viewWidth, Color.WHITE, Color.BLACK, Shader.TileMode.CLAMP);
				paint.setShader(rg);
				canvas.drawText(text, textCenterX, textBaselineY, paint);
				super.onDraw(canvas);
	}
	
	/**
	 * 定位文本绘制的位置
	 */
	private void setTextLocation() {
		paint.setTextSize(textSize);
		paint.setColor(textColor);
		fm = paint.getFontMetrics();
		//文本的宽度
		float textWidth = paint.measureText(text);
		float textCenterVerticalBaselineY = viewHeight / 2 - fm.descent + (fm.descent - fm.ascent) / 2;
		switch (textAlign) {
		case TEXT_ALIGN_CENTER_HORIZONTAL | TEXT_ALIGN_CENTER_VERTICAL:
			textCenterX = (float)viewWidth / 2;
			textBaselineY = textCenterVerticalBaselineY;
			break;
		case TEXT_ALIGN_LEFT | TEXT_ALIGN_CENTER_VERTICAL:
			textCenterX = textWidth / 2;
			textBaselineY = textCenterVerticalBaselineY;
			break;
		case TEXT_ALIGN_RIGHT | TEXT_ALIGN_CENTER_VERTICAL:
			textCenterX = viewWidth - textWidth / 2;
			textBaselineY = textCenterVerticalBaselineY;
			break;
		case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_CENTER_HORIZONTAL:
			textCenterX = viewWidth / 2;
			textBaselineY = viewHeight - fm.bottom; 
			break;
		case TEXT_ALIGN_TOP | TEXT_ALIGN_CENTER_HORIZONTAL:
			textCenterX = viewWidth / 2;
			textBaselineY = -fm.ascent;
			break;
		case TEXT_ALIGN_TOP | TEXT_ALIGN_LEFT:
			textCenterX = textWidth / 2;
			textBaselineY = -fm.ascent;
			break;
		case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_LEFT:
			textCenterX = textWidth / 2;
			textBaselineY = viewHeight - fm.bottom; 
			break;
		case TEXT_ALIGN_TOP | TEXT_ALIGN_RIGHT:
			textCenterX = viewWidth - textWidth / 2;
			textBaselineY = -fm.ascent;
			break;
		case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_RIGHT:
			textCenterX = viewWidth - textWidth / 2;
			textBaselineY = viewHeight - fm.bottom; 
			break;
		}
	}
	/**
	 * 设置文本内容
	 * @param text
	 */
	public void setText(String text) {
		this.text = text;
		invalidate();
	}
	/**
	 * 设置文本大小
	 * @param textSizeSp 文本大小,单位是sp
	 */
	public void setTextSize(int textSizeSp) {
		
		DisplayParams displayParams = DisplayParams.getInstance(context);
		this.textSize = DisplayUtil.sp2px(textSizeSp, displayParams.fontScale);
		invalidate();
	}
	/**
	 * 设置文本的方位
	 */
	public void setTextAlign(int textAlign) {
		this.textAlign = textAlign;
		invalidate();
	}
	/**
	 * 设置文本的颜色
	 * @param textColor
	 */
	public void setTextColor(int textColor) {
		this.textColor = textColor;
		invalidate();
	}
	
}
布局文件 :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"  
    tools:context="${relativePackage}.${activityClass}" 
    android:orientation="vertical">

    <com.example.msgdialog.MyTextView 
        android:layout_margin="10dip"
        android:id="@+id/my_tv"
        android:padding="10dip"
        android:layout_width="180dp"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:gravity="center"
        android:layout_gravity="center_horizontal"
        android:background="#000000"/>
</LinearLayout>
运行效果如下:




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值