Android 仿美团悬浮购物车显示隐藏

效果图:

在这里插入图片描述

这是美团的效果

在这里插入图片描述 在这里插入图片描述

通过效果图可以看到 静止的时候是购物车图标是显示的,滑动的时候是隐藏一半并半透明显示的。
这里用到一个触摸反馈的方法dispatchTouchEvent

  • MotionEvent.ACTION_DOWN://手指按下
  • MotionEvent.ACTION_MOVE://手指滑动
  • MotionEvent.ACTION_UP://手指抬起

整体的思路就是在滑动过程中,购物车图标向右位移,并加一个渐变效果。

在这里插入图片描述

向右移动的距离计算:屏幕的宽度减去图标距左边的宽度(红线),然后加上图标的半径(蓝线)

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <ImageView
        android:id="@+id/iv_cart"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="60dp"
        android:layout_marginEnd="20dp"
        android:layout_marginRight="20dp"
        android:contentDescription="@null"
        android:src="@drawable/ic_cart"/>

</RelativeLayout>

代码

初始化控件
        mListView = findViewById(R.id.list_view);
        mIvCart = findViewById(R.id.iv_cart);
初始化数据
        for (int i = 0; i < 50; i++) {
            titles.add("第  -  " + i + "  -  条数据");
        }
        mListView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, titles));
计算移动距离
        //控件绘制完成之后再获取其宽高
        mIvCart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //动画移动的距离 屏幕的宽度减去图片距左边的宽度 就是图片距右边的宽度,再加上隐藏的一半
                moveDistance = getScreenWidth() - mIvCart.getRight() + mIvCart.getWidth() / 2;
                //监听结束之后移除监听事件
                mIvCart.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });
    private int getScreenWidth() {
        DisplayMetrics dm = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }
隐藏动画
    private void hideFloatImage(int distance) {
        isShowFloatImage = false;

        //位移动画
        TranslateAnimation ta = new TranslateAnimation(0, distance, 0, 0);
        ta.setDuration(300);

        //渐变动画
        AlphaAnimation al = new AlphaAnimation(1f, 0.5f);
        al.setDuration(300);

        AnimationSet set = new AnimationSet(true);
        //动画完成后不回到原位
        set.setFillAfter(true);
        set.addAnimation(ta);
        set.addAnimation(al);
        mIvCart.startAnimation(set);
    }
显示动画
    private void showFloatImage(int distance) {
        isShowFloatImage = true;

        //位移动画
        TranslateAnimation ta = new TranslateAnimation(distance, 0, 0, 0);
        ta.setDuration(300);

        //渐变动画
        AlphaAnimation al = new AlphaAnimation(0.5f, 1f);
        al.setDuration(300);

        AnimationSet set = new AnimationSet(true);
        //动画完成后不回到原位
        set.setFillAfter(true);
        set.addAnimation(ta);
        set.addAnimation(al);
        mIvCart.startAnimation(set);
    }
处理滑动逻辑
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://手指按下
                if (System.currentTimeMillis() - upTime < 1000) {
                    //本次按下距离上次的抬起小于1s时,取消Timer
                    timer.cancel();
                }
                startY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE://手指滑动
                if (Math.abs(startY - event.getY()) > 10) {
                    if (isShowFloatImage) {
                        hideFloatImage(moveDistance);
                    }
                }
                startY = event.getY();
                break;
            case MotionEvent.ACTION_UP://手指抬起
                if (!isShowFloatImage) {
                    //抬起手指1s后再显示悬浮按钮
                    //开始1s倒计时
                    upTime = System.currentTimeMillis();
                    timer = new Timer();
                    timer.schedule(new FloatTask(), 1000);
                }
                break;
        }
        return super.dispatchTouchEvent(event);
    }
  • 这里用一个upTime 记录手指抬起的时间,如果小于1s动画就不执行,避免快速反复滑动导致动画多次执行。
  • 然后用一个定时器timer延时执行动画
  • 在手指抬起的时候记录当前时间戳,并执行动画
  • moveDistance就是计算的移动的距离
  • isShowFloatImage是一个布尔类型的标识,判断图标状态是否显示
  • startY - event.getY()) > 10 这个大于10是因为手指按下的是一个面,不是一个点,把这个面的高度定为10

github : https://github.com/yechaoa/FloatCartDemo


ok,完成,借鉴https://blog.csdn.net/Lindroid20/article/details/78887347

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
您!要实现仿微信视频通话悬浮窗功能,您可以按照以下步骤进行操作: 1. 创建悬浮窗权限:在 AndroidManifest.xml 文件中添加悬浮窗权限声明,如下所示: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 2. 创建悬浮窗服务:创建一个继承自 Service 的类,用于管理悬浮窗的创建、更新和移除等操作。在该类中,您可以使用 WindowManager 来显示悬浮窗,并监听触摸事件来实现拖拽和缩放等操作。 3. 设计悬浮窗布局:创建一个 XML 布局文件,用于定义悬浮窗的界面。您可以自定义界面元素,如视频画面、控制按钮等。 4. 实现悬浮窗功能:在悬浮窗服务类中,根据需要添加相应的逻辑。例如,您可以使用 MediaProjection API 来捕获屏幕内容,并将其显示悬浮窗中;您还可以使用 Camera API 来获取摄像头数据,并实现视频通话功能。 5. 添加权限申请逻辑:在需要使用悬浮窗功能的地方,添加权限申请逻辑,以确保用户在安装应用时授予悬浮窗权限。 请注意,实现仿微信视频通话悬浮窗功能需要一定的 Android 开发知识和经验。如果您对 Android 开发不太熟悉,建议您先学习相关的基础知识,然后再尝试实现该功能。同时,还要注意遵守 Android 官方的开发规范和安全要求。希望对您有所帮助!如果您有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yechaoa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值