1.自定义布局
package com.example.administrator.test; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.TranslateAnimation; import android.widget.PopupWindow; import android.widget.RelativeLayout; /** * Created by Administrator on 2018/6/27. */ public class MyView extends View implements View.OnClickListener { public static final String TAG = "AgreeView"; //默认动画移动距离 private static final int DEFAULT_DISTANCE = 60; //默认动画起始点 private static final int DEFAULT_FROM_Y = 0; //动画起始点距离 private static final int DEFAULT_TO_Y = DEFAULT_DISTANCE; //动画起始透明度 private static final float DEFAULT_FROM_ALPHA = 1.0f; //动画默认透明度 private static final float DEFAULT_TO_ALPHA = 0.0f; //动画时长 private static final int DEFAULT_DURATION = 700; //默认文字大小 private static final int DEFAULT_TEXT_SIZE = 16; //默认文字颜色 private static final int DEFAULT_TEXT_COLOR = Color.BLACK; //默认 文字 private static final String DEFAULT_TEXT = "+1"; //默认点赞图片 private static final int DEFAULT_IMG = R.drawable.donghua; //动画 文字 private static final int ANIMATION_MODE_TEXT = 0; //动画图片 private static final int ANIMATION_MODE_IMG = 1; //默认文字模式动画 private static final int DEFAULT_ANIMATION_MODE = ANIMATION_MODE_TEXT; //移动距离 private int distance; //Y轴起始偏移量 private int from_y; //Y轴移动距离 private int to_y; //起始透明度 private float from_alpha; //结束透明度 private float to_alpha; //动画时长 private int duration; //动画文本 private String text = ""; //文本大小 private int text_size; //文本颜色 private int text_color; //动画 private AppCompatTextView tvAnimation; //动画图片 private Drawable animalDrawable; //点赞图片 private Drawable agreeDrawable; private Context mContext; private int animationMode; /** * PopupWindow来显示点击动画 */ private PopupWindow mPW; /** * 动画组合 */ private AnimationSet mAnimationSet; /** * 是否改变了属性 */ private boolean isChanged = true; private Animation animation; public MyView(Context context) { super(context); mContext = context; initView(null); } public MyView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); mContext = context; initView(attrs); } public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; initView(attrs); } private void initView(AttributeSet attrs) { if (attrs != null) { TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.MyView); distance = typedArray.getInt(R.styleable.MyView_distance, DEFAULT_DISTANCE); from_y = typedArray.getInt(R.styleable.MyView_from_y, DEFAULT_FROM_Y); to_y = distance; from_alpha = typedArray.getFloat(R.styleable.MyView_from_alpha, DEFAULT_FROM_ALPHA); to_alpha = typedArray.getFloat(R.styleable.MyView_to_alpha, DEFAULT_TO_ALPHA); duration = typedArray.getInt(R.styleable.MyView_duration, DEFAULT_DURATION); text = typedArray.getString(R.styleable.MyView_text); if (text == null) { text = DEFAULT_TEXT; } text_size = typedArray.getInt(R.styleable.MyView_text_size, DEFAULT_TEXT_SIZE); text_color = typedArray.getColor(R.styleable.MyView_text_color, DEFAULT_TEXT_COLOR); animalDrawable = typedArray.getDrawable(R.styleable.MyView_animation_img); agreeDrawable = typedArray.getDrawable(R.styleable.MyView_picture); animationMode = typedArray.getInt(R.styleable.MyView_animation, ANIMATION_MODE_TEXT); if (agreeDrawable == null) { agreeDrawable = ContextCompat.getDrawable(getContext(), R.drawable.donghua); } //资源释放 typedArray.recycle(); } //我们将PopupWindow作为动画View //初始化我们的PopupWindow mPW = new PopupWindow(); //PopupWindow创建相对布局 RelativeLayout layout = new RelativeLayout(mContext); //布局参数 RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); tvAnimation = new AppCompatTextView(mContext); tvAnimation.setIncludeFontPadding(false); tvAnimation.setTextSize(TypedValue.COMPLEX_UNIT_DIP, text_size); tvAnimation.setTextColor(text_color); if (animationMode == ANIMATION_MODE_TEXT) { tvAnimation.setText(text); } else { tvAnimation.setText(""); tvAnimation.setBackgroundDrawable(animalDrawable); } tvAnimation.setLayoutParams(layoutParams); layout.addView(tvAnimation); mPW.setContentView(layout); //量测我们的动画的宽高 int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); tvAnimation.measure(w, h); mPW.setWidth(tvAnimation.getMeasuredWidth()); mPW.setHeight(distance + tvAnimation.getMeasuredHeight()); mPW.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); mPW.setFocusable(false); mPW.setTouchable(false); mPW.setOutsideTouchable(false); this.setOnClickListener(this); //设置文字、图片移动动画 setPopAnimation(); //点击缩放动画 setScaleAnimation(); } /** * 缩放动画 */ private void setScaleAnimation() { ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1f, 0.8f, 1.2f, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1f, 0.8f, 1.2f, 1f); scaleX.setDuration(duration); scaleY.setDuration(duration); scaleX.setInterpolator(new AccelerateDecelerateInterpolator()); scaleY.setInterpolator(new AccelerateDecelerateInterpolator()); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(scaleX).with(scaleY); animatorSet.start(); } @Override public void onClick(View v) { if (mPW != null && !mPW.isShowing()) { int offsetY = -getHeight() - mPW.getHeight(); mPW.showAsDropDown(this, getWidth() / 2 - mPW.getWidth() / 2, offsetY); mPW.update(); if (mAnimationSet == null) { setPopAnimation(); } tvAnimation.startAnimation(mAnimationSet); setScaleAnimation(); //外部点击事件 if (clickListener != null) { clickListener.onAgreeClick(v); } } } /** * 动画组合 */ private void setPopAnimation() { mAnimationSet = new AnimationSet(true); TranslateAnimation translateAnim = new TranslateAnimation(0, 0, from_y, -to_y); AlphaAnimation alphaAnim = new AlphaAnimation(from_alpha, to_alpha); mAnimationSet.addAnimation(translateAnim); mAnimationSet.addAnimation(alphaAnim); mAnimationSet.setDuration(duration); mAnimationSet.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (mPW != null && mPW.isShowing()) { new Handler().post(new Runnable() { @Override public void run() { mPW.dismiss(); } }); } } @Override public void onAnimationRepeat(Animation animation) { } }); } @Override protected void onDraw(Canvas canvas) { //将我们的Drawable画到画布 agreeDrawable.draw(canvas); } /** * 量测点击控件的大小 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width; int height; int w_mode = MeasureSpec.getMode(widthMeasureSpec); int w_size = MeasureSpec.getSize(widthMeasureSpec); int h_mode = MeasureSpec.getMode(heightMeasureSpec); int h_size = MeasureSpec.getSize(heightMeasureSpec); if (w_mode == MeasureSpec.AT_MOST || w_mode == MeasureSpec.UNSPECIFIED) { width = agreeDrawable.getIntrinsicWidth(); } else { width = w_size; } if (h_mode == MeasureSpec.AT_MOST || h_mode == MeasureSpec.UNSPECIFIED) { height = agreeDrawable.getIntrinsicHeight(); } else { height = h_size; } setMeasuredDimension(width, height); //根据量测的宽高,设置我们画的Drawable的大小 @SuppressLint("DrawAllocation") Rect rect = new Rect(0, 0, width, height); agreeDrawable.setBounds(rect); } public void setClickListener(MyViewClickListener clickListener) { this.clickListener = clickListener; } private MyViewClickListener clickListener; public interface MyViewClickListener { void onAgreeClick(View view); } }
2.资源donghua
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:fillColor="#c6115f" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/> </vector>3.values中的arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyView"> <!--动画颜色--> <attr name="text_color" format="color"/> <!--点赞图片--> <attr name="picture" format="reference"/> <!--动画图片--> <attr name="animation_img" format="reference"/> <!--动画移动最终距离--> <attr name="distance" format="integer"/> <!--动画起始位置--> <attr name="from_y" format="integer"/> <!--动画开始透明度--> <attr name="from_alpha" format="float"/> <!--动画结束透明度--> <attr name="to_alpha" format="float"/> <!--持续时间--> <attr name="duration" format="integer"/> <!--动画显示的文字--> <attr name="text" format="string"/> <!--动画文字大小--> <attr name="text_size" format="integer"/> <!--动画选择是图片还是文字--> <attr name="animation" format="enum"> <enum name="text" value="0"/> <enum name="picture" value="1"/> </attr> </declare-styleable> </resources>4.activity布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:view="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.administrator.test.MyView android:id="@+id/myview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="208dp" android:layout_gravity="center_horizontal" view:animation="text" view:animation_img="@drawable/donghua" view:distance="100" view:from_y="60" view:text="点赞+1" view:text_color="@color/colorAccent"> </com.example.administrator.test.MyView> <android.support.constraint.Group android:id="@+id/group" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>5.activity
package com.example.administrator.test; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; public class MainActivity extends AppCompatActivity { private MyView txtAgreeView; public static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtAgreeView = findViewById(R.id.myview); txtAgreeView.setClickListener(new MyView.MyViewClickListener() { @Override public void onAgreeClick(View view) { Log.e(TAG, "onAgreeClick: " + "IMG"); } }); } }