【问题标题】:GridView with colspan and rowSpan带有 colspan 和 rowSpan 的 GridView
【发布时间】:2018-03-27 02:21:19
【问题描述】:

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

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

【问题讨论】:

标签: android gridview


【解决方案1】:

你可以试试:

https://github.com/askerov/DynamicGrid

希望对你的问题有所帮助!

【讨论】:

    【解决方案2】:

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

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

    这是演示视频:

    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;
        }
    }
    

    如果您稍微使用一下演示,您会发现可以移动瓷砖以打开 1x1 瓷砖间隙。这可能没问题,但如果不是,代码可能需要重新编写。

    【讨论】:

    • 您的程序的唯一问题是 1 没有调整大小,您将其拖动到第三行。
    • @Furqan GridLayout 是 3 列 x 5 行。我不清楚拖动到第三行时您期望的调整大小。你能进一步解释一下吗?
    • 我的意思是当你将数字 1 拖到任何位置时,数字 1 应该调整为正常大小,另一个数字替换数字的位置,将其大小更改为更大的。简而言之,位置 0 的数字大小保持不变,但其他数字可以在它们被放置到 0 时调整大小。
    • 拖动位置有什么解决办法吗..?我想检查拖动位置图像是否可用,然后我想放在那里,否则我不想放。
    • 你有演示吗?请分享我们
    猜你喜欢
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多