我的第一个开源控件-DragGridView

Posted _StriveG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的第一个开源控件-DragGridView相关的知识,希望对你有一定的参考价值。

我的第一个开源控件出炉了,希望各个小伙伴给个star,支持下。项目地址

1. 前言

由于项目需要,要做一个类似腾讯视频,频道管理,拖拽排序的效果。这个控件是在原地址 之上改造出来的。先看下效果图。
 1.0版本的效果图
由于我电脑是ubuntu,没法弄gif,等星期一到了公司上gif吧,不过,github上有apk,可以弄下来看看,
这里写图片描述

2. 实现思路

2.1 如何响应长按事件

我们虽然可以给view设置监听器,但是我们需要频繁的调用GridVIew的一些方法,显然,那样做是不合适的。于是,我们在onInterceptTouchEvent中设置长按和短按的监听。

2.2 响应长按之后干什么

在响应长按事件之后,我们通过windowmanager在我们长按处添加一个view.添加view的代码如下。

windowParams = new WindowManager.LayoutParams();
        windowParams.gravity = Gravity.TOP | Gravity.LEFT;
        windowParams.x = x - win_view_x;
        windowParams.y = y - win_view_y;
        windowParams.width = (int) (dragScale * dragBitmap.getWidth());// 放大dragScale倍,可以设置拖动后的倍数
        windowParams.height = (int) (dragScale * dragBitmap.getHeight());// 放大dragScale倍,可以设置拖动后的倍数
        this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        this.windowParams.format = PixelFormat.TRANSLUCENT;
        this.windowParams.windowAnimations = 0;
        ImageView iv = new ImageView(getContext());
        iv.setImageBitmap(dragBitmap);
        windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
        windowManager.addView(iv, windowParams);

2.3 移动的过程怎么处理

移动的过程中我们需要处理2件事,更改view的位置,动画。
先说更改view的位置。代码如下

windowParams.alpha = 1.f;
            windowParams.x = rawx - win_view_x;
            windowParams.y = rawy - win_view_y;
            windowManager.updateViewLayout(dragImageView, windowParams);

我们只需要修改params的x,y,并且update即可。再说动画。

  • 计算当前所在的position | pointToPosition(x, y);
  • 计算应该移动的数量 | 当前-移动那一块
movecount = endPosition - dragPosition;
  • 根据大小计算移动的方向和距离
for (int i = 0; i < movecount_abs; i++) {
                    to_x = x_vlaue;
                    to_y = y_vlaue;
                    //像左
                    if (movecount > 0) {
                        // 判断是不是同一行的
                        holdPosition = dragPosition + i + 1;
                        if (dragPosition / mColumns == holdPosition / mColumns) {
                            to_x = -x_vlaue;
                            to_y = 0;
                        } else if (holdPosition % 4 == 0) {
                            to_x = 3 * x_vlaue;
                            to_y = -y_vlaue;
                        } else {
                            to_x = -x_vlaue;
                            to_y = 0;
                        }
                    } else {
                        //向右,下移到上,右移到左
                        holdPosition = dragPosition - i - 1;
                        if (dragPosition / mColumns == holdPosition / mColumns) {
                            to_x = x_vlaue;
                            to_y = 0;
                        } else if ((holdPosition + 1) % 4 == 0) {
                            to_x = -3 * x_vlaue;
                            to_y = y_vlaue;
                        } else {
                            to_x = x_vlaue;
                            to_y = 0;
                        }
                    }
  • 在动画结束的时候更新数据源 
    我们需要做的大概就是上面几部。那么,现在我们移动完了。

2.4 up事件的处理

由于这样的控件,百分之90可能会有数据联动,所以,我们需要在Up事件中回调通知其他的adapter数据源变化(注意,up事件很可能发生在多次动画之后)。

((BaseDragAdapter)getAdapter()).dragEnd();
                    requestDisallowInterceptTouchEvent(false);

恩,大概就这么多了。具体的大家看代码吧。

3. 结语

这个控件,我已经用在了开发当中,虽然,这个控件还存在一些问题,如adapter不能使用convertView and holder来优化等等。

github地址:DragGridView 求个star

以上是关于我的第一个开源控件-DragGridView的主要内容,如果未能解决你的问题,请参考以下文章

winform 界面全屏

Python Qt GUI设计:QTableViewQListViewQListWidetQTableWidgetQTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)(代码片

Python Qt GUI设计:QTableViewQListViewQListWidetQTableWidgetQTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)(代码片

为了能看到星星,我开源了一片星空——耶瞳星空

我的第一篇博文

如何将字节数组附加到Go中的字节片[重复]