TA的每日心情 | 开心 昨天 00:08 |
---|
签到天数: 362 天 [LV.8]以坛为家I
管理员
  
- 积分
- 160408
|
一个自定义收起展开动画的Button% b7 X7 f H/ s! L* e: D& }' ?
3 t8 k) {. y$ X3 H' Y1 K* l下边那个绿色的是一个可拖拽的悬浮按钮:https://www.jianshu.com/p/286acc503268
& [! v, G4 v* Y$ L }( Z+ x* o: ^3 r6 s9 v [0 I/ f
CustomAnimatorButton.java
/ K) ?$ g1 c hpackage com.xc.myexercise.widget;import android.animation.Animator;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.drawable.GradientDrawable;import android.text.TextUtils;import android.util.AttributeSet;import android.view.View;import android.view.animation.AnticipateInterpolator;import androidx.annotation.Nullable;import com.xc.myexercise.R;/** * author: roc * time: 1/13/21 12:30 PM * explain:带动画的按钮 */public class CustomAnimatorButton extends View { private Context mContext; //view的宽度 private int width; //view的高度 private int height; //圆角矩形Paint private Paint rectPaint; private GradientDrawable mDrawable; //矩形背景颜色 private int rectBackColor; //矩形的渐变颜色 private int backStartColor; private int backEndColor; //渐变颜色方向 private int colorDirection; //默认圆角半径 private final int DEFAULTANGLE = 100; //矩形圆角半径 private int circleAngle; //文字Paint private Paint textPaint; private int textColor; private int btnTextSize; private String buttonText; //图片资源 private int imageDrable; //图片与文字的间距 private int imagePadding; private Bitmap imgBitmap; private RectF rectf = new RectF(); private Rect rect2 = new Rect(); private Rect rect3 = new Rect(); private Rect textRect = new Rect(); //底部标签绘制的drawable private GradientDrawable tagDrawable; //底部标签的文字Paint private Paint tagTextPaint; //底部标签的背景颜色 private int tagBackColor; //底部标签的文字颜色 private int tagTextColor; //底部标签的文字大小 private int tagTextSize; //底部标签的背景弧度 private int tagBackAngle; //底部标签的文字 private String tagtext; //底部标签的宽度 private int tagBackWidth; //底部标签的高度 private int tagBackHeight; //进入动画 private AnimatorSet entryAnimatorSet = new AnimatorSet(); //矩形到圆形形过度的动画 private ValueAnimator animatorRectToCircle; //view右移的动画 private ObjectAnimator animatorMoveToRight; //退出动画 private AnimatorSet exitAnimatorSet = new AnimatorSet(); //圆形过度到矩形的动画 private ValueAnimator animatorCircleToRect; //view左移的动画 private ObjectAnimator animatorMoveToLeft; //动画执行时间 private int animatorDuration = 200; //移动距离 private int moveDistance = 50; //默认两圆圆心之间的距离=需要移动的距离 private int defaultTwoCircleDistance; //两圆圆心之间的距离 private int twoCircleDistance; //是否显示文字 private boolean isShowText = true; private AnimatorButtonListener animatorButtonListener; private AnimatorButtonClickListener animatorButtonClickListener; //动画是否正在执行中 private boolean isAnimatorExecution = false; //是否收起状态 private boolean isCloseState = false; public CustomAnimatorButton(Context context) { this(context, null); } public CustomAnimatorButton(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public CustomAnimatorButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; initAttrs(attrs); initPaint(); this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (animatorButtonClickListener != null) animatorButtonClickListener.onClickBtn(); } }); entryAnimatorSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { isAnimatorExecution = true; if (animatorButtonListener != null) animatorButtonListener.entryStart(); } @Override public void onAnimationEnd(Animator animation) { invalidate(); isCloseState = true; isAnimatorExecution = false; if (animatorButtonListener != null) animatorButtonListener.entryEnd(); } @Override public void onAnimationCancel(Animator animation) { isAnimatorExecution = false; } @Override public void onAnimationRepeat(Animator animation) { } }); exitAnimatorSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { isAnimatorExecution = true; if (animatorButtonListener != null) animatorButtonListener.exitStart(); } @Override public void onAnimationEnd(Animator animation) { isAnimatorExecution = false; isCloseState = false; isShowText = true; invalidate(); if (animatorButtonListener != null) animatorButtonListener.exitEnd(); } @Override public void onAnimationCancel(Animator animation) { isAnimatorExecution = false; } @Override public void onAnimationRepeat(Animator animation) { } }); } private void initAttrs(AttributeSet attrs) { TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.CustomAnimatorButton); if (typedArray == null) { return; } try { circleAngle = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_rect_angle, DEFAULTANGLE); rectBackColor = typedArray.getColor(R.styleable.CustomAnimatorButton_rect_back_color, Color.parseColor("#DDDDDD")); backStartColor = typedArray.getColor(R.styleable.CustomAnimatorButton_rect_back_start_color, -1); backEndColor = typedArray.getColor(R.styleable.CustomAnimatorButton_rect_back_end_color, -1); colorDirection = typedArray.getInteger(R.styleable.CustomAnimatorButton_color_direction, 1); textColor = typedArray.getColor(R.styleable.CustomAnimatorButton_text_color, Color.parseColor("#000000")); btnTextSize = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_btn_text_size, 20); buttonText = typedArray.getString(R.styleable.CustomAnimatorButton_btn_text); if (TextUtils.isEmpty(buttonText)) buttonText = "我要提问"; animatorDuration = typedArray.getInteger(R.styleable.CustomAnimatorButton_animator_duration, 200); moveDistance = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_move_distance, 100); imageDrable = typedArray.getResourceId(R.styleable.CustomAnimatorButton_image_drawable, R.mipmap.edit_pencil_icon); imagePadding = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_image_padding, 10); tagBackColor = typedArray.getColor(R.styleable.CustomAnimatorButton_tag_back_color, Color.parseColor("#FFDB9B")); tagTextColor = typedArray.getColor(R.styleable.CustomAnimatorButton_tag_text_color, Color.parseColor("#C68A36")); tagTextSize = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_tag_text_size, -1); tagBackAngle = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_tag_angle, DEFAULTANGLE); tagtext = typedArray.getString(R.styleable.CustomAnimatorButton_tag_text); tagBackWidth = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_tag_back_width, -1); tagBackHeight = typedArray.getDimensionPixelSize(R.styleable.CustomAnimatorButton_tag_back_height, -1); } finally { typedArray.recycle(); } } /** * 初始化化Paint */ private void initPaint() { if (backEndColor == -1 || backStartColor == -1) { rectPaint = new Paint(); rectPaint.setStrokeWidth(4); rectPaint.setStyle(Paint.Style.FILL); rectPaint.setAntiAlias(true); rectPaint.setColor(rectBackColor); } else { //初始化柱状图drawable mDrawable = new GradientDrawable(); if (colorDirection == 1) {//设置颜色渐变方向为纵向 mDrawable.setOrientation(GradientDrawable.Orientation.TOP_BOTTOM);//设置渐变方向(从上到下) } else { mDrawable.setOrientation(GradientDrawable.Orientation.LEFT_RIGHT);//设置渐变方向(从左到右) } mDrawable.setShape(GradientDrawable.RECTANGLE);//设置形状为矩形 mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); mDrawable.setCornerRadii(new float[]{circleAngle, circleAngle, circleAngle, circleAngle, circleAngle, circleAngle, circleAngle, circleAngle});//设置圆角 mDrawable.setColors(new int[]{backStartColor, backEndColor});//设置渐变颜色 } //初始化文字pain textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); textPaint.setTextSize(btnTextSize); textPaint.setColor(textColor); textPaint.setTextAlign(Paint.Align.CENTER); textPaint.setAntiAlias(true); //初始化图片bitMap imgBitmap = BitmapFactory.decodeResource(this.getResources(), imageDrable); //初始化底部标签的pain if (!TextUtils.isEmpty(tagtext)) { //初始化底部文字的paint tagTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); if (tagTextSize == -1) tagTextSize = btnTextSize / 2; tagTextPaint.setTextSize(tagTextSize); tagTextPaint.setColor(tagTextColor); tagTextPaint.setTextAlign(Paint.Align.CENTER); tagTextPaint.setAntiAlias(true); //初始化柱状图drawable tagDrawable = new GradientDrawable(); tagDrawable.setShape(GradientDrawable.RECTANGLE);//设置形状为矩形 tagDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); tagDrawable.setCornerRadii(new float[]{tagBackAngle, tagBackAngle, tagBackAngle, tagBackAngle, 0, 0, 0, 0});//设置圆角 tagDrawable.setColors(new int[]{backStartColor, backEndColor});// tagDrawable.setColor(tagBackColor);//设置底部标签的背景颜色 } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); width = w; height = h; defaultTwoCircleDistance = (w - h) / 2; initAnimation(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawOvalToCircle(canvas); if (isShowText) drawTextAndImg(canvas); else drawImg(canvas); } /** * 绘制长方形变成圆形 * * @param canvas 画布 */ private void drawOvalToCircle(Canvas canvas) { if (backStartColor == -1 || backEndColor == -1) {//如果不用颜色渐变,就绘制纯色的圆角矩形 rectf.left = twoCircleDistance; rectf.top = 0; rectf.right = width - twoCircleDistance; rectf.bottom = height; //画圆角矩形 canvas.drawRoundRect(rectf, circleAngle, circleAngle, rectPaint); } else { //绘制渐变颜色的圆角矩形 rect2.left = twoCircleDistance; rect2.top = 0; rect2.right = width - twoCircleDistance; rect2.bottom = height; mDrawable.setBounds(rect2);//设置位置大小 mDrawable.draw(canvas);//绘制到canvas上 } } /** * 绘制图片与文字 * * @param canvas 画布 */ private void drawTextAndImg(Canvas canvas) { textRect.left = 0; textRect.top = 0; textRect.right = width; textRect.bottom = height; int textWidth = (int) (textPaint.getTextSize() * buttonText.length()); int imgWidth = imgBitmap.getWidth(); int imgHeight = imgBitmap.getHeight(); int imgStartX = (width - textWidth - imgWidth - imagePadding) / 2; int imgStartY = height / 2 - imgHeight / 2; int textStartX = imgStartX + imgWidth + textWidth / 2 + imagePadding; //绘制文字 Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt(); int baseline = (textRect.bottom + textRect.top - fontMetrics.bottom - fontMetrics.top) / 2;// canvas.drawText(buttonText, textRect.centerX(), baseline, textPaint); canvas.drawText(buttonText, textStartX, baseline, textPaint); //绘制图片 canvas.drawBitmap(imgBitmap, imgStartX, imgStartY, null); drawBottomTag(canvas); } /** * 绘制底部标签 */ private void drawBottomTag(Canvas canvas) { if (TextUtils.isEmpty(tagtext)) return; if (tagBackWidth == -1) tagBackWidth = defaultTwoCircleDistance * 2 + 30; if (tagBackHeight == -1) tagBackHeight = height / 4 - 5; //绘制底部标签的背景 rect3.left = (width - tagBackWidth) / 2; rect3.top = height - tagBackHeight - 2; rect3.right = rect3.left + tagBackWidth; rect3.bottom = height - 2; tagDrawable.setBounds(rect3);//设置位置大小 tagDrawable.draw(canvas);//绘制到canvas上 //绘制文字 Paint.FontMetricsInt fontMetrics = tagTextPaint.getFontMetricsInt(); int baseline = (rect3.bottom + rect3.top - fontMetrics.bottom - fontMetrics.top) / 2; canvas.drawText(tagtext, rect3.centerX(), baseline, tagTextPaint); } /** * 绘制图片 * * @param canvas */ private void drawImg(Canvas canvas) { int imgWidth = imgBitmap.getWidth(); int imgHeight = imgBitmap.getHeight(); int imgStartX = (width - imgWidth) / 2; int imgStartY = height / 2 - imgHeight / 2; //绘制图片 canvas.drawBitmap(imgBitmap, imgStartX, imgStartY, null); } /** * 初始化所有动画 */ private void initAnimation() { setRectToCircleAnimation(); setMoveToRightAnimation(); entryAnimatorSet .play(animatorMoveToRight) .after(animatorRectToCircle); setCircleToRectAnimation(); setMoveToLeftAnimation(); exitAnimatorSet .play(animatorCircleToRect) .after(animatorMoveToLeft); } /** * 设置圆角矩形过度到圆的动画 */ private void setRectToCircleAnimation() { animatorRectToCircle = ValueAnimator.ofInt(0, defaultTwoCircleDistance); animatorRectToCircle.setDuration(animatorDuration); animatorRectToCircle.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { twoCircleDistance = (int) animation.getAnimatedValue(); int alpha = 255 - (twoCircleDistance * 255) / defaultTwoCircleDistance; textPaint.setAlpha(alpha); isShowText = false; invalidate(); } }); } /** * 设置圆形过渡到圆角矩形的动画 */ private void setCircleToRectAnimation() { animatorCircleToRect = ValueAnimator.ofInt(defaultTwoCircleDistance, 0); animatorCircleToRect.setDuration(animatorDuration); animatorCircleToRect.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { twoCircleDistance = (int) animation.getAnimatedValue(); int alpha = 255 - (twoCircleDistance * 255) / defaultTwoCircleDistance; textPaint.setAlpha(alpha); invalidate(); } }); } /** * 设置view右移的动画 */ private void setMoveToRightAnimation() { final float curTranslationX = this.getTranslationX(); animatorMoveToRight = ObjectAnimator.ofFloat(this, "translationX", curTranslationX, curTranslationX + moveDistance); animatorMoveToRight.setDuration(animatorDuration); animatorMoveToRight.setInterpolator(new AnticipateInterpolator()); } /** * 设置view左移的动画 */ private void setMoveToLeftAnimation() { final float curTranslationX = this.getTranslationX(); animatorMoveToLeft = ObjectAnimator.ofFloat(this, "translationX", curTranslationX + moveDistance, curTranslationX); animatorMoveToLeft.setDuration(animatorDuration); animatorMoveToLeft.setInterpolator(new AnticipateInterpolator()); } /** * 启动动画 */ public void closeBtn() { entryAnimatorSet.start(); } /** * 退出动画 */ public void unfoldBtn() { exitAnimatorSet.start(); } public void setAnimatorButtonListener(AnimatorButtonListener animatorButtonListener) { this.animatorButtonListener = animatorButtonListener; } public void setAnimatorButtonClickListener(AnimatorButtonClickListener animatorButtonClickListener) { this.animatorButtonClickListener = animatorButtonClickListener; } /** * 动画是否正在执行中 * * @return */ public boolean isAnimatorExecution() { return isAnimatorExecution; } /** * 是否收起状态 * * @return */ public boolean isCloseState() { return isCloseState; } public interface AnimatorButtonListener { void entryStart(); void entryEnd(); void exitStart(); void exitEnd(); } public interface AnimatorButtonClickListener { void onClickBtn(); } private void clearAnimator() { if (entryAnimatorSet != null) { entryAnimatorSet.cancel(); entryAnimatorSet = null; } if (exitAnimatorSet != null) { exitAnimatorSet.cancel(); exitAnimatorSet = null; } if (animatorRectToCircle != null) { animatorRectToCircle.cancel(); animatorRectToCircle = null; } if (animatorMoveToRight != null) { animatorMoveToRight.cancel(); animatorMoveToRight = null; } if (animatorCircleToRect != null) { animatorCircleToRect.cancel(); animatorCircleToRect = null; } if (animatorMoveToLeft != null) { animatorMoveToLeft.cancel(); animatorMoveToLeft = null; } }}attrs.xml
/ _3 _6 W8 S4 e! [ 使用方式:直接在布局文件中使用
# |$ {% w# x2 K在代码中调用closeBtn()和unfoldBtn()来收起和展开按钮状态
6 t* K9 D6 F5 c# v3 Z
4 _9 A5 V! x, q6 Z* l' Cprivate boolean isCloseState = false;@Overrideprotected void initView(@Nullable Bundle savedInstanceState) { customBtn.setAnimatorButtonClickListener(new CustomAnimatorButton.AnimatorButtonClickListener() { @Override public void onClickBtn() { if (isCloseState) { customBtn.unfoldBtn(); } else { customBtn.closeBtn(); } isCloseState = !isCloseState; } });}5 L% r3 _4 e+ O' P7 u# H
Java吧 收集整理 java论坛 www.java8.com |
|