打造炫酷通用的ViewPager指示器玩转字体变色.docx
《打造炫酷通用的ViewPager指示器玩转字体变色.docx》由会员分享,可在线阅读,更多相关《打造炫酷通用的ViewPager指示器玩转字体变色.docx(16页珍藏版)》请在冰豆网上搜索。
打造炫酷通用的ViewPager指示器玩转字体变色
打造炫酷通用的ViewPager指示器-玩转字体变色
1.概述
最近一直都在仿着其他项目的效果在做,仿内涵段子,二手车之家等等。
会不会有一天被抓还真是有点心虚,我这分明是给这些APP打广告。
等这些效果基本讲完就开始设计模式和系统框架一整套的视频也就会出来了,等总的访问量达到100万之后就会利用空余的时间去录制Java基础和Android基础,请各位多多start和suggest。
我们来看一下效果吧:
2.2实现思路:
我们看到这效果之后,就会尼玛网上有没有?
不要害怕不要担心其实分析了之后自己写也很简单的:
2.2.1我们肯定要自定义View但是继承自谁呢?
VieworTextView其实这里最好继承自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(Stringtext,floatx,floaty,Paintpaint)这些参数不了解的你得自己去google看一下了,温馨提示参数y是文字的基线,给一张图片看看吧:
/**
*CreatedbyDarrenon2016/12/5.
*Email:
240336124@
*Description:
文字颜色跟踪的TextView
*/
publicclassColorTrackTextViewextendsTextView{
//默认的字体颜色的画笔
privatePaintmOriginPaint;
//改变的字体颜色的画笔
privatePaintmChangePaint;
//当前的进度
privatefloatmCurrentProgress=0.6f;
privateStringTAG="CTTV";
//当前文本
privateStringmText;
publicColorTrackTextView(Contextcontext){
this(context,null);
}
publicColorTrackTextView(Contextcontext,AttributeSetattrs){
this(context,attrs,0);
}
publicColorTrackTextView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
initPaint();
}
/**
*初始化画笔
*/
privatevoidinitPaint(){
mOriginPaint=getPaintByColor(Color.BLACK);
mChangePaint=getPaintByColor(Color.RED);
}
/**
*获取画笔根据不同的颜色
*/
privatePaintgetPaintByColor(intcolor){
Paintpaint=newPaint();
//抗锯齿
paint.setAntiAlias(true);
//仿抖动
paint.setDither(true);
paint.setColor(color);
//字体的大小设置为TextView的文字大小
paint.setTextSize(getTextSize());
returnpaint;
}
/**
*这里肯定是自己去画不能用super
*/
@Override
protectedvoidonDraw(Canvascanvas){
//获取当前文本
mText=getText().toString();
//获取控件宽度
intwidth=getWidth();
if(!
TextUtils.isEmpty(mText)){
//根据当前进度计算中间位置
intmiddle=(int)(width*mCurrentProgress);
drawOrigin(canvas,middle);
drawChange(canvas,middle);
}
}
/**
*画变色的字体部分
*/
privatevoiddrawChange(Canvascanvas,intmiddle){
drawText(canvas,mChangePaint,0,middle);
}
/**
*画不变色的字体部分
*/
privatevoiddrawOrigin(Canvascanvas,intmiddle){
drawText(canvas,mOriginPaint,middle,getWidth());
}
/**
*绘制文本根据指定的位置
*
*@paramcanvascanvas画布
*@parampaint画笔
*@paramstartX开始的位置
*@paramendX结束的位置
*/
privatevoiddrawText(Canvascanvas,Paintpaint,intstartX,intendX){
//保存画笔状态
canvas.save();
//截取绘制的内容,待会就只会绘制clipRect设置的参数部分
canvas.clipRect(startX,0,endX,getHeight());
//获取文字的范围
Rectbounds=newRect();
mOriginPaint.getTextBounds(mText,0,mText.length(),bounds);
//获取文字的Metrics用来计算基线
Paint.FontMetricsIntfontMetrics=mOriginPaint.getFontMetricsInt();
//获取文字的宽高
intfontTotalHeight=fontMetrics.bottom-fontMetrics.top;
//计算基线到中心点的位置
intoffY=fontTotalHeight/2-fontMetrics.bottom;
//计算基线位置
intbaseline=(getMeasuredHeight()+fontTotalHeight)/2-offY;
canvas.drawText(mText,getMeasuredWidth()/2-bounds.width()/2,baseline,paint);
//释放画笔状态
canvas.restore();
}
}
看上面的代码其实还是挺简单的,我截取了一张效果图
2.4实现左右不同方向不断变色:
当一个TextView有了两种文字颜色之后,我们接下来就不断的控制当前的进度mCurrentProgress变量不断的绘制然后给两个朝向从左到右,从右到左,还把写死的两个颜色值变成自定义的属性,自定义属性应该不用说了吧?
如果实在不行等周末看视频吧,这里就不做过多的讲解。
我这里只贴出修改部分代码,如果觉得有点扯那就下载完整代码吧:
//当前朝向
privateDirectionmDirection=DIRECTION_LEFT;
//绘制的朝向枚举
publicenumDirection{
DIRECTION_LEFT,DIRECTION_RIGHT
}
@Override
protectedvoidonDraw(Canvascanvas){
//获取当前文本
mText=getText().toString();
//获取控件宽度
intwidth=getWidth();
if(!
TextUtils.isEmpty(mText)){
//根据当前进度计算中间位置
intmiddle=(int)(width*mCurrentProgress);
//根据不同的朝向去画字体
if(mDirection==DIRECTION_LEFT){
drawOriginDirectionLeft(canvas,middle);
drawChangeDirectionLeft(canvas,middle);
}
if(mDirection==DIRECTION_RIGHT){
drawOriginDirectionRight(canvas,middle);
drawChangeDirectionRight(canvas,middle);
}
}
}
/**
*画朝向右边变色字体
*/
privatevoiddrawChangeDirectionRight(Canvascanvas,intmiddle){
drawText(canvas,mChangePaint,getWidth()-middle,getWidth());
}
/**
*画朝向左边默认色字体
*/
privatevoiddrawOriginDirectionRight(Canvascanvas,intmiddle){
drawText(canvas,mOriginPaint,0,getWidth()-middle);
}
/**
*画朝向左边变色字体
*/
privatevoiddrawChangeDirectionLeft(Canvascanvas,intmiddle){
drawText(canvas,mChangePaint,0,middle);
}
/**
*画朝向左边默认色字体
*/
privatevoiddrawOriginDirectionLeft(Canvascanvas,intmiddle){
drawText(canvas,mOriginPaint,middle,getWidth());
}
/**
*设置当前的进度
*
*@paramcurrentProgress当前进度
*/
publicvoidsetCurrentProgress(floatcurrentProgress){
this.mCurrentProgress=currentProgress;
//重新绘制
invalidate();
}
/**
*设置绘制方向,从右到左或者从左到右
*
*@paramdirection绘制方向
*/
publicvoidsetDirection(Directiondirection){
this.mDirection=direction;
}
接下来我们写一个主Activity做一下测试:
publicclassMainActivityextendsAppCompatActivity{
privateColorTrackTextViewmCttv;
privateStringTAG="MainActivity";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCttv=(ColorTrackTextView)findViewById(R.id.tv);
}
//onClick事件写在了不居中-->android:
onClick="left"
publicvoidleft(Viewview){
//设置朝向
mCttv.setDirection(ColorTrackTextView.Direction.DIRECTION_LEFT);
//用属性动画来控制,当然也可以用线程去控制
ObjectAnimatoranimator=ObjectAnimator.ofFloat(mCttv,"progress",0,1);
animator.setDuration(2000)
.start();
//添加动画的监听,不断的改变当前的进度
animator.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation){
floatprogress=(float)animation.getAnimatedValue();
Log.e(TAG,"progress-->"+progress);
mCttv.setCurrentProgress(progress);
}
});
}
//这与上面类似,只是朝向不一样
publicvoidright(Viewview){
mCttv.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);
ObjectAnimatoranimator=ObjectAnimator.ofFloat(mCttv,"progress",0,1);
animator.setDuration(2000)
.start();
animator.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation){
floatprogress=(float)animation.getAnimatedValue();
Log.e(TAG,"progress-->"+progress);
mCttv.setCurrentProgress(progress);
}
});
}
}
2.5结合ViewPager:
publicclassMainActivityextendsAppCompatActivity{
privateString[]items={"直播","推荐","视频","图片","段子","精华"};
privateLinearLayoutmIndicatorContainer;
privateListmIndicators;
privateViewPagermViewPager;
privateStringTAG="ViewPagerActivity";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
mIndicators=newAList<>();
mIndicatorContainer=(LinearLayout)findViewById(R.id.indicator_view);
mViewPager=(ViewPager)findViewById(R.id.view_pager);
initIndicator();
initViewPager();
}
/**
*初始化ViewPager
*/
privatevoidinitViewPager(){
mViewPager.setAdapter(newFragmentPagerAdapter(getSupportFragmentManager()){
@Override
publicFragmentgetItem(intposition){
returnItemFragment.newInstance(items[position]);
}
@Override
publicintgetCount(){
returnitems.length;
}
@Override
publicvoiddestroyItem(ViewGroupcontainer,intposition,Objectobject){
}
});
/**
*添加一个切换的监听那个setOnPageChangeListener过时了
*这个看源码去吧
*/
mViewPager.addOnPageChangeListener(newViewPager.SimpleOnPageChangeListener(){
@Override
publicvoidonPageScrolled(intposition,floatpositionOffset,
intpositionOffsetPixels){
Log.e(TAG,"position-->"+position+"positionOffset-->"+positionOffset);
if(positionOffset>0){
//获取左边
ColorTrackTextViewleft=mIndicators.get(position);
//设置朝向
left.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);
//设置进度positionOffset是从0一直变化到1不信可以看打印
left.setCurrentProgress(1-positionOffset);
//获取右边
ColorTrackTextViewright=mIndicators.get(position+1);
right.setDirection(ColorTrackTextView.Direction.DIRECTION_LEFT);
right.setCurrentProgress(positionOffset);
}
}
});
//默认一进入就选中第一个
ColorTrackTextViewleft=mIndicators.get(0);
left.setDirection(ColorTrackTextView.Direction.DIRECTION_RIGHT);
left.setCurrentProgress
(1);
}
/**
*初始化可变色的指示器
*/
privatevoidinitIndicator(){
for(inti=0;i//动态添加颜色跟踪的TextView
LinearLayout.LayoutParamsparams=newLinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
params.weight=1;
ColorTrackTextViewcolorTrackTextView=newColorTrackTextView(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适配器模式自己造一个轮子吧。