android 点赞放大,Android自定义View实现点赞控件

本文实例为大家分享了Android点赞控件的具体代码,供大家参考,具体内容如下

预览效果

878e89a5915a92c4df591d2936429826.gif

目录

图片类: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), width / 2, 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", 0, 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, "animatorOldY", baseline,

baseline * 2);

ObjectAnimator oldAlphaAnimator = ObjectAnimator.ofFloat(this, "animatorOldAlpha", 1, 0);

ObjectAnimator newYAnimator = ObjectAnimator.ofInt(this, "animatorNewY", 0, baseline);

ObjectAnimator newAlphaAnimator = ObjectAnimator.ofFloat(this, "animatorNewAlpha", 0, 1);

minusAnimator = new AnimatorSet();

minusAnimator.playTogether(oldYAnimator, oldAlphaAnimator, newYAnimator, 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, @Nullable AttributeSet attrs) {

super(context, attrs);

init();

}

public LikeImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, 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, 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 = 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, 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, 0,

shiningMoveX + selectedShiningBtimap.getWidth(), selectedShiningBtimap.getHeight());

canvas.drawBitmap(selectedShiningBtimap, src, shiningDst, shiningPaint);

} else {

//画灰赞

canvas.drawBitmap(unSelectedBtimap, src, selectDst, 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", 0.7f, 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 charTvs = new ArrayList<>();

private LikeImageView likeImageView;

public LikeView(Context context) {

super(context);

init();

}

public LikeView(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

initAttr(context, attrs);

init();

}

public LikeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initAttr(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, int heightMeasureSpec) {

super.onMeasure(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, (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 + 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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值