Android 自定义变化的文本控件ColorChangeView
发布日期:2021-06-30 22:35:22 浏览次数:2 分类:技术文章

本文共 17664 字,大约阅读时间需要 58 分钟。

实例图

这里写图片描述

说明图

这里写图片描述

/** * 有颜色过渡变化的textview *  * @Project App_View * @Package com.android.view.colortextview * @author chenlin * @version 1.0 * @Note TODO *//** * 有颜色过渡变化的textview *  * @Project App_View * @Package com.android.view.colortextview * @author chenlin * @version 1.0 * @Note TODO */public class ColorChangeView extends View {
public static final int DIRECTION_LEFT = 0; public static final int DIRECTION_RIGHT = 1; public static final int DIRECTION_TOP = 2; public static final int DIRECTION_BOTTOM = 3; public static final String DEFAULT_TEXT = "颜色变化"; // 默认字体大小 private static final int DEF_TEXT_SIZE = 0; // 文本内容 private String mText; // 文本大小 private int mTextSize = sp2px(30); // 文本原来颜色 private int mOriginColor = 0xff000000; // 文本改变后的颜色 private int mChangeColor = 0xffff0000; // 改变颜色时的进度百分比 private float mProgress; // 改变颜色的方向,默认从左边开始变色 private int mDirection = DIRECTION_LEFT; // 绘制文本的画笔 private Paint mPaint; // ---测量信息---------------------------------------- // 文本宽度 private int mTextWidth; // 文本高度 private int mTextHeight; // 文本区域 private Rect mTextBound = new Rect(); // 开始移动坐标 private int mTextStartX; private int mTextStartY; /** 总共分四个方向 */ public enum Direction { LEFT, RIGHT, TOP, BOTTOM; } public ColorChangeView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public ColorChangeView(Context context) { this(context, null); } private void init(Context context, AttributeSet attrs) { // 初始化画笔 mPaint = new Paint(); mPaint.setAntiAlias(true); // 初始化自定义属性 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColorChangeView); mText = ta.getString(R.styleable.ColorChangeView_text); mTextSize = ta.getDimensionPixelSize(R.styleable.ColorChangeView_text_size, mTextSize); mOriginColor = ta.getColor(R.styleable.ColorChangeView_text_origin_color, mOriginColor); mChangeColor = ta.getColor(R.styleable.ColorChangeView_text_change_color, mChangeColor); mProgress = ta.getFloat(R.styleable.ColorChangeView_progress, 0); mDirection = ta.getInt(R.styleable.ColorChangeView_direction, mDirection); ta.recycle(); // 为画笔设置文本大小 mPaint.setTextSize(mTextSize); } /** * 测量 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 第一步:先测量文本的区域大小 measureText(); // 第二步:对视图测量 int width = measureWidth(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); // 这个方法决定了当前View的大小 setMeasuredDimension(width, height); // 从有文字的位置开始绘制 mTextStartX = (getMeasuredWidth() - mTextWidth) / 2; mTextStartY = (getMeasuredHeight() - mTextHeight) / 2; } /** * 测量高度 * * @param heightMeasureSpec * @return */ private int measureHeight(int heightMeasureSpec) { int height = 0; int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); switch (heightMode) { case MeasureSpec.EXACTLY: height = heightSize; break; case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: height = mTextBound.height(); height += getPaddingBottom() + getPaddingTop(); break; } return height = heightMode == MeasureSpec.AT_MOST ? Math.min(height, heightSize) : height; } /** * 测量宽度 * * @param widthMeasureSpec * @return */ private int measureWidth(int widthMeasureSpec) { int width = 0; int widthtSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); switch (widthMode) { case MeasureSpec.EXACTLY: width = widthtSize; break; case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: width = mTextWidth; width += getPaddingLeft() + getPaddingRight(); break; } return width = widthMode == MeasureSpec.AT_MOST ? Math.min(width, widthtSize) : width; } /** * 对文本控件测量,得到绘制时的宽高 */ private void measureText() { mTextWidth = (int) mPaint.measureText(mText); FontMetrics fm = mPaint.getFontMetrics(); // 文本的最低处-文本的最高处 mTextHeight = (int) Math.ceil(fm.descent - fm.top); mPaint.getTextBounds(mText, 0, mText.length(), mTextBound); // 获得高度 mTextHeight = mTextBound.height(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 水平移动距离 int distance_x = (int) (mProgress * mTextWidth + mTextStartX); // 垂直移动距离 int distance_y = (int) (mProgress * mTextHeight + mTextStartY); // 从左移动 if (mDirection == DIRECTION_LEFT) { drawOriginLeft(canvas, distance_x); drawChangeLeft(canvas, distance_x); // 从右移动 } else if (mDirection == DIRECTION_RIGHT) { drawOriginRight(canvas, distance_x); drawChangeRight(canvas, distance_x); // 从上移动 } else if (mDirection == DIRECTION_TOP) { drawOriginTop(canvas, distance_y); drawChangeTop(canvas, distance_y); } else if (mDirection == DIRECTION_BOTTOM) { // 从底部移动 drawOriginBottom(canvas, distance_y); drawChangeBottom(canvas, distance_y); } } /** * 反转颜色 */ public void reverseColor() { int tmp = mOriginColor; mOriginColor = mChangeColor; mChangeColor = tmp; } /** * 从左绘制变化的文本 * * @param canvas * @param hProgress */ private void drawChangeLeft(Canvas canvas, int distance_x) { drawText_x(canvas, mChangeColor, mTextStartX, distance_x); } /** * 从左绘制原来的文本 * * @param canvas * @param hProgress */ private void drawOriginLeft(Canvas canvas, int distance_x) { drawText_x(canvas, mOriginColor, distance_x, mTextStartX + mTextWidth); } /** * 从右边绘制原文本 * * @param canvas * @param distance_x */ private void drawOriginRight(Canvas canvas, int distance_x) { drawText_x(canvas, mOriginColor, (int) (mTextStartX + (1 - mProgress) * mTextWidth), mTextStartX + mTextWidth); } /** * 从右边绘制变化文本 * * @param canvas * @param distance_x */ private void drawChangeRight(Canvas canvas, int distance_x) { drawText_x(canvas, mChangeColor, mTextStartX, (int) (mTextStartX + (1 - mProgress) * mTextWidth)); } private void drawOriginTop(Canvas canvas, int distance_y) { drawText_y(canvas, mOriginColor, mTextStartY, (int) (mTextStartY + mProgress * mTextHeight)); } private void drawChangeTop(Canvas canvas, int distance_y) { drawText_y(canvas, mChangeColor, (int) (mTextStartY + mProgress * mTextHeight), mTextStartY + mTextHeight); } private void drawChangeBottom(Canvas canvas, int distance_y) { drawText_y(canvas, mChangeColor, (int) (mTextStartY + (1 - mProgress) * mTextHeight), mTextStartY + mTextHeight); } private void drawOriginBottom(Canvas canvas, int distance_y) { drawText_y(canvas, mOriginColor, mTextStartY, (int) (mTextStartY + (1 - mProgress) * mTextHeight)); } private boolean debug = false; /** * 水平绘制 * * @param canvas * @param color * @param startX * @param endX */ private void drawText_x(Canvas canvas, int color, int startX, int endX) { mPaint.setColor(color); if (debug) { mPaint.setStyle(Style.STROKE); // 第一步:先绘制矩形区域,在这之前,设定画笔的颜色 canvas.drawRect(startX, 0, endX, getMeasuredHeight(), mPaint); } canvas.save(Canvas.CLIP_SAVE_FLAG); // 第二步:实现动画绘制,在之前,先保存绘制好的区域 canvas.clipRect(startX, 0, endX, getMeasuredHeight()); // 第三步:绘制出整个文本, mPaint.descent() + mPaint.ascent() = 字体的高 getMeasuredHeight是view的高 canvas.drawText(mText, mTextStartX, getMeasuredHeight() / 2 - ((mPaint.descent() + mPaint.ascent()) / 2), mPaint); // 第四步:恢复画布 canvas.restore(); } /** * 垂直绘制 * * @param canvas * @param color * @param startY * @param endY */ private void drawText_y(Canvas canvas, int color, int startY, int endY) { mPaint.setColor(color); if (debug) { mPaint.setStyle(Style.STROKE); // 第一步:先绘制矩形区域,在这之前,设定画笔的颜色 canvas.drawRect(0, startY, getMeasuredWidth(), endY, mPaint); } canvas.save(Canvas.CLIP_SAVE_FLAG); // 第二步:实现动画绘制,在之前,先保存绘制好的区域 canvas.clipRect(0, startY, getMeasuredWidth(), endY); // 第三步:绘制出整个文本, mPaint.descent() + mPaint.ascent() = 字体的高 getMeasuredHeight是view的高 canvas.drawText(mText, mTextStartX, getMeasuredHeight() / 2 - ((mPaint.descent() + mPaint.ascent()) / 2), mPaint); // 第四步:恢复画布 canvas.restore(); } // --Set Get --向外提供的方法-------------------------------------------------------- public void setDirection(int direction) { this.mDirection = direction; } public float getProgress() { return mProgress; } public void setProgress(float progress) { this.mProgress = progress; invalidate(); } public int getTextSize() { return mTextSize; } public void setTextSize(int textSize) { this.mTextSize = textSize; mPaint.setTextSize(mTextSize); requestLayout(); invalidate(); } public void setText(String text) { this.mText = text; requestLayout(); invalidate(); } public int getTextOriginColor() { return mOriginColor; } public void setTextOriginColor(int originColor) { this.mOriginColor = originColor; invalidate(); } public int getTextChangeColor() { return mChangeColor; } public void setTextChangeColor(int changeColor) { this.mChangeColor = changeColor; invalidate(); } // ---像素转化函数---------------------------------------------------- public int dp2px(float dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics()); } public int sp2px(float dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dpVal, getResources().getDisplayMetrics()); } // ----保存和恢复数据----------------------------------------------------------------- private static final String KEY_STATE_PROGRESS = "key_progress"; private static final String KEY_DEFAULT_STATE = "key_default_state"; @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putFloat(KEY_STATE_PROGRESS, mProgress); bundle.putParcelable(KEY_DEFAULT_STATE, super.onSaveInstanceState()); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; mProgress = bundle.getFloat(KEY_STATE_PROGRESS); super.onRestoreInstanceState(bundle.getParcelable(KEY_DEFAULT_STATE)); return; } super.onRestoreInstanceState(state); }}

运用

public class HomeActivity extends ListActivity {
private String[] mTitles = new String[] { "简单使用", "变化应用" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getListView().setAdapter(new ArrayAdapter
(this, android.R.layout.simple_list_item_1, mTitles)); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { Intent intent = null; switch (position) { case 0: intent = new Intent(this,SimpleActivity.class); break; case 1: intent = new Intent(this,ViewPagerActivity.class); break; } if (intent != null) { startActivity(intent); } }}

1)简单运用

public class SimpleActivity extends Activity implements OnClickListener {
@ViewInject(R.id.id_changeTextColorView) private ColorChangeView mView; @ViewInject(R.id.id_left) private Button mBtnLeft; @ViewInject(R.id.id_right) private Button mBtnRight; @ViewInject(R.id.id_top) private Button mBtnTop; @ViewInject(R.id.id_bottom) private Button mBtnBottom; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simpepager); ViewUtils.inject(this); initEvents(); } private void initEvents() { mBtnLeft.setOnClickListener(this); mBtnRight.setOnClickListener(this); mBtnTop.setOnClickListener(this); mBtnBottom.setOnClickListener(this); } @Override public void onClick(View v) { if (v == mBtnLeft) { mView.setDirection(ColorChangeView.DIRECTION_LEFT); ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start(); }else if (v == mBtnRight) { mView.setDirection(ColorChangeView.DIRECTION_RIGHT); ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start(); }else if (v == mBtnTop) { mView.setDirection(ColorChangeView.DIRECTION_TOP); ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start(); }else if (v == mBtnBottom) { mView.setDirection(ColorChangeView.DIRECTION_BOTTOM); ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start(); } }}

布局

2)使用viewpager展示

public class ViewPagerActivity extends FragmentActivity {
private String[] mTitles = new String[] { "简介", "评价", "相关" }; //创建viewpager private ViewPager mViewPager; //定义数据数组 private TabFragment[] mDatas = new TabFragment[mTitles.length]; //定义标题控件 private List
mTabs = new ArrayList
(); private FragmentPagerAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_viewpager); initViews(); initDatas(); initEvenvts(); } private void initViews() { mViewPager = (ViewPager) findViewById(R.id.id_viewpager); mTabs.add((ColorChangeView) findViewById(R.id.id_tab_01)); mTabs.add((ColorChangeView) findViewById(R.id.id_tab_02)); mTabs.add((ColorChangeView) findViewById(R.id.id_tab_03)); } private void initDatas() { for (int i = 0; i < mTitles.length; i++) { mDatas[i] = TabFragment.newInstance(mTitles[i]); } mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()){ @Override public Fragment getItem(int position) { return mDatas[position]; } @Override public int getCount() { return mTitles.length; } }; mViewPager.setAdapter(mAdapter); mViewPager.setCurrentItem(0); } private void initEvenvts() { mViewPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (positionOffset > 0) { ColorChangeView left = mTabs.get(position); left.setDirection(ColorChangeView.DIRECTION_LEFT); left.setProgress(1-positionOffset); ColorChangeView right = mTabs.get(position+1); right.setDirection(ColorChangeView.DIRECTION_RIGHT); right.setProgress(positionOffset); } } @Override public void onPageScrollStateChanged(int state) { } }); }}

Fragment代码

public class TabFragment extends Fragment {
public static final String TITLE = "title"; private String mTitle = "Defaut Value"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mTitle = getArguments().getString(TITLE); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView tv = new TextView(getActivity()); tv.setTextSize(60); Random r = new Random(); tv.setBackgroundColor(Color.argb(r.nextInt(120), r.nextInt(255), r.nextInt(255), r.nextInt(255))); tv.setText(mTitle); tv.setGravity(Gravity.CENTER); return tv; } public static TabFragment newInstance(String title) { TabFragment tabFragment = new TabFragment(); Bundle bundle = new Bundle(); bundle.putString(TITLE, title); //保存标题信息 tabFragment.setArguments(bundle); return tabFragment; }}

相关布局

———————————————————————

有需求者请加qq:136137465,非诚勿扰
(java 架构师全套教程,共760G, 让你从零到架构师,每月轻松拿3万)
01.高级架构师四十二个阶段高
02.Java高级系统培训架构课程148课时
03.Java高级互联网架构师课程
04.Java互联网架构Netty、Nio、Mina等-视频教程
05.Java高级架构设计2016整理-视频教程
06.架构师基础、高级片
07.Java架构师必修linux运维系列课程
08.Java高级系统培训架构课程116课时
(送:hadoop系列教程,java设计模式与数据结构, Spring Cloud微服务, SpringBoot入门)
——————————————————————–

转载地址:https://lovoo.blog.csdn.net/article/details/51263104 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:C游戏 简单迷宫游戏开发
下一篇:Android 内容提供者ContentProvider

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月11日 00时13分19秒