package com.xscm.moduleutil.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.content.Context; import android.os.Build; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; import android.widget.LinearLayout; import com.blankj.utilcode.util.ScreenUtils; import com.xscm.moduleutil.utils.BarUtils; /** * com.xscm.moduleutil.widget * qx 首页首充好礼的悬浮框 * 2025/11/4 */ public class DropHomeView extends LinearLayout { private int rightMargin = 0; private float lastX, lastY; private int screenWidth; private int screenHeight; // 添加屏幕高度变量 public DropHomeView(Context context) { super(context); init(); } public DropHomeView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DropHomeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } void init() { // 初始化屏幕尺寸 screenWidth = ScreenUtils.getScreenWidth(); screenHeight = ScreenUtils.getScreenHeight(); post(new Runnable() { @Override public void run() { //设置初始位置 int sh = ScreenUtils.getScreenHeight(); int sw = ScreenUtils.getScreenWidth(); // setBackgroundResource(R.drawable.bg_home_drop_view); int y = (int) (0.6f * sh) - getHeight();//这是设置展示的纵坐标 // 确保Y坐标不会超出屏幕范围 y = Math.max(0, Math.min(y, sh - getHeight())); // int x = sw - getWidth();//这是靠右边展示的 int x=20 ;//这里这只一小的数值,就是靠左展示的 setTranslationX(x); setTranslationY(y); } }); updateSize(); mStatusBarHeight = BarUtils.getStatusBarHeight(); } /** * 更新屏幕尺寸信息 */ protected void updateSize() { ViewGroup viewGroup = (ViewGroup) getParent(); if (viewGroup != null) { mScreenWidth = viewGroup.getWidth(); mScreenHeight = viewGroup.getHeight(); } else { // 如果父视图为空,使用屏幕的实际宽度和高度 mScreenWidth = getResources().getDisplayMetrics().widthPixels; mScreenHeight = getResources().getDisplayMetrics().heightPixels; } } boolean starDrap = false; float X1; float X2; float Y1; float Y2; // 记录视图初始位置 private float originalX; private float originalY; @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (starDrap) return true; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: X1 = event.getRawX(); Y1 = event.getRawY(); // 记录视图当前位置 originalX = getTranslationX(); originalY = getTranslationY(); break; case MotionEvent.ACTION_MOVE: X2 = event.getRawX(); Y2 = event.getRawY(); Action(X1, X2, Y1, Y2); break; } return starDrap; } String TAG = "DropHourlView"; public boolean Action(float X1, float X2, float Y1, float Y2) { float ComparedX = X2 - X1;//第二次的X坐标的位置减去第一次X坐标的位置,代表X坐标上的变化情况 float ComparedY = Y2 - Y1;//同理 //当X坐标的变化量的绝对值大于Y坐标的变化量的绝对值,以X坐标的变化情况作为判断依据 //上下左右的判断,都在一条直线上,但手指的操作不可能划直线,所有选择变化量大的方向上的量 //作为判断依据 if (Math.abs(ComparedX) > 30 || Math.abs(ComparedY) > 30) { Log.i(TAG, "Action: 拖动"); starDrap = true; // setBackgroundResource(R.drawable.bg_home_drop_view); return true; } else { starDrap = false; return false; } } private float mOriginalRawX; private float mOriginalRawY; private float mOriginalX; private float mOriginalY; protected int mScreenWidth; private int mScreenHeight; private int mStatusBarHeight; private void updateViewPosition(MotionEvent event) { // 计算新的Y位置 float desY = mOriginalY + event.getRawY() - mOriginalRawY; // 限制Y位置不超出屏幕边界 if (desY < mStatusBarHeight) { desY = mStatusBarHeight; } if (desY > mScreenHeight - getHeight()) { desY = mScreenHeight - getHeight(); } // 计算新的X位置 float desX = mOriginalX + event.getRawX() - mOriginalRawX; // 限制X位置不超出屏幕边界 if (desX < 0) { desX = 0; } if (desX > mScreenWidth - getWidth()) { desX = mScreenWidth - getWidth(); } // 设置视图的新位置 setX(desX); setY(desY); } private void changeOriginalTouchParams(MotionEvent event) { mOriginalX = getX();//getX()相对于控件X坐标的距离 mOriginalY = getY(); mOriginalRawX = event.getRawX();//getRawX()指控件在屏幕上的X坐标 mOriginalRawY = event.getRawY(); } @Override public boolean onTouchEvent(MotionEvent event) { if (event == null) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: changeOriginalTouchParams(event); updateSize(); // 添加这行确保尺寸是最新的 // ... 其他现有代码 ... break; case MotionEvent.ACTION_MOVE: updateViewPosition(event); // 使用更新后的带边界检查的方法 // setBackgroundResource(R.drawable.bg_home_drop_view); // 使用屏幕绝对坐标计算新位置 // float newX = originalX + (event.getRawX() - X1); // float newY = originalY + (event.getRawY() - Y1); // // // 限制X和Y坐标在屏幕范围内 // newX = Math.max(0, Math.min(newX, screenWidth - getWidth())); // newY = Math.max(0, Math.min(newY, screenHeight - getHeight())); // // setTranslationX(newX); // setTranslationY(newY); // X2 = event.getRawX(); break; case MotionEvent.ACTION_UP: starDrap = false; int sw = ScreenUtils.getScreenWidth(); Log.i(TAG, "onTouchEvent: " + sw + "," + X2); boolean isR = getTranslationX() + getWidth() / 2 >= sw / 2;//贴边方向 // 获取当前Y坐标 float currentY = getTranslationY(); // 创建X轴和Y轴的动画 ObjectAnimator animX = ObjectAnimator.ofFloat(this, "translationX", isR ? sw - getWidth() : 0f).setDuration(200); // Y轴保持当前位置,但确保在屏幕范围内 currentY = Math.max(0, Math.min(currentY, screenHeight - getHeight())); ObjectAnimator animY = ObjectAnimator.ofFloat(this, "translationY", currentY).setDuration(200); animX.start(); animY.start(); break; } return true; } public void doRevealAnimation(View mPuppet, boolean flag) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { int[] vLocation = new int[2]; getLocationInWindow(vLocation); int centerX = vLocation[0] + getMeasuredWidth() / 2; int centerY = vLocation[1] + getMeasuredHeight() / 2; int height = ScreenUtils.getScreenHeight(); int width = ScreenUtils.getScreenWidth(); int maxRradius = (int) Math.hypot(height, width); Log.e("hei", maxRradius + ""); if (flag) { mPuppet.setVisibility(VISIBLE); Animator animator = ViewAnimationUtils.createCircularReveal(mPuppet, centerX, centerY, maxRradius, 0); animator.setDuration(600); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mPuppet.setVisibility(View.GONE); } }); animator.start(); flag = false; } else { Animator animator = ViewAnimationUtils.createCircularReveal(mPuppet, centerX, centerY, 0, maxRradius); animator.setDuration(1000); animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { mPuppet.setVisibility(View.VISIBLE); } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); animator.start(); flag = true; } } } }