Android仿今日頭條文字漸變效果
概述

繪制水平垂直居中的文本
采用畫布裁剪實(shí)現(xiàn)漸變效果
繪制水平垂直居中的文本
文本水平居中
調(diào)用Paint的setTextAlign(Paint.Align.CENTER)方法
控件寬度 / 2 - 文字寬度 / 2計算文本的x軸坐標(biāo)
文本垂直居中
獲取View的中心位置
中心位置下移半個字體的高度
上移descent,達(dá)到文字的最終位置即BaseLine的位置
代碼實(shí)現(xiàn)如下:
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();float baseLine = (getHeight() + fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
為了方便理解,baseLine的計算,可參考下圖:

畫布裁剪實(shí)現(xiàn)漸變效果
//漸變部分private void drawGradientText(Canvas canvas) {//保存當(dāng)前畫布canvas.save();//文字水平居中方案二:x = getWidth() / 2 - 文字寬度 / 2float textWidth = mTextPaint.measureText(mText, 0, mText.length());float x = (getWidth() - textWidth) / 2;//文字垂直居中:BaseLine的計算 = getHeight() / 2 + 文字高度 / 2 - descentPaint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();float textHeight = fontMetrics.descent - fontMetrics.ascent;float y = (getHeight() + textHeight) / 2 - fontMetrics.descent;mTextPaint.setColor(Color.RED);//先裁剪漸變區(qū)域文字要顯示的區(qū)域float right = x + textWidth * mPercent;canvas.clipRect(x, 0, right, getHeight());//裁剪完成后再繪制文字canvas.drawText(mText, x, y, mTextPaint);//恢復(fù)畫布canvas.restore();}//不變部分private void drawNormalText(Canvas canvas) {canvas.save();float textWidth = mTextPaint.measureText(mText, 0, mText.length());float x = (getWidth() - textWidth) / 2;Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();float textHeight = fontMetrics.descent - fontMetrics.ascent;float y = (getHeight() + textHeight) / 2 - fontMetrics.descent;mTextPaint.setColor(Color.BLACK);//對不變區(qū)域文字進(jìn)行裁剪,防止過度繪制(這個很重要)float left = x + textWidth * mPercent;canvas.clipRect(left, 0, x + textWidth, getHeight());canvas.drawText(mText, x, y, mTextPaint);canvas.restore();}
仿今日頭條文字漸變效果實(shí)現(xiàn)思路
漸變控件關(guān)鍵代碼:
public class ColorChangeTextView extends AppCompatTextView {private int mTextSize = sp2px(30);private int mTextColor = Color.BLACK;private int mTextColorChange = Color.RED;private TextPaint mTextPaint;private int mDirection = LEFT;//文件漸變方向protected static final int LEFT = 0;protected static final int RIGHT = 1;@IntDef(value = {LEFT, RIGHT})@Retention(RetentionPolicy.SOURCE)public @interface Direction {}private float mProgress;//文字漸變的進(jìn)度public float getProgress() {return mProgress;}public void setProgress(float mProgress) {this.mProgress = mProgress;invalidate();}public void setDirection(@Direction int direction) {this.mDirection = direction;}public ColorChangeTextView(Context context) {this(context, null);}public ColorChangeTextView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public ColorChangeTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initAttr(context, attrs);init();}private void initAttr(final Context context, @Nullable final AttributeSet attrs) {TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ColorChangeTextView);mTextSize = ta.getDimensionPixelSize(R.styleable.ColorChangeTextView_text_size, mTextSize);mTextColor = ta.getColor(R.styleable.ColorChangeTextView_text_color, mTextColor);mTextColorChange = ta.getColor(R.styleable.ColorChangeTextView_text_color_change, mTextColorChange);mProgress = ta.getFloat(R.styleable.ColorChangeTextView_progress, 0);ta.recycle();}private void init() {mTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);mTextPaint.setColor(mTextColor);mTextPaint.setTextSize(mTextSize);}@Overrideprotected void onDraw(Canvas canvas) {switch (mDirection){case LEFT:drawLeft(canvas);break;case RIGHT:drawRight(canvas);break;}}private void drawLeft(Canvas canvas){//繪制底部不變部分canvas.save();String text = getText().toString();float textWidth = mTextPaint.measureText(text);Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();float textHeight = fontMetrics.descent - fontMetrics.ascent;float x = (getWidth() - textWidth) / 2;float baseLine = (getHeight() + textHeight) / 2 - fontMetrics.descent;float left = x + textWidth * mProgress;canvas.clipRect(left,0,x + textWidth,getHeight());mTextPaint.setColor(mTextColor);canvas.drawText(text,x,baseLine,mTextPaint);canvas.restore();//繪制頂部漸變部分canvas.save();float right = x + textWidth * mProgress;canvas.clipRect(x,0,right,getHeight());mTextPaint.setColor(mTextColorChange);canvas.drawText(text,x,baseLine,mTextPaint);canvas.restore();}private void drawRight(Canvas canvas) {//繪制頂部漸變部分canvas.save();String text = getText().toString();float textWidth = mTextPaint.measureText(text);Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();float textHeight = fontMetrics.descent - fontMetrics.ascent;float baseLine = (getHeight() + textHeight) / 2 - fontMetrics.descent;float x = (getWidth() - textWidth) / 2;float left = x + textWidth * (1 - mProgress);float right = x + textWidth;canvas.clipRect(left,0,right,getHeight());mTextPaint.setColor(mTextColorChange);canvas.drawText(text,x,baseLine,mTextPaint);canvas.restore();//繪制底部不變部分canvas.save();right = x + textWidth * (1 - mProgress);canvas.clipRect(0,0,right,getHeight());mTextPaint.setColor(mTextColor);canvas.drawText(text,x,baseLine,mTextPaint);canvas.restore();}static int sp2px(float sp) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, Resources.getSystem().getDisplayMetrics());}}
mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {if(positionOffset > 0){ColorChangeTextView left = mTabs.get(position);ColorChangeTextView right = mTabs.get(position + 1);left.setDirection(ColorChangeTextView.RIGHT);right.setDirection(ColorChangeTextView.LEFT);left.setProgress(1- positionOffset);right.setProgress(positionOffset);}}});
評論
圖片
表情
