自定义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

相关文章

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

Spring中管理bean对象的方式(专业级说明)

《Spring中管理bean对象的方式(专业级说明)》在Spring框架中,Bean的管理是核心功能,主要通过IoC(控制反转)容器实现,下面给大家介绍Spring中管理bean对象的方式,感兴趣的朋... 目录1.Bean的声明与注册1.1 基于XML配置1.2 基于注解(主流方式)1.3 基于Java

基于Python+PyQt5打造一个跨平台Emoji表情管理神器

《基于Python+PyQt5打造一个跨平台Emoji表情管理神器》在当今数字化社交时代,Emoji已成为全球通用的视觉语言,本文主要为大家详细介绍了如何使用Python和PyQt5开发一个功能全面的... 目录概述功能特性1. 全量Emoji集合2. 智能搜索系统3. 高效交互设计4. 现代化UI展示效果

Druid连接池实现自定义数据库密码加解密功能

《Druid连接池实现自定义数据库密码加解密功能》在现代应用开发中,数据安全是至关重要的,本文将介绍如何在​​Druid​​连接池中实现自定义的数据库密码加解密功能,有需要的小伙伴可以参考一下... 目录1. 环境准备2. 密码加密算法的选择3. 自定义 ​​DruidDataSource​​ 的密码解密3

Mysql中的用户管理实践

《Mysql中的用户管理实践》:本文主要介绍Mysql中的用户管理实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录13. 用户管理13.1 用户 13.1.1 用户信息 13.1.2 创建用户 13.1.3 删除用户 13.1.4 修改用户

spring-gateway filters添加自定义过滤器实现流程分析(可插拔)

《spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔)》:本文主要介绍spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔),本文通过实例图... 目录需求背景需求拆解设计流程及作用域逻辑处理代码逻辑需求背景公司要求,通过公司网络代理访问的请求需要做请

linux服务之NIS账户管理服务方式

《linux服务之NIS账户管理服务方式》:本文主要介绍linux服务之NIS账户管理服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、所需要的软件二、服务器配置1、安装 NIS 服务2、设定 NIS 的域名 (NIS domain name)3、修改主

Python+PyQt5开发一个Windows电脑启动项管理神器

《Python+PyQt5开发一个Windows电脑启动项管理神器》:本文主要介绍如何使用PyQt5开发一款颜值与功能并存的Windows启动项管理工具,不仅能查看/删除现有启动项,还能智能添加新... 目录开篇:为什么我们需要启动项管理工具功能全景图核心技术解析1. Windows注册表操作2. 启动文件

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指