本文实例为大家分享了Android点赞控件的具体代码,供大家参考,具体内容如下
预览效果
目录
图片类:LikeImageView
文字类:LikeCharTextView
整合类:LikeView.java
自定义属性:attrs.xml
LikeCharTextView
public class LikeCharTextView extends View { public static final int DEFAULT_TEXTCOLOR = Color.BLACK; public static final int DEFAULT_TEXTSIZE = 36; private TextPaint newTextPaint,oldTextPaint; private AnimatorSet addAnimator; private AnimatorSet minusAnimator; private int measureWidth; private int measureHeight; private int textColor = DEFAULT_TEXTCOLOR; private int textSize = DEFAULT_TEXTSIZE; private int num; private int oldNum; private int newNum; private int animatorOldY; private float animatorOldAlpha = 1; private int animatorNewY; private float animatorNewAlpha = 0; private int baseline; public LikeCharTextView(Context context) { super(context); init(); } public LikeCharTextView(Context context,@Nullable AttributeSet attrs) { super(context,attrs); initAttr(context,attrs); init(); } public LikeCharTextView(Context context,@Nullable AttributeSet attrs,int defStyleAttr) { super(context,attrs,defStyleAttr); initAttr(context,attrs); init(); } /** * 初始化属性 * * @param context * @param attrs */ private void initAttr(Context context,@Nullable AttributeSet attrs) { TypedArray typedArray = 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) { throw new IllegalArgumentException("Number is only 0-9"); } oldNum = num; typedArray.recycle(); } /** * 初始化 */ private void init() { initPaints(); initParams(); } /** * 初始化画笔 */ private void initPaints() { newTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); newTextPaint.setStyle(Paint.Style.FILL); newTextPaint.setTextSize(textSize); newTextPaint.setColor(textColor); newTextPaint.setTextAlign(Paint.Align.CENTER); oldTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); oldTextPaint.set(newTextPaint); } /** * 初始化参数 */ private void initParams() { Paint.FontMetrics fontMetrics = newTextPaint.getFontMetrics(); measureWidth = (int) newTextPaint.measureText(String.valueOf(num)); measureHeight = (int) (fontMetrics.bottom - fontMetrics.top); float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; baseline = (int) (measureHeight * 1.0f / 2 + distance); animatorOldY = baseline; } @Override protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) { super.onMeasure(widthMeasureSpec,heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); switch (widthMode) { case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: widthSize = measureWidth; break; case MeasureSpec.EXACTLY: break; } int heightMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(widthMeasureSpec); switch (heightMode) { case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: heightSize = measureHeight; break; case MeasureSpec.EXACTLY: break; } setMeasuredDimension(widthSize,heightSize); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = 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),animatorNewY,newTextPaint); } public void setTextColor(int textColor) { this.textColor = textColor; init(); invalidate(); } public void setTextSize(int textSize) { this.textSize = textSize; init(); invalidate(); } public void setAnimatorOldY(int animatorOldY) { this.animatorOldY = animatorOldY; invalidate(); } public void setAnimatorOldAlpha(float animatorOldAlpha) { this.animatorOldAlpha = animatorOldAlpha; invalidate(); } public void setAnimatorNewY(int animatorNewY) { this.animatorNewY = animatorNewY; invalidate(); } public void setAnimatorNewAlpha(float animatorNewAlpha) { this.animatorNewAlpha = animatorNewAlpha; invalidate(); } public void setNum(int num) { this.num = num; if (0 > num || num > 10) { throw new IllegalArgumentException("Number is only 0-9"); } oldNum = num; invalidate(); } public void add() { Logger.e("执行加动画.基线:" + baseline); ObjectAnimator oldYAnimator = ObjectAnimator.ofInt(this,"animatorOldY",baseline,0); ObjectAnimator oldAlphaAnimator = ObjectAnimator.ofFloat(this,"animatorOldAlpha",1,0); ObjectAnimator newYAnimator = ObjectAnimator.ofInt(this,"animatorNewY",baseline * 2,baseline); ObjectAnimator newAlphaAnimator = ObjectAnimator.ofFloat(this,"animatorNewAlpha",1); addAnimator = new AnimatorSet(); addAnimator.playTogether(oldYAnimator,oldAlphaAnimator,newYAnimator,newAlphaAnimator); addAnimator.setInterpolator(new LinearInterpolator()); addAnimator.setDuration(300); addAnimator.start(); } public void minus() { Logger.e("执行减动画.基线:" + baseline); ObjectAnimator oldYAnimator = ObjectAnimator.ofInt(this,baseline * 2); ObjectAnimator oldAlphaAnimator = ObjectAnimator.ofFloat(this,1); minusAnimator = new AnimatorSet(); minusAnimator.playTogether(oldYAnimator,newAlphaAnimator); minusAnimator.setInterpolator(new LinearInterpolator()); minusAnimator.setDuration(300); minusAnimator.start(); } public void change(boolean isAdd) { 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(); } } /** * 重新计算绘画的值 * * @param isAdd */ private void sumNum(boolean isAdd) { Logger.e("计算值开始"); oldNum = num; newNum = num + (isAdd ? 1 : -1); if (newNum < 0) { newNum = 9; } else if (newNum > 9) { newNum = 0; } num = newNum; Logger.e("计算值结束:" + num); } }
LikeImageView
public class LikeImageView extends View { private Paint imagePaint,shiningPaint; private int shiningMoveX; private int shiningMoveY; private int measureWidth; private int measureHeight; private Bitmap selectedBtimap; private Bitmap selectedShiningBtimap; private Bitmap unSelectedBtimap; private boolean isAdd = false; private float shiningAlpha = isAdd ? 1f : 0f; public LikeImageView(Context context) { super(context); init(); } public LikeImageView(Context context,attrs); init(); } public LikeImageView(Context context,defStyleAttr); init(); } private void init() { imagePaint = new Paint(Paint.ANTI_ALIAS_FLAG); shiningPaint = new Paint(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 protected void onMeasure(int widthMeasureSpec,heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); switch (widthMode) { case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: widthSize = Math.max(selectedBtimap.getWidth(),unSelectedBtimap.getWidth()); shiningMoveX = (int) (widthSize * 1.0f - selectedShiningBtimap.getWidth()) - 2; break; case MeasureSpec.EXACTLY: break; } int heightMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(widthMeasureSpec); switch (heightMode) { case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: heightSize = Math.max(selectedBtimap.getHeight(),unSelectedBtimap.getHeight()); shiningMoveY = (int) (selectedShiningBtimap.getHeight() * 1.0f / 3); heightSize += shiningMoveY; break; case MeasureSpec.EXACTLY: break; } setMeasuredDimension(widthSize,heightSize); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); Rect src = new Rect(0,width,height); Rect selectDst = new Rect(0,shiningMoveY,selectedBtimap.getWidth(),height); if (isAdd) { //画红赞 canvas.drawBitmap(selectedBtimap,src,selectDst,imagePaint); //画阴影 shiningPaint.setAlpha((int) (255 * shiningAlpha)); Rect shiningDst = new Rect(shiningMoveX,shiningMoveX + selectedShiningBtimap.getWidth(),selectedShiningBtimap.getHeight()); canvas.drawBitmap(selectedShiningBtimap,shiningDst,shiningPaint); } else { //画灰赞 canvas.drawBitmap(unSelectedBtimap,imagePaint); } } public void setShiningAlpha(float shiningAlpha) { this.shiningAlpha = shiningAlpha; invalidate(); } public void setAdd(boolean add) { isAdd = add; shiningAlpha = 1.0f; invalidate(); } public void changeLike(boolean isAdd) { this.isAdd = !isAdd; invalidate(); anim(); } private void anim() { ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(this,"scaleX",0.7f,1f); scaleXAnim.setDuration(500); ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(this,"scaleY",1f); scaleYAnim.setDuration(500); ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this,"shiningAlpha",0f,1f); alphaAnim.setDuration(500); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(scaleXAnim,scaleYAnim,alphaAnim); animatorSet.setInterpolator(new BounceInterpolator()); animatorSet.start(); } }
LikeView
public class LikeView extends LinearLayout { private final int IMAGEPADDING = 4; private boolean isAdd = false; private int num; private int textSize; private int textColor; private int imagePadding; private List<LikeCharTextView> charTvs = new ArrayList<>(); private LikeImageView likeImageView; public LikeView(Context context) { super(context); init(); } public LikeView(Context context,attrs); init(); } public LikeView(Context context,attrs); init(); } private void initAttr(Context context,AttributeSet attrs) { TypedArray typedArray = 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(); } /** * 初始化 */ private void init() { initView(); } protected void initView() { removeAllViews(); likeImageView = new LikeImageView(getContext()); likeImageView.setAdd(isAdd); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.rightMargin = imagePadding; likeImageView.setLayoutParams(layoutParams); addView(likeImageView); charTvs.clear(); String str_num = String.valueOf(num); for (int i = 0; i < str_num.length(); i++) { LikeCharTextView textView = new LikeCharTextView(getContext()); int show_num = Integer.valueOf(str_num.substring(i,i + 1)); Log.e("zanview","show_num:" + show_num); textView.setTextSize(textSize); textView.setTextColor(textColor); textView.setNum(show_num); addView(textView); charTvs.add(textView); } } public void setNum(int num) { this.num = num; init(); invalidate(); } public void setAdd(boolean add) { isAdd = add; } @Override protected void onMeasure(int widthMeasureSpec,heightMeasureSpec); //计算出所有的childView的宽高 measureChildren(widthMeasureSpec,heightMeasureSpec); setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec)); } /** * 测量宽度 * * @param widthMeasureSpec * @return */ private int measureWidth(int widthMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); switch (widthMode) { case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: widthSize = 0; for (int i = 0; i < getChildCount(); i++) { View childView = getChildAt(i); //获取子view的宽 int cWidth = childView.getMeasuredWidth(); MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams(); widthSize += cWidth + params.leftMargin + params.rightMargin; } break; case MeasureSpec.EXACTLY: break; } return widthSize; } /** * 测量高度 * * @param widthMeasureSpec * @return */ private int measureHeight(int widthMeasureSpec) { int heightMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(widthMeasureSpec); switch (heightMode) { case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: heightSize = 0; for (int i = 0; i < getChildCount(); i++) { View childView = getChildAt(i); //获取子view的宽 int cWidth = childView.getMeasuredHeight(); MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams(); int height = cWidth + params.leftMargin + params.rightMargin; heightSize = Math.max(heightSize,height); } break; case MeasureSpec.EXACTLY: break; } return heightSize; } private boolean click = false; private final int MOHUFANWEI = 10; private float lastX = 0; private float lastY = 0; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (1 == event.getPointerCount()) { click = true; } break; case MotionEvent.ACTION_UP: if (click) { onClick(); } break; case MotionEvent.ACTION_MOVE: if (Math.abs(lastX - x) > MOHUFANWEI || Math.abs(lastY - y) > MOHUFANWEI) { click = false; } break; } lastX = x; lastY = y; return true; } private void onClick() { Logger.e("点击事件" + isAdd); String str_num = String.valueOf(num); Logger.e("点击事件,str_num:" + str_num); boolean nextAnim = false; if (isAdd) { likeImageView.changeLike(true); for (int i = (str_num.length() - 1); i >= 0; i--) { int chr_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 < 0)); if (chr_num < 0) { nextAnim = true; } else { nextAnim = false; } Logger.e("nextAnim:" + nextAnim); } } } num--; isAdd = !isAdd; } else { likeImageView.changeLike(false); for (int i = (str_num.length() - 1); i >= 0; i--) { int chr_num = Integer.valueOf(str_num.substring(i,i); charTvs.get(i).change(false); chr_num++; Logger.e("chr_num:%d,是否执行上一位动画:",(chr_num > 9)); if (chr_num > 9) { nextAnim = true; } else { nextAnim = false; } Logger.e("nextAnim:" + nextAnim); } } } num++; isAdd = !isAdd; } } }
attrs.xml
<attr name="textSize" format="dimension" /> <attr name="textColor" format="color" /> <attr name="number" format="integer" /> <attr name="imageWidth" format="dimension" /> <attr name="imageHeight" format="dimension" /> <declare-styleable name="LikeView"> <attr name="textSize" /> <attr name="textColor" /> <attr name="number" /> <attr name="imageWithd" /> <attr name="imageHeight" /> <attr name="imagePadding" format="dimension" /> </declare-styleable> <declare-styleable name="LikeCharTextView"> <attr name="textSize" /> <attr name="textColor" /> <attr name="number" /> </declare-styleable> <declare-styleable name="LikeImageView"> <attr name="imageWithd" /> <attr name="imageHeight" /> </declare-styleable>原文链接:https://www.f2er.com/android/534597.html