Android实现textView倒影效果ReflectTextView

代码转载自https://github.com/Dean1990/ReflectTextView by Dean1990

效果

要实现带倒影效果的textview,效果如下
在这里插入图片描述
有2种方法,一种是如果是只有数字和字母,让设计切出来相应带倒影效果的文字图片,需要哪张图,就用哪张图显示即可。还有一种就是重写TextView,加上倒影效果。

实现

ReflectTextView.java

话不多说,先上代码,本地新建ReflectTextView.java类,代码如下:

package com.ui.common;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;

public class ReflectTextView extends TextView
{
	private Matrix mMatrix;
	private Paint mPaint;

	private static int REFLECT_ALPHA;// 倒影透明度
	private static float REFLECT_HEIGHT_MULTIPLE;// 倒影的高度倍数
	private static int SPACING_VALUE;// 实体文字与倒影之间的空隙
	private static float OFF_Y;// Y轴偏移,由于倒影的高度倍数设置小于1时就会出现偏移,显示部分倒影

	public ReflectTextView(Context context, AttributeSet attrs)
	{
		this(context, attrs, 0);

	}

	public ReflectTextView(Context context, AttributeSet attrs, int defStyleAttr)
	{
		super(context, attrs, defStyleAttr);

		REFLECT_ALPHA = 100;
		REFLECT_HEIGHT_MULTIPLE = 0.5f;
		SPACING_VALUE = 0;

		TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
				R.styleable.reflect, defStyleAttr, 0);
		int n = a.getIndexCount();
		for (int i = 0; i < n; i++)
		{
			int attr = a.getIndex(i);

			if (attr == R.styleable.reflect_reflectAlpha)
			{
				// 倒影透明度[1-255]
				REFLECT_ALPHA = a.getInteger(attr, 100);// 默认100
				if (REFLECT_ALPHA < 1)
					REFLECT_ALPHA = 1;
				else if (REFLECT_ALPHA > 255)
					REFLECT_ALPHA = 255;
			}
			else if (attr == R.styleable.reflect_reflectHeightMultiple)
			{
				// 倒影的高度倍数[0-1]
				REFLECT_HEIGHT_MULTIPLE = a.getFloat(attr, 1f);// 默认1
				if (REFLECT_HEIGHT_MULTIPLE < 0)
					REFLECT_HEIGHT_MULTIPLE = 0;
				else if (REFLECT_HEIGHT_MULTIPLE > 1)
					REFLECT_HEIGHT_MULTIPLE = 1;
			}
			else if (attr == R.styleable.reflect_spacingValue)
			{
				// 实体文字与倒影之间的空隙 默认10dp
				SPACING_VALUE = a.getDimensionPixelSize(attr, (int) TypedValue
						.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0,
								getResources().getDisplayMetrics()));
			}
		}
		a.recycle();

		init();
	}

	private void init()
	{

		mMatrix = new Matrix();
		mMatrix.preScale(1, -1);
		// 这句是关闭硬件加速,启用软件加速,如果报相关错误可以尝试注释这句代码
		setLayerType(View.LAYER_TYPE_SOFTWARE, null);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		int temp = (int) (getMeasuredHeight() - (getLineHeight() - getTextSize()) / 2);
		OFF_Y = temp - temp * REFLECT_HEIGHT_MULTIPLE;
		setMeasuredDimension(getMeasuredWidth(), Math.round(temp * 2 - OFF_Y)
				+ SPACING_VALUE);
	}

	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
		int height = getMeasuredHeight();
		int width = getMeasuredWidth();
		setDrawingCacheEnabled(true);
		Bitmap originalImage = getDrawingCache();
		Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, 0,
				Math.min(width, originalImage.getWidth()), height, mMatrix,
				false);
		Paint paint = new Paint();
		paint.setAlpha(REFLECT_ALPHA);
		canvas.drawBitmap(reflectionImage, 0, OFF_Y, paint);
		if (mPaint == null)
		{
			mPaint = new Paint();
			// 阴影的效果可以自己根据需要设定
			LinearGradient shader = new LinearGradient(0, (height + OFF_Y) / 2,
					0, height, 0xffffffff, 0x00ffffff, Shader.TileMode.CLAMP);
			mPaint.setShader(shader);
			mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
		}
		canvas.drawRect(0, (height + OFF_Y) / 2, width, height, mPaint);
	}

	@Override
	protected void onTextChanged(CharSequence text, int start,
			int lengthBefore, int lengthAfter)
	{
		super.onTextChanged(text, start, lengthBefore, lengthAfter);
		buildDrawingCache();
		postInvalidate();
		// 每次更新TextView后遗留上次的残影,所以在这里每次刷新TextView后清楚DrawingCache
		destroyDrawingCache();
	}
}

attrs.xml配置

配置reflectAlpha、reflectHeightMultiple、spacingValue参数,便于在布局文件中使用

<resources>

    <declare-styleable name="reflect">
        <attr name="reflectAlpha" format="integer" />
        <attr name="reflectHeightMultiple" format="float" />
        <attr name="spacingValue" format="dimension" />
    </declare-styleable>

</resources>

xml布局文件中使用

//需要最外层布局文件中加入此代码,便可以引用reflect
xmlns:reflect="http://schemas.android.com/apk/res-auto"

//布局文件引用
	<com.skypine.ui.common.ReflectTextView
            android:id="@+id/rtv_freq"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="188dp"
            android:lineSpacingMultiplier="0.7"
            android:textColor="@color/white"
            android:textSize="@dimen/text_size100"
            android:textStyle="bold"
            reflect:reflectAlpha="120"
            reflect:reflectHeightMultiple="0.3"
            reflect:spacingValue="12dp" />

参数说明

参数名说明默认值
reflect:spacingValue实体文字与倒影之间的空隙0dp
reflect:reflectAlpha倒影透明度100,取值范围 [1-255]
reflect:reflectHeightMultiple倒影的高度倍数1f,取值范围 [0-1f]

代码中使用就和普通的TextView一样,绑定之后,直接setText即可。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值