Android中实现直播带货功能

前言:

这两年直播带货非常火,前段时间我们项目需求也提了这个功能,于是查看抖音、快手、淘宝的实现方式,结合咱们自己的项目,直播带货有2种场景:

1.一种是在单一页面进行商品购买.

2.一种是全局悬浮窗,在所有页面都可以去购物.

3.单一页面一个拖拽按钮就可以实现,全局悬浮窗比较麻烦,由于涉及到多个页面的跳转传递数据和回收问题。

4.单个页面的悬浮按钮,可以用一个自定义的可拖拽按钮来实现.

5.实现思路:

5.1 通过重写控件的onTouchEvent方法监听触摸效果.

5.2 通过view的setX和setY方法来实现移动.

5.3 使用属性动画来实现边缘吸附效果.

5.4 左右吸附功能:

ScreenUtils.dip2px(getContext(), 20)是控制左右边距的大小,通过dp转化为px,适配不同分辨率的机型。如果需要靠边吸附,更改为0即可,如果不需要自动吸附功能,也直接注释掉就可以了,使用十分简单方便。

5.5 可拖动的悬浮按钮

/** * @作者: njb * @时间: 2019/12/10 14:38 * @描述: 可拖动的悬浮按钮 */ @SuppressLint("AppCompatCustomView") public class DragFloatActionButton extends ImageView { ​ private int parentHeight; private int parentWidth; private int lastX; private int lastY; private boolean isDrag; ​ public DragFloatActionButton(Context context) { super(context); } ​ public DragFloatActionButton(Context context, AttributeSet attrs) { super(context, attrs); } ​ public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } ​ ​ @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { int rawX = (int) event.getRawX(); int rawY = (int) event.getRawY(); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: isDrag = false; setPressed(true); getParent().requestDisallowInterceptTouchEvent(true); lastX = rawX; lastY = rawY; ViewGroup parent; if (getParent() != null) { parent = (ViewGroup) getParent(); parentHeight = parent.getHeight(); parentWidth = parent.getWidth(); } break; case MotionEvent.ACTION_MOVE: if (parentHeight <= 0 || parentWidth == 0) { isDrag = false; break; } else { isDrag = true; } int dx = rawX - lastX; int dy = rawY - lastY; //这里修复一些华为手机无法触发点击事件 int distance = (int) Math.sqrt(dx * dx + dy * dy); if (distance == 0) { isDrag = false; break; } float x = getX() + dx; float y = getY() + dy; //检测是否到达边缘 左上右下 x = x < 0 ? 0 : x > parentWidth - getWidth() ? parentWidth - getWidth() : x; y = getY() < 0 ? 0 : getY() + getHeight() > parentHeight ? parentHeight - getHeight() : y; setX(x); setY(y); lastX = rawX; lastY = rawY; Rlog.d("aa", "isDrag=" + isDrag + "getX=" + getX() + ";getY=" + getY() + ";parentWidth=" + parentWidth); break; case MotionEvent.ACTION_UP: if (isDrag) { //恢复按压效果 setPressed(false); moveHide(rawX); } break; default: break; } //如果是拖拽则消耗事件,否则正常传递即可。 return isDrag || super.onTouchEvent(event); } ​ /** * 吸附动画 * @param rawX */ private void moveHide(int rawX) { if (rawX >= parentWidth / 2) { //靠右吸附 animate().setInterpolator(new DecelerateInterpolator()) .setDuration(500) .xBy(parentWidth - getWidth() - getX() - ScreenUtil.dip2px( 20)) .start(); } else { //靠左吸附 ObjectAnimator oa = ObjectAnimator.ofFloat(this, "x", getX(), ScreenUtil.dip2px(20)); oa.setInterpolator(new DecelerateInterpolator()); oa.setDuration(500); oa.start(); ​ } } }

6.单页面实现的效果截图如下:

img

点击按钮就可以进入直播购物界面,这里就不写了,很简单的一个跳转事件.后面会给出全局悬浮窗实现方案。

7.全局悬浮窗:

这里全局悬浮窗用的是EasyFloat这个第三方库,由于项目时间太赶,所以用的现成的方案,没有专门用系统的windowmanager, EasyFloat的github地址为: GitHub - princekin-f/EasyFloat: 🔥 EasyFloat:浮窗从未如此简单(Android可拖拽悬浮窗口,支持页面过滤、自定义动画,可设置单页面浮窗、前台浮窗、全局浮窗,浮窗权限按需自动申请...),这里有详细的使用说明和介绍.

7.1 导入方式:implementation 'com.github.princekin-f:EasyFloat:1.2.1'

7.2 如果你要在整个项目全局使用的话就可以直接在application中初始化,

​ ** * @author: njb * @date: 2020/2/28 0028 12:35 * @desc: */ public class App extends Application { //全局Context private static Context sContext; ​ @Override public void onCreate() { super.onCreate(); sContext = getApplicationContext(); //初始化悬浮窗 initEasyFloat(); } ​ private void initEasyFloat() { EasyFloat.init(this); } ​ ​ public static Context getContext() { return sContext; } }

img

7.3 请求系统浮窗权限

loadPermissions();

img

/** * 请求悬浮窗权限 */ private void loadPermissions() { if (PermissionUtils.checkPermission(this)) { String liveId = "100086"; //初始化悬浮窗 initFlowWindow(liveId); }else { final AlertDialog.Builder alert = new AlertDialog.Builder(this); alert.setMessage("使用浮窗功能,需要您授权悬浮窗权限。"); alert.setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())); alert.setPositiveButton("去开启", (dialog, which) -> { String liveId = "100086"; initFlowWindow(liveId); dialog.dismiss(); }); alert.show(); } }

7.4 初始化悬浮窗布局,由于我们的需求是从直接跳转到购物页面,所以点击按钮回到直播间,这里只是给出悬浮窗的使用,具体的业务逻辑要根据需求自己去实现,当然回直播间后这个悬浮按钮也随之隐藏,如果需求不需要隐藏也可以设置不隐藏.

/** * 初始化悬浮窗布局 * @param liveId */ private void initFlowWindow(String liveId) { if (!TextUtils.isEmpty(liveId)) { EasyFloat.with(this) // 设置浮窗xml布局文件 .setLayout(R.layout.layout_float_window, view -> { // view就是我们传入的浮窗xml布局 view.findViewById(R.id.go_to_image).setOnClickListener(view1 -> { //回直播 startActivity(new Intent(Mainivity.this,LiveActivity.class)) //隐藏悬浮框 EasyFloat.hideAppFloat("live"); EasyFloat.dismissAppFloat("live"); }); }) // 设置浮窗显示类型,默认只在当前Activity显示,可选一直显示、仅前台显示 .setShowPattern(ShowPattern.FOREGROUND) // 设置吸附方式,共15种模式,详情参考SidePattern .setSidePattern(SidePattern.RESULT_HORIZONTAL) // 设置浮窗的标签,用于区分多个浮窗 .setTag("live") // 设置浮窗是否可拖拽 .setDragEnable(true) // 设置浮窗的对齐方式和坐标偏移量 .setGravity(Gravity.END | Gravity.CENTER_VERTICAL, 0, 200) // 设置宽高是否充满父布局,直接在xml设置match_parent属性无效 .setMatchParent(false, false) // 设置Activity浮窗的出入动画,可自定义,实现相应接口即可(策略模式),无需动画直接设置为null .setAnimator(new DefaultAnimator()) // 设置系统浮窗的出入动画,使用同上 .setAppFloatAnimator(new AppFloatDefaultAnimator()).show(); EasyFloat.showAppFloat("live"); } else { EasyFloat.hide(); EasyFloat.hideAppFloat("live"); } }

7.5 实现的效果如下:

img

7.6 最后感谢刘振峰大佬的开源方案,全局悬浮窗介绍这么简单便捷.后面会尝试使用系统的windowmanager实现全局悬浮框.

原文链接:https://blog.csdn.net/u012556114/article/details/104553851?ops_request_misc=&request_id=860d261d96a74196884ce286e8101054&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~koosearch~default-24-104553851-null-null.268%5Ev1%5Econtrol&utm_term=%E7%9B%B4%E6%92%AD%E5%B8%A6%E8%B4%A7

兔子先生 西安驾培

于灯火阑珊处,于暗香离别时,未曾放弃

相关推荐

抖音矩阵平台有哪些?

  抖音矩阵平台是指一系列用于在抖音平台上进行内容创作、运营和推广的工具和系统。其中,视界引擎短视频运营获客系统作为一款全面的抖音矩阵平台,具有许多优势。 抖音矩阵平台是当今数字营销领域的热门工 ...

怎么看待直播带货的营销形式?

随着电商行业的崛起,越来越多的商家开始使用直播的方式来进行产品推广,那么直播为什么可以推广产品带货呢?直播带货的本质是什么呢?今天,就来跟大家讲解一下。直播之所以可以推广产品,引导观众购买产品是因 ...

快抖矩阵多账号管理系统官方正版

账号源从哪里来?没有那么多抖音账号?怎么赚钱?有什么价值?       首先这是一套多开可招代理的矩阵账号管理系统,第一目的是让你拿来给有很多账号的品牌机构或达人当账号辅助管理工具打理账户 ...