1.分解步驟
- 1.分析效果
- 2.確定自定義屬性中燥,編寫(xiě)attrs.xml
- 3.在布局中使用
- 4.編寫(xiě)自定義控件實(shí)現(xiàn)類(lèi)
- 5.定義并初始化所需變量(如文字畫(huà)筆,顏色進(jìn)度占比等)
- 5.ondraw()畫(huà)文字斧蜕,編寫(xiě)繪制邏輯(主要運(yùn)用到“切割畫(huà)板”的思想)
- 6.其他處理(動(dòng)畫(huà)效果)
2.具體步驟
- attrs.xml文件 定義需要的控件內(nèi)部屬性變量
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ColorTrackTextView">
<attr name="originColor" format="color"/>//初始顏色
<attr name="changeColor" format="color"/>//切換顏色
</declare-styleable>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.incall.apps.textswitch.ColorTrackTextView
android:id="@+id/text_draw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="32sp"
android:layout_gravity="center"
app:originColor="@color/black"
app:changeColor="@color/teal_200"
android:text="Hello World !!"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="左到右"
android:layout_gravity="center"
android:onClick="leftToRight"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="右到右"
android:layout_gravity="center"
android:onClick="rightToLeft"/>
</LinearLayout>
- 編寫(xiě)控件類(lèi)ColorTrackTextView,繼承textView
package com.incall.apps.textswitch;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;
import androidx.annotation.Nullable;
@SuppressLint("AppCompatCustomView")
public class ColorTrackTextView extends TextView {
private Paint mOriginPaint; //初始顏色畫(huà)筆
private Paint mChangePaint; //變化顏色畫(huà)筆
//設(shè)置變色百分比
private float currentProgress = 0.0f;
//設(shè)置變色朝向
Direction mdirection = Direction.LEFT_TO_RIGHT;
enum Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT;
}
public ColorTrackTextView(Context context) {
this(context, null);
}
public ColorTrackTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorTrackTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public ColorTrackTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initPaint(context, attrs);
}
/**
* 初始化
*/
private void initPaint(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);
int orginColor = array.getColor(R.styleable.ColorTrackTextView_originColor, getTextColors().getDefaultColor());
int changeColor = array.getColor(R.styleable.ColorTrackTextView_changeColor, getTextColors().getDefaultColor());
mOriginPaint = getPaintByColor(orginColor);
mChangePaint = getPaintByColor(changeColor);
array.recycle();
}
/**
* 根據(jù)顏色值獲取畫(huà)筆
*
* @return
*/
private Paint getPaintByColor(int color) {
Paint paint = new Paint();
//設(shè)置顏色
paint.setColor(color);
//抗鋸齒
paint.setAntiAlias(true);
//防抖動(dòng)
paint.setDither(true);
//設(shè)置字體大小
paint.setTextSize(getTextSize());
return paint;
}
@Override
protected void onDraw(Canvas canvas) {
int middle = (int) (currentProgress * getWidth());
//從左變到右
if (mdirection == Direction.LEFT_TO_RIGHT) {
drawText(canvas, mOriginPaint, middle, getWidth());
drawText(canvas, mChangePaint, 0, middle);
}
//從右邊變到左
else if (mdirection == Direction.RIGHT_TO_LEFT) {
drawText(canvas, mOriginPaint, 0, getWidth() - middle);
drawText(canvas, mChangePaint, getWidth() - middle, getWidth());
}
}
/**
* * @description 文字圖像繪制
* @param canvas
* @param paint
* @param start
* @param end
* @return void
*/
private void drawText(Canvas canvas, Paint paint, int start, int end) {
canvas.save();//保存畫(huà)板
//根據(jù)進(jìn)度計(jì)算中間值
Rect rect = new Rect(start, 0, end, getHeight());
canvas.clipRect(rect);
String text = getText().toString();
//計(jì)算起始位置
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
int x = getWidth() / 2 - bounds.width() / 2;
//計(jì)算基線
Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
int dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
int baseLine = getHeight() / 2 + dy;
canvas.drawText(text, x, baseLine, paint);
canvas.restore();//釋放畫(huà)板
}
public void setCurrentProgress(float currentProgress) {
this.currentProgress = currentProgress;
invalidate();
}
public void setMdirection(Direction mdirection) {
this.mdirection = mdirection;
}
}
- 編寫(xiě)MainActivity,添加屬性動(dòng)畫(huà)君旦,添加按鈕邏輯
package com.incall.apps.textswitch;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
ColorTrackTextView textDraw;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textDraw = findViewById(R.id.text_draw);
}
public void leftToRight(View view) {
textDraw.setMdirection(ColorTrackTextView.Direction.LEFT_TO_RIGHT);
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 1);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentProgress = (Float) animation.getAnimatedValue();
textDraw.setCurrentProgress(currentProgress);
}
});
valueAnimator.start();
}
public void rightToLeft(View view) {
textDraw.setMdirection(ColorTrackTextView.Direction.RIGHT_TO_LEFT);
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 1);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentProgress = (Float) animation.getAnimatedValue();
textDraw.setCurrentProgress(currentProgress);
}
});
valueAnimator.start();
}
}
3.效果圖