本文实例为大家分享了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), 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<LikeCharTextView> 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
<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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持得得之家。
本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!