android - 带有 colspan 和 rowSpan 的 GridView

标签 android gridview

我一直在尝试制作一个具有拖放功能的 GridView 以及一个不同大小的单元格。我已经使网格拖放并且工作正常。您可以从 here 查看代码

my code output

但我希望它是这样的并且是纯动态的,因为我将拖放另一个将自动替换和调整大小的 desired output

最佳答案

更新了适应调整单元格大小的新代码。 你的问题是指 GridView 但你提供的代码没有提到 GridView 而是使用 GridLayout ,所以我假设 GridLayout 是正确的布局。

我使用带有一个 2x2 磁贴的模型布局制作了一个演示。我修改了您提供的代码以适应 2x2 磁贴。除了我为实现 2x2 磁贴而添加的代码外,对 MainAcitivity 的唯一其他更改是 calculateNextIndex 方法,该方法使用不同的方式计算 (x, y) 位置的索引。由于未提供布局和 LongPressListener 类,因此也进行了模拟。

这是演示视频:

enter image description here

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private static final int ITEMS = 10;
    private GridLayout mGrid;
    private ScrollView mScrollView;
    private ValueAnimator mAnimator;
    private Boolean isScroll = false;
    private GridLayout.Spec m1xSpec = GridLayout.spec(GridLayout.UNDEFINED, 1);
    private GridLayout.Spec m2xSpec = GridLayout.spec(GridLayout.UNDEFINED, 2);
    private int mBaseWidth;
    private int mBaseHeight;
    private int mBaseMargin;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mScrollView = (ScrollView) findViewById(R.id.scrollView);
        mScrollView.setSmoothScrollingEnabled(true);

        mGrid = (GridLayout) findViewById(R.id.grid);

        mGrid.setOnDragListener(new DragListener());

        final LayoutInflater inflater = LayoutInflater.from(this);

        GridLayout.LayoutParams lp;

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        float dpiToPx = displayMetrics.density;
        View view = inflater.inflate(R.layout.item, mGrid, false);
        lp = (GridLayout.LayoutParams) view.getLayoutParams();
        mBaseWidth = lp.width;
        mBaseHeight = lp.height;
        mBaseMargin = lp.rightMargin;

        for (int i = 0; i < ITEMS; i++) {
            final View itemView = inflater.inflate(R.layout.item, mGrid, false);
            final TextView text = (TextView) itemView.findViewById(R.id.text);
            text.setText(String.valueOf(i + 1));
            itemView.setOnLongClickListener(new LongPressListener());
            lp = (i == 0) ? make2x2LayoutParams(itemView) : make1x1LayoutParams(itemView);
            mGrid.addView(itemView, lp);
        }
    }

    private GridLayout.LayoutParams make2x2LayoutParams(View view) {
        GridLayout.LayoutParams lp = (GridLayout.LayoutParams) view.getLayoutParams();

        lp.width = mBaseWidth * 2 + 2 * mBaseMargin;
        lp.height = mBaseHeight * 2 + 2 * mBaseMargin;
        lp.rowSpec = m2xSpec;
        lp.columnSpec = m2xSpec;
        lp.setMargins(mBaseMargin, mBaseMargin, mBaseMargin, mBaseMargin);
        return lp;
    }

    private GridLayout.LayoutParams make1x1LayoutParams(View view) {
        GridLayout.LayoutParams lp = (GridLayout.LayoutParams) view.getLayoutParams();

        lp.width = mBaseWidth;
        lp.height = mBaseHeight;
        lp.setMargins(mBaseMargin, mBaseMargin, mBaseMargin, mBaseMargin);
        lp.rowSpec = m1xSpec;
        lp.columnSpec = m1xSpec;
        return lp;
    }

    private int mDraggedIndex;

    class DragListener implements View.OnDragListener {
        @Override
        public boolean onDrag(View v, DragEvent event) {
            final View view = (View) event.getLocalState();
            int index = calculateNextIndex(event.getX(), event.getY());
            View child;

            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    mDraggedIndex = index;
                    break;

                case DragEvent.ACTION_DRAG_LOCATION:
                    if (view == v) return true;
                    // get the new list index


                    final Rect rect = new Rect();
                    mScrollView.getHitRect(rect);
                    final int scrollY = mScrollView.getScrollY();

                    if (event.getY() - scrollY > mScrollView.getBottom() - 250) {
                        startScrolling(scrollY, mGrid.getHeight());
                    } else if (event.getY() - scrollY < mScrollView.getTop() + 250) {
                        startScrolling(scrollY, 0);
                    } else {
                        stopScrolling();
                    }

                    child = mGrid.getChildAt(0);
                    if (index == 0) {
                        child.setLayoutParams(make1x1LayoutParams(child));
                        view.setLayoutParams(make2x2LayoutParams(view));
                    } else if (mDraggedIndex == 0) {
                        view.setLayoutParams(make1x1LayoutParams(view));
                        child.setLayoutParams(make2x2LayoutParams(child));
                    } else {
                        child.setLayoutParams(make2x2LayoutParams(child));
                        view.setLayoutParams(make1x1LayoutParams(view));
                    }
                    mGrid.removeView(view);
                    mGrid.addView(view, index);
                    break;
                case DragEvent.ACTION_DROP:
                    for (int i = 0; i < mGrid.getChildCount(); i++) {
                        child = mGrid.getChildAt(i);
                        child.setLayoutParams(make1x1LayoutParams(child));
                    }
                    mGrid.removeView(view);
                    if (index == 0) {
                        view.setLayoutParams(make2x2LayoutParams(view));
                    }
                    mGrid.addView(view, index);
                    view.setVisibility(View.VISIBLE);
                    mGrid.getChildAt(0).setLayoutParams(make2x2LayoutParams(mGrid.getChildAt(0)));
                    break;
                case DragEvent.ACTION_DRAG_ENDED:
                    if (!event.getResult()) {
                        view.setVisibility(View.VISIBLE);
                    }
                    break;
            }
            return true;
        }
    }

    private void startScrolling(int from, int to) {
        if (from != to && mAnimator == null) {
            isScroll = true;
            mAnimator = new ValueAnimator();
            mAnimator.setInterpolator(new OvershootInterpolator());
            mAnimator.setDuration(Math.abs(to - from));
            mAnimator.setIntValues(from, to);
            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    mScrollView.smoothScrollTo(0, (int) valueAnimator.getAnimatedValue());
                }
            });
            mAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    isScroll = false;
                    mAnimator = null;
                }
            });
            mAnimator.start();
        }
    }

    private void stopScrolling() {
        if (mAnimator != null) {
            mAnimator.cancel();
        }
    }

    private int calculateNextIndexOld(float x, float y) {
        // calculate which column to move to
        final float cellWidth = mGrid.getWidth() / mGrid.getColumnCount();
        final int column = (int) (x / cellWidth);

        final float cellHeight = mGrid.getHeight() / mGrid.getRowCount();
        final int row = (int) Math.floor(y / cellHeight);

        int index = row * mGrid.getColumnCount() + column;
        if (index >= mGrid.getChildCount()) {
            index = mGrid.getChildCount() - 1;
        }
        Log.d("MainActivity", "<<<<index=" + index);
        return index;
    }

    private int calculateNextIndex(float x, float y) {
        // calculate which column to move to
        int index;

        for (index = 0; index < mGrid.getChildCount(); index++) {
            View child = mGrid.getChildAt(index);
            Rect rect = new Rect();
            child.getHitRect(rect);
            if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
                break;
            }
        }
        if (index >= mGrid.getChildCount()) {
            // Move into empty cell? Calculate based upon uniform cell sizes.
            index = calculateNextIndexOld(x, y);
        }
        if (index >= mGrid.getChildCount()) {
            // Can't determine where to put it? Add it to the end.
            index = mGrid.getChildCount() - 1;
        }
        return index;
    }
}

如果您稍加研究演示,您会发现可以移动图 block 以打开 1x1 的图 block 间隙。这可能没问题,但如果不行,代码可能需要稍微修改一下。

关于android - 带有 colspan 和 rowSpan 的 GridView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46755465/

相关文章:

android - 是否可以同时调试 UI App 和 AAR?

android - 每当打开 AlertDialog.Builder 对象时显示软键盘

android - ViewPager addOnPageChangeListener 不能在同一个选项卡上工作单击

android - 如何使用自定义 BaseAdapter 在 Android 中选择/取消选择 gridView 项目时显示/隐藏布局

c# - 如何在 Checkbox.checked 上从 Gridview 获取 Id?

android - 我可以使用 gridview 元素,比如一张图片,然后是字符串,然后是复选框,如何使用?

c# - 将复选框列添加到 asp.net gridview

java - retrofit2 在 onFailure() 中获取 responseBody

android - 如何使用 openRawResource Fd()?

android - 在 GridView 中混合 ImageView 和 VideoView