首页 > 代码库 > 自定义GridLayout实现条目的拖动动画特效

自定义GridLayout实现条目的拖动动画特效

1、自定义GridLayout实现增加条目过度动画操作

public class MyGridLayout extends GridLayout {
        public MyGridLayout(Context context) {
            //super(context);
            this(context,null);
        }
        public MyGridLayout(Context context, AttributeSet attrs) {
            //super(context, attrs);
            this(context,attrs,-1);
        }
        public MyGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            // 设置 GridLayout 中的条目增加过渡动画***********************
            this.setLayoutTransition(new LayoutTransition());
        }
    }

2、创建条目

private void addTextView(String string) {
        TextView textView = new TextView(getContext());
        textView.setText(string);
        textView.setTextColor(Color.BLACK);
        textView.setBackgroundResource(R.drawable.shape_selecitem_black_bg);
        textView.setGravity(Gravity.CENTER);
        textView.setPadding(15, 5, 15, 5);
        GridLayout.LayoutParams params = new LayoutParams();
        params.setMargins(5, 5, 5, 5);
        // 设置 params 给 TextView, 使用 margins 效果生效
        textView.setLayoutParams(params);
        // 将 textview 添加 Gridlayout 中展示
        this.addView(textView);
    }

3、拖拽效果的实现

    3.1 设置条目的长按事件

  

public void addTextView(String string) {
            ....
            // 设置 textview 的长按事件,实现拖拽效果
            textView.setOnLongClickListener(longClickListener);
            // 将 textview 添加 Gridlayout 中展示
            this.addView(textView);
        }

  3.2 长按事件中实现拖拽效果 

  

private OnLongClickListener longClickListener = new OnLongClickListener() {
            // 长按控件调用的方法
            // 参数:被长按的控件
            @Override
            public boolean onLongClick(View v) {
            // 设置控件开始拖拽
            // 参数 1 :拖拽要显示的数据,一般 null
            // 参数 2 :拖拽显示的阴影样式 ,DragShadowBuilder(v): 根据拖拽的控件,设置拖拽阴影的样式效果
            // 参数 3 :拖拽的控件的状态,一般 null
            // 参数 4 :拖拽的其他设置的标示,一般 0
            v.startDrag(null, new DragShadowBuilder(v), null, 0);
            // 返回 true 表示处理长按事件, false 就是不处理
            return true;
            }
        };

4、拖拽移动操作的实现

核心理念:根据 textview 创建矩形,矩形中包含有原先 textview 的左上角和右下角的坐标,移动的时候,判断按下的坐标是否在矩形的坐标内,如果在就说明移动到了相应的矩形的位置,也就是相应的 textview 的位置

/** 拖拽监听操作 **/
    private OnDragListener dragListener = new OnDragListener() {
        // 当拖拽操作执行的时候调用的方法
        // 参数 1 :拖拽的控件
        // 参数 2 :拖拽的事件
        @Override
        public boolean onDrag(View v, DragEvent event) {
            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:// 开始拖拽
                    System.out.println(" 开始拖拽 ");
                    // 根据 textview 创建矩形
                    createRect();
                break;
                case DragEvent.ACTION_DRAG_ENTERED:// 开始拖拽控件后,进入拖拽控件范围事件
                    System.out.println(" 进入拖拽控件范围 ");
                break;
                case DragEvent.ACTION_DRAG_EXITED:// 开始拖拽控件后,离开拖拽控件范围事件
                    System.out.println(" 离开拖拽控件范围 ");
                break;
                case DragEvent.ACTION_DRAG_LOCATION:// 开始拖拽控件后,移动控件或者是拖拽控件执行的操作
                    System.out.println(" 拖拽控件移动 ");
                    // 根据拖拽的按下的坐标,获取拖拽控件移动的位置
                    int index = getIndex(event);
                    //MyGridLayout.this.getChildAt(index) != currentView :  判断移动到位置的 textview 和拖拽的 textview 是否一致,一致不进行移动,不一致进行移动操作
                    if (index != -1 && currentView != null && MyGridLayout.this.getChildAt(index) != currentView) {
                        // 实现 Gridlayout 的移动操作
                        // 将原来位置的拖拽的特性 tview 删除
                        MyGridLayout.this.removeView(currentView);
                        // 将拖拽的 textview 添加到移动的位置
                        MyGridLayout.this.addView(currentView, index);// 将 view 对象,添加到那个位置
                    }
                break;
                case DragEvent.ACTION_DRAG_ENDED:// 结束拖拽
                    System.out.println(" 结束拖拽 ");
                    // 设置拖拽的 textview 背景改为黑色边框的背景
                    if (currentView != null) {
                        currentView.setEnabled(true);
                    }
                break;
                case DragEvent.ACTION_DROP:// 结束拖拽,在控件范围内,松开手指,在控件范围外不执行操作
                    System.out.println(" 松开手指 ");
                break;
            }
            return true;
        }
    };
    /**
    *  根据 textview 创建矩形
    *
    * 2016 年 12 月 30 日 上午 11:44:08
    */
    protected void createRect() {
        //getChildCount() :  获取 Gridlayout 的子控件的个数
        rects = new Rect[this.getChildCount()];
        // 根据孩子的个数,创建相应个数的矩形
        for (int i = 0; i < this.getChildCount(); i++) {
        // 根据子控件的索引,获取子控件的 view 对象
        View view = this.getChildAt(i);
        // 创建一个矩形
        // 参数 1,2 :左上角的 x 和 y 的坐标
        // 参数 3,4 :右下角的 x 和 y 的坐标
        Rect rect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
        // 保存到就行到数组中
        rects[i] = rect;
        }
    }
    /**
    *  根据拖拽按下的坐标,获取拖拽控件移动的位置
    *
    * 2016 年 12 月 30 日 上午 11:50:20
    */
    protected int getIndex(DragEvent event) {
        for (int i = 0; i < rects.length; i++) {
            // 判断按下的坐标是否包含在矩形的坐标范围内容
            if (rects[i].contains((int)event.getX(), (int)event.getY())) {
                return i;
            }
        }
        return -1;
    }

 

自定义GridLayout实现条目的拖动动画特效