Android自定义View实现点赞控件
本文实例为大家分享了Android点赞控件的具体代码,供大家参考,具体内容如下
预览效果
目录
图片类:LikeImageView
文字类:LikeCharTextView
整合类:LikeView.java
自定义属性:attrs.xml
代码
LikeCharTextView
publicclassLikeCharTextViewextendsView{
publicstaticfinalintDEFAULT_TEXTCOLOR=Color.BLACK;
publicstaticfinalintDEFAULT_TEXTSIZE=36;
privateTextPaintnewTextPaint,oldTextPaint;
privateAnimatorSetaddAnimator;
privateAnimatorSetminusAnimator;
privateintmeasureWidth;
privateintmeasureHeight;
privateinttextColor=DEFAULT_TEXTCOLOR;
privateinttextSize=DEFAULT_TEXTSIZE;
privateintnum;
privateintoldNum;
privateintnewNum;
privateintanimatorOldY;
privatefloatanimatorOldAlpha=1;
privateintanimatorNewY;
privatefloatanimatorNewAlpha=0;
privateintbaseline;
publicLikeCharTextView(Contextcontext){
super(context);
init();
}
publicLikeCharTextView(Contextcontext,@NullableAttributeSetattrs){
super(context,attrs);
initAttr(context,attrs);
init();
}
publicLikeCharTextView(Contextcontext,@NullableAttributeSetattrs,
intdefStyleAttr){
super(context,attrs,defStyleAttr);
initAttr(context,attrs);
init();
}
/**
*初始化属性
*
*@paramcontext
*@paramattrs
*/
privatevoidinitAttr(Contextcontext,@NullableAttributeSetattrs){
TypedArraytypedArray=context.obtainStyledAttributes(attrs,
R.styleable.LikeCharTextView);
textColor=typedArray.getColor(R.styleable.LikeCharTextView_textColor,
DEFAULT_TEXTCOLOR);
textSize=typedArray.getDimensionPixelSize(R.styleable.LikeCharTextView_textSize,
DEFAULT_TEXTSIZE);
num=typedArray.getInt(R.styleable.LikeCharTextView_number,0);
if(0>num||num>10){
thrownewIllegalArgumentException("Numberisonly0-9");
}
oldNum=num;
typedArray.recycle();
}
/**
*初始化
*/
privatevoidinit(){
initPaints();
initParams();
}
/**
*初始化画笔
*/
privatevoidinitPaints(){
newTextPaint=newTextPaint(Paint.ANTI_ALIAS_FLAG);
newTextPaint.setStyle(Paint.Style.FILL);
newTextPaint.setTextSize(textSize);
newTextPaint.setColor(textColor);
newTextPaint.setTextAlign(Paint.Align.CENTER);
oldTextPaint=newTextPaint(Paint.ANTI_ALIAS_FLAG);
oldTextPaint.set(newTextPaint);
}
/**
*初始化参数
*/
privatevoidinitParams(){
Paint.FontMetricsfontMetrics=newTextPaint.getFontMetrics();
measureWidth=(int)newTextPaint.measureText(String.valueOf(num));
measureHeight=(int)(fontMetrics.bottom-fontMetrics.top);
floatdistance=(fontMetrics.bottom-fontMetrics.top)/2-fontMetrics.bottom;
baseline=(int)(measureHeight*1.0f/2+distance);
animatorOldY=baseline;
}
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
intwidthMode=MeasureSpec.getMode(widthMeasureSpec);
intwidthSize=MeasureSpec.getSize(widthMeasureSpec);
switch(widthMode){
caseMeasureSpec.UNSPECIFIED:
break;
caseMeasureSpec.AT_MOST:
widthSize=measureWidth;
break;
caseMeasureSpec.EXACTLY:
break;
}
intheightMode=MeasureSpec.getMode(widthMeasureSpec);
intheightSize=MeasureSpec.getSize(widthMeasureSpec);
switch(heightMode){
caseMeasureSpec.UNSPECIFIED:
break;
caseMeasureSpec.AT_MOST:
heightSize=measureHeight;
break;
caseMeasureSpec.EXACTLY:
break;
}
setMeasuredDimension(widthSize,heightSize);
}
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
intwidth=getWidth();
intheight=getHeight();
oldTextPaint.setAlpha((int)(255*animatorOldAlpha));
canvas.drawText(String.valueOf(oldNum),width/2,animatorOldY,oldTextPaint);
newTextPaint.setAlpha((int)(255*animatorNewAlpha));
canvas.drawText(String.valueOf(newNum),width/2,animatorNewY,newTextPaint);
}
publicvoidsetTextColor(inttextColor){
this.textColor=textColor;
init();
invalidate();
}
publicvoidsetTextSize(inttextSize){
this.textSize=textSize;
init();
invalidate();
}
publicvoidsetAnimatorOldY(intanimatorOldY){
this.animatorOldY=animatorOldY;
invalidate();
}
publicvoidsetAnimatorOldAlpha(floatanimatorOldAlpha){
this.animatorOldAlpha=animatorOldAlpha;
invalidate();
}
publicvoidsetAnimatorNewY(intanimatorNewY){
this.animatorNewY=animatorNewY;
invalidate();
}
publicvoidsetAnimatorNewAlpha(floatanimatorNewAlpha){
this.animatorNewAlpha=animatorNewAlpha;
invalidate();
}
publicvoidsetNum(intnum){
this.num=num;
if(0>num||num>10){
thrownewIllegalArgumentException("Numberisonly0-9");
}
oldNum=num;
invalidate();
}
publicvoidadd(){
Logger.e("执行加动画.基线:"+baseline);
ObjectAnimatoroldYAnimator=ObjectAnimator.ofInt(this,"animatorOldY",baseline,0);
ObjectAnimatoroldAlphaAnimator=ObjectAnimator.ofFloat(this,"animatorOldAlpha",1,0);
ObjectAnimatornewYAnimator=ObjectAnimator.ofInt(this,"animatorNewY",baseline*2,
baseline);
ObjectAnimatornewAlphaAnimator=ObjectAnimator.ofFloat(this,"animatorNewAlpha",0,1);
addAnimator=newAnimatorSet();
addAnimator.playTogether(oldYAnimator,oldAlphaAnimator,newYAnimator,newAlphaAnimator);
addAnimator.setInterpolator(newLinearInterpolator());
addAnimator.setDuration(300);
addAnimator.start();
}
publicvoidminus(){
Logger.e("执行减动画.基线:"+baseline);
ObjectAnimatoroldYAnimator=ObjectAnimator.ofInt(this,"animatorOldY",baseline,
baseline*2);
ObjectAnimatoroldAlphaAnimator=ObjectAnimator.ofFloat(this,"animatorOldAlpha",1,0);
ObjectAnimatornewYAnimator=ObjectAnimator.ofInt(this,"animatorNewY",0,baseline);
ObjectAnimatornewAlphaAnimator=ObjectAnimator.ofFloat(this,"animatorNewAlpha",0,1);
minusAnimator=newAnimatorSet();
minusAnimator.playTogether(oldYAnimator,oldAlphaAnimator,newYAnimator,newAlphaAnimator);
minusAnimator.setInterpolator(newLinearInterpolator());
minusAnimator.setDuration(300);
minusAnimator.start();
}
publicvoidchange(booleanisAdd){
Logger.e("charTextVie.点击事件:"+isAdd);
if(isAdd){
if(null!=addAnimator&&addAnimator.isStarted()){
Logger.e("charTextVie.加动画已执行.取消");
addAnimator.cancel();
}
if(null!=minusAnimator&&minusAnimator.isStarted()){
Logger.e("charTextVie.减动画已执行.取消");
minusAnimator.cancel();
}
sumNum(false);
minus();
}else{
if(null!=minusAnimator&&minusAnimator.isStarted()){
Logger.e("charTextVie.减动画已执行.取消");
minusAnimator.cancel();
}
if(null!=addAnimator&&addAnimator.isStarted()){
Logger.e("charTextVie.加动画已执行.取消");
addAnimator.cancel();
}
sumNum(true);
add();
}
}
/**
*重新计算绘画的值
*
*@paramisAdd
*/
privatevoidsumNum(booleanisAdd){
Logger.e("计算值开始");
oldNum=num;
newNum=num+(isAdd?1:-1);
if(newNum<0){
newNum=9;
}elseif(newNum>9){
newNum=0;
}
num=newNum;
Logger.e("计算值结束:"+num);
}
}
LikeImageView
publicclassLikeImageViewextendsView{
privatePaintimagePaint,shiningPaint;
privateintshiningMoveX;
privateintshiningMoveY;
privateintmeasureWidth;
privateintmeasureHeight;
privateBitmapselectedBtimap;
privateBitmapselectedShiningBtimap;
privateBitmapunSelectedBtimap;
privatebooleanisAdd=false;
privatefloatshiningAlpha=isAdd?1f:0f;
publicLikeImageView(Contextcontext){
super(context);
init();
}
publicLikeImageView(Contextcontext,@NullableAttributeSetattrs){
super(context,attrs);
init();
}
publicLikeImageView(Contextcontext,@NullableAttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
init();
}
privatevoidinit(){
imagePaint=newPaint(Paint.ANTI_ALIAS_FLAG);
shiningPaint=newPaint(Paint.ANTI_ALIAS_FLAG);
selectedBtimap=BitmapFactory.decodeResource(getResources(),R.mipmap.ic_like_selected);
selectedShiningBtimap=BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_like_selected_shining);
unSelectedBtimap=BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_like_unselected);
}
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
intwidthMode=MeasureSpec.getMode(widthMeasureSpec);
intwidthSize=MeasureSpec.getSize(widthMeasureSpec);
switch(widthMode){
caseMeasureSpec.UNSPECIFIED:
break;
caseMeasureSpec.AT_MOST:
widthSize=Math.max(selectedBtimap.getWidth(),unSelectedBtimap.getWidth());
shiningMoveX=(int)(widthSize*1.0f-selectedShiningBtimap.getWidth())-2;
break;
caseMeasureSpec.EXACTLY:
break;
}
intheightMode=MeasureSpec.getMode(widthMeasureSpec);
intheightSize=MeasureSpec.getSize(widthMeasureSpec);
switch(heightMode){
caseMeasureSpec.UNSPECIFIED:
break;
caseMeasureSpec.AT_MOST:
heightSize=Math.max(selectedBtimap.getHeight(),unSelectedBtimap.getHeight());
shiningMoveY=(int)(selectedShiningBtimap.getHeight()*1.0f/3);
heightSize+=shiningMoveY;
break;
caseMeasureSpec.EXACTLY:
break;
}
setMeasuredDimension(widthSize,heightSize);
}
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
intwidth=getWidth();
intheight=getHeight();
Rectsrc=newRect(0,0,width,height);
RectselectDst=newRect(0,shiningMoveY,selectedBtimap.getWidth(),height);
if(isAdd){
//画红赞
canvas.drawBitmap(selectedBtimap,src,selectDst,imagePaint);
//画阴影
shiningPaint.setAlpha((int)(255*shiningAlpha));
RectshiningDst=newRect(shiningMoveX,0,
shiningMoveX+selectedShiningBtimap.getWidth(),selectedShiningBtimap.getHeight());
canvas.drawBitmap(selectedShiningBtimap,src,shiningDst,shiningPaint);
}else{
//画灰赞
canvas.drawBitmap(unSelectedBtimap,src,selectDst,imagePaint);
}
}
publicvoidsetShiningAlpha(floatshiningAlpha){
this.shiningAlpha=shiningAlpha;
invalidate();
}
publicvoidsetAdd(booleanadd){
isAdd=add;
shiningAlpha=1.0f;
invalidate();
}
publicvoidchangeLike(booleanisAdd){
this.isAdd=!isAdd;
invalidate();
anim();
}
privatevoidanim(){
ObjectAnimatorscaleXAnim=ObjectAnimator.ofFloat(this,"scaleX",0.7f,1f);
scaleXAnim.setDuration(500);
ObjectAnimatorscaleYAnim=ObjectAnimator.ofFloat(this,"scaleY",0.7f,1f);
scaleYAnim.setDuration(500);
ObjectAnimatoralphaAnim=ObjectAnimator.ofFloat(this,"shiningAlpha",0f,1f);
alphaAnim.setDuration(500);
AnimatorSetanimatorSet=newAnimatorSet();
animatorSet.playTogether(scaleXAnim,scaleYAnim,alphaAnim);
animatorSet.setInterpolator(newBounceInterpolator());
animatorSet.start();
}
}
LikeView
publicclassLikeViewextendsLinearLayout{
privatefinalintIMAGEPADDING=4;
privatebooleanisAdd=false;
privateintnum;
privateinttextSize;
privateinttextColor;
privateintimagePadding;
privateListcharTvs=newArrayList<>();
privateLikeImageViewlikeImageView;
publicLikeView(Contextcontext){
super(context);
init();
}
publicLikeView(Contextcontext,@NullableAttributeSetattrs){
super(context,attrs);
initAttr(context,attrs);
init();
}
publicLikeView(Contextcontext,@NullableAttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
initAttr(context,attrs);
init();
}
privatevoidinitAttr(Contextcontext,AttributeSetattrs){
TypedArraytypedArray=context.obtainStyledAttributes(attrs,R.styleable.LikeView);
textColor=typedArray.getColor(R.styleable.LikeView_textColor,
LikeCharTextView.DEFAULT_TEXTCOLOR);
textSize=typedArray.getDimensionPixelSize(R.styleable.LikeView_textSize,
LikeCharTextView.DEFAULT_TEXTSIZE);
num=typedArray.getInt(R.styleable.LikeView_number,0);
imagePadding=typedArray.getDimensionPixelSize(R.styleable.LikeView_imagePadding,IMAGEPADDING);
typedArray.recycle();
}
/**
*初始化
*/
privatevoidinit(){
initView();
}
protectedvoidinitView(){
removeAllViews();
likeImageView=newLikeImageView(getContext());
likeImageView.setAdd(isAdd);
LinearLayout.LayoutParamslayoutParams=newLinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.rightMargin=imagePadding;
likeImageView.setLayoutParams(layoutParams);
addView(likeImageView);
charTvs.clear();
Stringstr_num=String.valueOf(num);
for(inti=0;iMOHUFANWEI||Math.abs(lastY-y)>MOHUFANWEI){
click=false;
}
break;
}
lastX=x;
lastY=y;
returntrue;
}
privatevoidonClick(){
Logger.e("点击事件"+isAdd);
Stringstr_num=String.valueOf(num);
Logger.e("点击事件,str_num:"+str_num);
booleannextAnim=false;
if(isAdd){
likeImageView.changeLike(true);
for(inti=(str_num.length()-1);i>=0;i--){
intchr_num=Integer.valueOf(str_num.substring(i,i+1));
Logger.e("点击事件,chr_num:%d,charTvs.size:%d,i:%d",chr_num,charTvs.size(),i);
Logger.e("是否执行动画:"+(charTvs.size()>i));
if(charTvs.size()>i){
if(i==(str_num.length()-1)||nextAnim){
Logger.e("点击事件,执行个位动画||%b执行执行上%d位动画",nextAnim,i);
charTvs.get(i).change(true);
chr_num--;
Logger.e("chr_num:%d,是否执行上一位动画:",chr_num,(chr_num<0));
if(chr_num<0){
nextAnim=true;
}else{
nextAnim=false;
}
Logger.e("nextAnim:"+nextAnim);
}
}
}
num--;
isAdd=!isAdd;
}else{
likeImageView.changeLike(false);
for(inti=(str_num.length()-1);i>=0;i--){
intchr_num=Integer.valueOf(str_num.substring(i,i+1));
Logger.e("点击事件,chr_num:%d,charTvs.size:%d,i:%d",chr_num,charTvs.size(),i);
Logger.e("是否执行动画:"+(charTvs.size()>i));
if(charTvs.size()>i){
if(i==(str_num.length()-1)||nextAnim){
Logger.e("点击事件,执行个位动画||%b执行执行上%d位动画",nextAnim,i);
charTvs.get(i).change(false);
chr_num++;
Logger.e("chr_num:%d,是否执行上一位动画:",chr_num,(chr_num>9));
if(chr_num>9){
nextAnim=true;
}else{
nextAnim=false;
}
Logger.e("nextAnim:"+nextAnim);
}
}
}
num++;
isAdd=!isAdd;
}
}
}
attrs.xml
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。