自定义ViewGroup之仿网易新闻栏目管理

2023-10-23 07:38

本文主要是介绍自定义ViewGroup之仿网易新闻栏目管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前一直想写个,但是没时间。现在补上。先上效果图:

先分析一下,想到的两种实现方法:
第一种:
1. 当用户长按选择一个item时,将该item隐藏,然后用WindowManager添加一个新的window,该window与所选择item一模一样,并且跟随用户手指滑动而不断改变位置。
2. 当window的位置坐标在GridView里面时,使用pointToPosition (int x, int y)方法来判断对应的应该是哪个item,在adapter中作出数据集相应的变化,然后做出平移的动画。
3. 当用户手指抬起时,把window移除,使用notifyDataSetChanged()做出GridView更新
第二种:
       用getView获取要拖动的view,在Move事件下不断平移得到x新的坐标调用onLayout(true,l,t,r,b);
view.startAnimation; onLayout(true, getLeft(), getTop(), getRight(), getBottom());

第一种看到已经有人实现了,但是偶尔会有崩溃的问题。于是我根据他的思路,以自己更容易理解的方式再写了一遍。在此对这位兄弟表示感谢,地址我会贴在文章最后.
第二种有时间再补上。
下面正式开始:
先看一下所有的方法:


DragGridView继承GridView,在onInterceptTouchEvent的ACTION_DOWN时设置长按监听。长按item触发OnItemLongClickListener,
在这里windowManager.addView(dragView, windowLayoutParams);
onTouchEvent方法判断更新操作:
@Override
public boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:lastX = (int) ev.getRawX();
            lastY = (int) ev.getRawY();
            windowX = (int) ev.getX();
            windowY = (int) ev.getY();
            break;
        case MotionEvent.ACTION_MOVE://拖动时判断位置,平移;
            if (isDraging) {updateWindow(ev, (int) ev.getRawX() - lastX, (int) ev.getRawY() - lastY);
                lastX = (int) ev.getRawX();
                lastY = (int) ev.getRawY();
            }break;
        case MotionEvent.ACTION_UP://拖动时判断位置,平移;
            if (isDraging) {isDraging = false;
                closeWindow(ev);
            }break;
    }return super.onTouchEvent(ev);
}
重要的方法:
updateWindow();
/**
 * 更新悬浮窗位置;
 *
 * @param ev
 */
private void updateWindow(MotionEvent ev, int deltaX, int deltaY) {mTempPos = pointToPosition((int) ev.getX(), (int) ev.getY());
    if (mTempPos != AdapterView.INVALID_POSITION && mTempPos != prePos) {if (mTempPos > prePos) {for (int i = prePos + 1; i <= mTempPos; i++) {Animation moveAnimation;
                if (i % numColumns == 0) {moveAnimation = getMoveAnimation((numColumns - 1) * horizon_div, -vertical_div);
                } else {moveAnimation = getMoveAnimation(-horizon_div, 0);
                }getChildAt(i).startAnimation(moveAnimation);//left.
                if (i == mTempPos) {lastAniID = moveAnimation.toString();
                }moveAnimation.setAnimationListener(new Animation.AnimationListener() {@Override
                    public void onAnimationStart(Animation animation) {isMoving = true;
                    }@Override
                    public void onAnimationEnd(Animation animation) {swap(animation);
                        isMoving = false;
                    }@Override
                    public void onAnimationRepeat(Animation animation) {}});
            }} else {//mTempPos < prePos
            for (int i = prePos - 1; i >= mTempPos; i--) {Animation moveAnimation;
                if (i % numColumns == numColumns - 1) {moveAnimation = getMoveAnimation(-(numColumns - 1) * horizon_div, vertical_div);
                } else {moveAnimation = getMoveAnimation(horizon_div, 0);
                }getChildAt(i).startAnimation(moveAnimation);//left.
                if (i == mTempPos) {lastAniID = moveAnimation.toString();
                }moveAnimation.setAnimationListener(new Animation.AnimationListener() {@Override
                    public void onAnimationStart(Animation animation) {}@Override
                    public void onAnimationEnd(Animation animation) {swap(animation);
                    }@Override
                    public void onAnimationRepeat(Animation animation) {}});
            }}((DragAdapter) getAdapter()).swap(prePos, mTempPos);
        prePos = mTempPos;
    }windowLayoutParams.x += deltaX;
    windowLayoutParams.y += deltaY;
    windowManager.updateViewLayout(dragView, windowLayoutParams);
}
prePos为上一次拖动的位置,mTempPos为当前window添加的dragView移到的位置,不相等时出发平移动画,并且置换数据位置。
最后在UP事件时调用closeWindow,移除windowManager的view,显示之前隐藏的item。移除子view的动画。

这么思路整理下来,还是挺简单的,实际写的时候还是有需要注意的点:
1.在子view结束动画后,需要 clearAnimation(),因为Animation.setFillAfter(true);执行动画后,数据有变动了 ,再notify时也不会消除上一次动画的影响,造成错位。
2. 刚开始我使用的是动画结束才真实交换数据位置。但这样但会造成两次动画,因为动画没结束,prePos和mTempPos没变化,会再次触发动画。解决方法就是触发动画的同时真实交换数据位置。
3.在windowmanager添加view时:app主题为actionbar时会偏移,<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">改为NoActionBar。windowLayoutParams.y = DragGridView.this.getTop() + view.getTop();(这个是之前的写法,不适用于在scrollView的情况)
3.需要在scrollView中使用该控件,需要解决显示的长度,和事件冲突。(具体看源码,这里不在解释)

最后附上源码地址:https://github.com/Ulez/WangyiIndicator
参考:http://www.jianshu.com/p/559b631ec330

这篇关于自定义ViewGroup之仿网易新闻栏目管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/266465

相关文章

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

SpringBoot使用minio进行文件管理的流程步骤

《SpringBoot使用minio进行文件管理的流程步骤》MinIO是一个高性能的对象存储系统,兼容AmazonS3API,该软件设计用于处理非结构化数据,如图片、视频、日志文件以及备份数据等,本文... 目录一、拉取minio镜像二、创建配置文件和上传文件的目录三、启动容器四、浏览器登录 minio五、

IDEA中的Kafka管理神器详解

《IDEA中的Kafka管理神器详解》这款基于IDEA插件实现的Kafka管理工具,能够在本地IDE环境中直接运行,简化了设置流程,为开发者提供了更加紧密集成、高效且直观的Kafka操作体验... 目录免安装:IDEA中的Kafka管理神器!简介安装必要的插件创建 Kafka 连接第一步:创建连接第二步:选

SpringBoot 自定义消息转换器使用详解

《SpringBoot自定义消息转换器使用详解》本文详细介绍了SpringBoot消息转换器的知识,并通过案例操作演示了如何进行自定义消息转换器的定制开发和使用,感兴趣的朋友一起看看吧... 目录一、前言二、SpringBoot 内容协商介绍2.1 什么是内容协商2.2 内容协商机制深入理解2.2.1 内容

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s