900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 打造炫酷通用的ViewPager指示器 玩转字体变色

打造炫酷通用的ViewPager指示器 玩转字体变色

时间:2022-07-20 09:53:31

相关推荐

打造炫酷通用的ViewPager指示器   玩转字体变色

###1.概述

最近一直都在仿着其他项目的效果在做,仿内涵段子,二手车之家等等。会不会有一天被抓还真是有点心虚,我这分明是给这些APP打广告。等这些效果基本讲完就开始设计模式和系统框架一整套的视频也就会出来了,等总的访问量达到100万之后就会利用空余的时间去录制Java基础和Android基础,请各位多多start和suggest。我们来看一下效果:

###2.效果实现

2.1 整合上一个实例:

底部Fragment切换以及列表加轮播条都是从上一篇博客Android Fragment 从源码的角度去解析(下)中直接拿过来的效果,我们这里主要实现的是首页ViewPager指示器的变色效果以及切换效果。 其实我早就想写这个效果了,可能是那时候脑子短路了没有去过多的想,后来自己想到了实现方式也没有去写怕绕弯子在网上对比了一下才开始的,那么我们就彻底的来实现一下。2.2 实现思路:

我们看到这效果之后,就会尼玛网上有没有?不要害怕不要担心其实分析了之后自己写也很简单的:2.2.1我们肯定要自定义View但是继承自谁呢?View or TextView 其实这里最好继承自TextView,这分明就是一个TextView,而且不需要测量宽高,你看TextView的onMesure()方法你就知道要比继承自View少多少代码。2.2.2怎样才能达到变色?肯定需要去绘制,只要搞两个画笔不断的绘制各自的区域就能出来。2.2.3还是不会,但是得动起来才知道,我们先实现一个TextView两种颜色再说。

2.3 实现两种颜色的TextView:我们先实现一下简单的效果一个TextView两种颜色,黑色和红色吧?大致的思路就是:2.3.1根据当前的进度为了演示效果我就默认为0.6f,那么中间的分割位置就是0.6f*控件的宽度2.3.2在onDraw()中我们利用计算好的分割位置自己去绘制文字,裁剪绘制内容部分即可2.3.3画文字是canvas.drawText(String text, float x, float y, Paint paint) 这些参数不了解的你得自己去google看一下了,温馨提示参数y是文字的基线,给一张图片看看吧:

/*** Created by Darren on /12/5.* Email: 240336124@* Description: 文字颜色跟踪的TextView*/public class ColorTrackTextView extends TextView {// 默认的字体颜色的画笔private Paint mOriginPaint;// 改变的字体颜色的画笔private Paint mChangePaint;// 当前的进度private float mCurrentProgress = 0.6f;private String TAG = "CTTV";// 当前文本private String mText;public ColorTrackTextView(Context context) {this(context, null);}public ColorTrackTextView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public ColorTrackTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initPaint();}/*** 初始化画笔*/private void initPaint() {mOriginPaint = getPaintByColor(Color.BLACK);mChangePaint = getPaintByColor(Color.RED);}/*** 获取画笔根据不同的颜色*/private Paint getPaintByColor(int color) {Paint paint = new Paint();// 抗锯齿paint.setAntiAlias(true);// 仿抖动paint.setDither(true);paint.setColor(color);// 字体的大小设置为TextView的文字大小paint.setTextSize(getTextSize());return paint;}/*** 这里肯定是自己去画 不能用super*/@Overrideprotected void onDraw(Canvas canvas) {// 获取当前文本mText = getText().toString();// 获取控件宽度int width = getWidth();if (!TextUtils.isEmpty(mText)) {// 根据当前进度计算中间位置int middle = (int) (width * mCurrentProgress);drawOrigin(canvas, middle);drawChange(canvas, middle);}}/*** 画变色的字体部分*/private void drawChange(Canvas canvas, int middle) {drawText(canvas, mChangePaint, 0, middle);}/*** 画不变色的字体部分*/private void drawOrigin(Canvas canvas, int middle) {drawText(canvas, mOriginPaint, middle, getWidth());}/*** 绘制文本根据指定的位置** @param canvas canvas画布* @param paint 画笔* @param startX 开始的位置* @param endX 结束的位置*/private void drawText(Canvas canvas, Paint paint, int startX, int endX) {// 保存画笔状态canvas.save();// 截取绘制的内容,待会就只会绘制clipRect设置的参数部分canvas.clipRect(startX, 0, endX, getHeight());// 获取文字的范围Rect bounds = new Rect();mOriginPaint.getTextBounds(mText, 0, mText.length(), bounds);// 获取文字的Metrics 用来计算基线Paint.FontMetricsInt fontMetrics = mOriginPaint.getFontMetricsInt();// 获取文字的宽高int fontTotalHeight = fontMetrics.bottom - fontMetrics.top;// 计算基线到中心点的位置int offY = fontTotalHeight / 2 - fontMetrics.bottom;// 计算基线位置int baseline = (getMeasuredHeight() + fontTotalHeight) / 2 - offY;canvas.drawText(mText, getMeasuredWidth() / 2 - bounds.width() / 2, baseline, paint);// 释放画笔状态canvas.restore();}}复制代码

看上面的代码其实还是挺简单的,我截取了一张效果图

2.4 实现左右不同方向不断变色:当一个TextView有了两种文字颜色之后,我们接下来就不断的控制当前的进度mCurrentProgress变量不断的绘制然后给两个朝向从左到右,从右到左,还把写死的两个颜色值变成自定义的属性,自定义属性应该不用说了吧?如果实在不行等周末看视频吧,这里就不做过多的讲解。我这里只贴出修改部分代码,如果觉得有点扯那就下载完整代码吧:

// 当前朝向private Direction mDirection = DIRECTION_LEFT;// 绘制的朝向枚举public enum Direction {DIRECTION_LEFT, DIRECTION_RIGHT}@Overrideprotected void onDraw(Canvas canvas) {// 获取当前文本mText = getText().toString();// 获取控件宽度int width = getWidth();if (!TextUtils.isEmpty(mText)) {// 根据当前进度计算中间位置int middle = (int) (width * mCurrentProgress);// 根据不同的朝向去画字体if (mDirection == DIRECTION_LEFT) {drawOriginDirectionLeft(canvas, middle);drawChangeDirectionLeft(canvas, middle);}if (mDirection == DIRECTION_RIGHT) {drawOriginDirectionRight(canvas, middle);drawChangeDirectionRight(canvas, middle);}}}/*** 画朝向右边变色字体*/private void drawChangeDirectionRight(Canvas canvas, int middle) {drawText(canvas, mChangePaint, getWidth() - middle, getWidth());}/*** 画朝向左边默认色字体*/private void drawOriginDirectionRight(Canvas canvas, int middle) {drawText(canvas, mOriginPaint, 0, getWidth() - middle);}/*** 画朝向左边变色字体*/private void drawChangeDirectionLeft(Canvas canvas, int middle) {drawText(canvas, mChangePaint, 0, middle);}/*** 画朝向左边默认色字体*/private void drawOriginDirectionLeft(Canvas canvas, int middle) {drawText(canvas, mOriginPaint, middle, getWidth());}/*** 设置当前的进度** @param currentProgress 当前进度*/public void setCurrentProgress(float currentProgress) {this.mCurrentProgress = currentProgress;// 重新绘制invalidate();}/*** 设置绘制方向,从右到左或者从左到右** @param direction 绘制方向*/public void setDirection(Direction direction) {this.mDirection = direction;}复制代码

接下来我们写一个主Activity做一下测试:

public class MainActivity extends AppCompatActivity {private ColorTrackTextView mCttv;private String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mCttv = (ColorTrackTextView) findViewById(R.id.tv);}// onClick事件写在了不居中 --> android:onClick="left"public void left(View view) {// 设置朝向mCttv.setDirection(ColorTrackTextView.Direction.DIRECTION_LEFT);// 用属性动画来控制,当然也可以用线程去控制ObjectAnimator animator = ObjectAnimator.ofFloat(mCttv, "progress", 0, 1);animator.setDuration(2000).start();// 添加动画的监听,不断的改变当前的进度animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float progress = (float) animation.getAnimatedValue();Log.e(TAG, "progress --> " + progress);mCttv.setCurrentProgress(progress);}});}// 这与上面类似,只是朝向不一样public void right(View view) {mCttv.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);ObjectAnimator animator = ObjectAnimator.ofFloat(mCttv, "progress", 0, 1);animator.setDuration(2000).start();animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float progress = (float) animation.getAnimatedValue();Log.e(TAG, "progress --> " + progress);mCttv.setCurrentProgress(progress);}});}}复制代码

终极效果:

2.5 结合ViewPager:

public class MainActivity extends AppCompatActivity {private String[] items = {"直播", "推荐", "视频", "图片", "段子", "精华"};private LinearLayout mIndicatorContainer;private List<ColorTrackTextView> mIndicators;private ViewPager mViewPager;private String TAG = "ViewPagerActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_view_pager);mIndicators = new ArrayList<>();mIndicatorContainer = (LinearLayout) findViewById(R.id.indicator_view);mViewPager = (ViewPager) findViewById(R.id.view_pager);initIndicator();initViewPager();}/*** 初始化ViewPager*/private void initViewPager() {mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {@Overridepublic Fragment getItem(int position) {return ItemFragment.newInstance(items[position]);}@Overridepublic int getCount() {return items.length;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {}});/*** 添加一个切换的监听那个setOnPageChangeListener过时了* 这个看源码去吧*/mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {Log.e(TAG, "position --> " + position + " positionOffset --> " + positionOffset);if (positionOffset > 0) {// 获取左边ColorTrackTextView left = mIndicators.get(position);// 设置朝向left.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);// 设置进度 positionOffset 是从 0 一直变化到 1 不信可以看打印left.setCurrentProgress(1-positionOffset);// 获取右边ColorTrackTextView right = mIndicators.get(position + 1);right.setDirection(ColorTrackTextView.Direction.DIRECTION_LEFT);right.setCurrentProgress(positionOffset);}}});// 默认一进入就选中第一个ColorTrackTextView left = mIndicators.get(0);left.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);left.setCurrentProgress(1);}/*** 初始化可变色的指示器*/private void initIndicator() {for (int i = 0; i < items.length; i++) {// 动态添加颜色跟踪的TextViewLinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);params.weight = 1;ColorTrackTextView colorTrackTextView = new ColorTrackTextView(this);// 设置两种颜色colorTrackTextView.setOriginColor(Color.BLACK);colorTrackTextView.setChangeColor(Color.RED);colorTrackTextView.setText(items[i]);colorTrackTextView.setLayoutParams(params);// 把新的加入LinearLayout容器mIndicatorContainer.addView(colorTrackTextView);// 加入集合mIndicators.add(colorTrackTextView);}}}复制代码

到目前为止应该还是挺简单的,就是变个色而已,有一个棘手的问题就是目前用的指示器是用的LinearLayout。我们可以去网上找一个ViewPagerIndicator的源码测试一下,但是我觉得不是特别好用配置很麻烦,所以决定采用Adapter适配器模式自己造一个轮子。其实自己早期写过一篇,下载的人还有蛮多,可是代码有问题,所以还是录一期视频吧,有问题大家可以自己改一下。

附视频地址:/s/1jI9PgUE

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。