思路
- 找到
Activity 中DecorView 的RootView - 确定点赞控件位于屏幕中的坐标值
- 将点赞效果View加入到
RootView 中, 给效果View添加自己想要的动画效果. - 重复点击时候, 需要将效果View先移除掉再重新加入到
RootView 中.
代码
public class ViewLikeUtils {
public interface ViewLikeClickListener {
void onClick(View view, boolean toggle, ViewLikeUtils viewLikeUtils);
}
private View mClickView;
private View mAnimView;
private ViewLikeClickListener mListener;
private boolean toggle = false;
private int mX;
private int mY;
public ViewLikeUtils(View mClickView, View mAnimView, @NonNull ViewLikeClickListener mListener) {
this.mClickView = mClickView;
this.mAnimView = mAnimView;
this.mListener = mListener;
initListener();
}
private void initListener() {
mClickView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
getLocation();
toggle = !toggle;
if (mListener != null) {
mListener.onClick(mClickView, toggle, ViewLikeUtils.this);
}
}
return true;
}
});
}
private void getLocation() {
int[] mLocation = new int[2];
mClickView.getLocationOnScreen(mLocation);
mX = mLocation[0];
mY = mLocation[1];
}
private void startAnim(ValueAnimator valueAnimator) {
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mAnimView.setAlpha(1 - (Float) valueAnimator.getAnimatedFraction());
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mAnimView.getLayoutParams();
params.topMargin = (int) (mY - mAnimView.getMeasuredHeight() - 100 * valueAnimator.getAnimatedFraction());
mAnimView.setLayoutParams(params);
}
});
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
removeChildView(mAnimView);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
valueAnimator.start();
}
private void addAnimView(View animview) {
Activity activityFromView = getActivityFromView(mClickView);
if (activityFromView != null) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
FrameLayout mRootView = (FrameLayout) activityFromView.getWindow().getDecorView().getRootView();
mRootView.addView(animview, params);
animview.measure(0, 0);
params.topMargin = (int) (mY - animview.getMeasuredHeight());
params.leftMargin = mX + mClickView.getMeasuredWidth() / 2 - animview.getMeasuredHeight() / 2;
animview.setLayoutParams(params);
}
}
public void startLikeAnim(ValueAnimator valueAnimator) {
removeChildView(mAnimView);
addAnimView(mAnimView);
startAnim(valueAnimator);
}
public Activity getActivityFromView(View view) {
if (null != view) {
Context context = view.getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
}
return null;
}
private void removeChildView(View mChildView) {
ViewGroup parentViewGroup = (ViewGroup) mChildView.getParent();
if (parentViewGroup != null) {
parentViewGroup.removeView(mChildView);
}
}
}
使用
val textView = TextView(this@MainActivity2)
textView.text = "+1"
textView.setTextColor(Color.RED)
textView.textSize = mBtn.textSize
val animator = ValueAnimator.ofInt(10, 200)
animator.duration = 800
ViewLikeUtils(findViewById<Button>(R.id.btn_anim), textView) { clickView, toggle, mUtils ->
mUtils.startLikeAnim(animator)
}
效果
|