自定义 GridLayout 实现可拖拽的 GridView

转载请注明出处:https://blog.csdn.net/suprememjie/article/details/82465323

在项目中,如果有单独的一页来展示分类功能,经常会有一些交互的操作,比如长按拖拽某一个条目来调整位置、点击某一条目从当前列表中删除移入另一列表等。

看效果先:

自定义 GridLayout 实现可拖拽的 GridView_第1张图片

直接上代码:

public class DragGridLayout extends GridLayout {
    private List items;
    private int margin = 15;

    // 是否可以拖拽
    private boolean isCanDrag;
    // 记录被拖拽的View
    private View dragView;
    // 存放所有条目的矩形区域
    private List rects;

    public void setItems(List items) {
        this.items = items;
        for (int i = 0; i < items.size(); i++) {
            addGridItem(items.get(i));
        }
    }

    public void setCanDrag(boolean canDrag) {
        isCanDrag = canDrag;
        if (isCanDrag) {
            setOnDragListener(onDragListener);
        }
    }

    public DragGridLayout(Context context) {
        this(context, null);
    }

    public DragGridLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DragGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 给GridLayout添加item
     */
    public void addGridItem(String content) {
        TextView tv = new TextView(getContext());
        tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
        tv.setBackgroundResource(R.drawable.item_bg_selector);
        tv.setGravity(Gravity.CENTER);
        GridLayout.LayoutParams params = new GridLayout.LayoutParams();
        params.width = getResources().getDisplayMetrics().widthPixels / 4 - margin * 2;
        params.setMargins(margin, margin, margin, margin);
        tv.setLayoutParams(params);

        tv.setText(content);
        addView(tv);


        if (isCanDrag) {
            tv.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    dragView = view;
                    // 产生浮动的阴影效果
                    // 只有第二个参数有用,其他传空即可
                    view.startDrag(null, new View.DragShadowBuilder(view), null, 0);
                    // true 响应长按事件
                    return true;
                }
            });
        }
        // 设置条目的点击事件
        tv.setOnClickListener(onClickListener);
    }

    private OnDragListener onDragListener = new OnDragListener() {
        @Override
        public boolean onDrag(View view, DragEvent dragEvent) {
            switch (dragEvent.getAction()) {
                // 按下
                case DragEvent.ACTION_DRAG_STARTED:
                    dragView.setEnabled(false);
                    initRects();
                    break;
                // 移动
                case DragEvent.ACTION_DRAG_LOCATION:
                    int exchangeIndex = getExchangeIndex(dragEvent);
                    if (exchangeIndex > -1 && dragView != getChildAt(exchangeIndex)) {
                        removeView(dragView);
                        addView(dragView, exchangeIndex);
                    }
                    break;
                // 弹起
                case DragEvent.ACTION_DRAG_ENDED:
                    dragView.setEnabled(true);
                    break;
            }

            // true 响应拖拽事件
            return true;
        }
    };

    private void initRects() {
        rects = new ArrayList<>();
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            // 创建矩形
            Rect rect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
            rects.add(rect);
        }
    }

    /**
     * 获取要交换的位置下标
     *
     * @param dragEvent
     * @return
     */
    private int getExchangeIndex(DragEvent dragEvent) {
        for (int i = 0; i < rects.size(); i++) {
            Rect rect = rects.get(i);
            if (rect.contains((int) dragEvent.getX(), (int) dragEvent.getY())) {
                return i;
            }
        }
        return -1;
    }

    private OnClickListener onClickListener = new OnClickListener() {
        @Override
        public void onClick(View view) {
            if (onDragItemClickListener != null) {
                onDragItemClickListener.onDragItemClick((TextView) view);
            }
        }
    };

    //接口
    public interface OnDragItemClickListener {
        void onDragItemClick(TextView tv);
    }

    private OnDragItemClickListener onDragItemClickListener;

    public void setOnDragItemClickListener(OnDragItemClickListener onDragItemClickListener) {
        this.onDragItemClickListener = onDragItemClickListener;
    }
}

对于列表中的 item 是否可以拖拽、点击是否移进和移出列表都是可以从外部设置的,所以控件比较灵活。下面看下在 Activity 中的具体调用:

public class MainActivity extends AppCompatActivity {

    private DragGridLayout gridLayout1;
    private DragGridLayout gridLayout2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        gridLayout1 = findViewById(R.id.gridLayout1);
        gridLayout2 = findViewById(R.id.gridLayout2);

        gridLayout1.setCanDrag(true);
        List items = new ArrayList<>();
        items.add("明星");
        items.add("搞笑");
        items.add("情感");
        items.add("新时代");
        items.add("社会");
        items.add("电影");
        items.add("游戏");
        items.add("音乐");
        items.add("动漫");
        items.add("萌宠");
        gridLayout1.setItems(items);

        List items2 = new ArrayList<>();
        items2.add("汽车");
        items2.add("摄影");
        items2.add("国际");
        items2.add("数码");
        items2.add("财经");
        items2.add("股市");
        items2.add("读书");
        gridLayout2.setItems(items2);

        gridLayout1.setOnDragItemClickListener(new DragGridLayout.OnDragItemClickListener() {
            @Override
            public void onDragItemClick(TextView tv) {
                gridLayout1.removeView(tv);
                gridLayout2.addGridItem(tv.getText().toString());
            }
        });
        gridLayout2.setOnDragItemClickListener(new DragGridLayout.OnDragItemClickListener() {
            @Override
            public void onDragItemClick(TextView tv) {
                gridLayout2.removeView(tv);
                gridLayout1.addGridItem(tv.getText().toString());
            }
        });
    }
}

你可能感兴趣的:(Android日常)