在触摸该列时上下移动 Gridview 的列

Posted

技术标签:

【中文标题】在触摸该列时上下移动 Gridview 的列【英文标题】:Shift column of Gridview up and down on touch on that column 【发布时间】:2018-01-07 22:09:57 【问题描述】:

我有一个 3x3 的网格视图。想象如下。

1 2 3
4 5 6
7 8 9

现在我想要实现的目标

我希望网格视图的列在触摸时向上和向下移动。

考虑一下,网格视图的第一列。那是

1
4
7

现在,如果我触摸此列上的任何位置,无论是在 1、4 或 7 上,然后在任何一个方向(例如向上或向下)滑动。然后我想将列移动 1 或 2 个位置。

让我澄清一下

如果我通过触摸 7 向上滑动。结果应该是这样的

1
4 2 3
7 5 6 
  8 9

或者,如果我触摸第二列并将其向下移动,那么它将看起来像下面的东西

1   3
4 2 6
7 5 9
  8

如果我移动 2 个网格单元的列,那么它看起来像

1   3
4   6
7 2 9
  5
  8

对于每一列,我应该能够将列移动一到两个单元格,具体取决于我滚动列的程度。

还有一件事如果我稍微滚动列并且如果它不完全适合任何网格单元到所需位置,那么它应该自动适合接近适合位置的网格单元。

我在这里搜索了太多关于堆栈溢出的问题并查询了很多谷歌。但我没有得到我真正想要的。

如果我解释得不好,请告诉我。我将尝试解释更多。 任何想法、任何提示或任何技巧都将是可观的。

编辑

如果我将列移动超过 3 个网格,然后在释放触摸时,列将变为 仅两个元素。就这样

1   3
4   6
7 2 9
  5
  8

【问题讨论】:

它必须是 3x3 GridView 还是其他类似 3 1x3 GridView 的东西,每个都可以上下滚动?这将更容易实现,但可能需要更多的幕后工作。 @Cheticamp 没有任何尺寸的网格视图。这里 3x3 只是我用来说明的一个例子。是的,我绝对知道这需要更多的工作。 【参考方案1】:

要按照您的要求进行操作,您需要负责GridView 的画布,将被触摸的列分开,并为拖动、甩动等进行自己的绘图。一旦移动完成,您将需要通过GridView对栏目中的视图进行调整,保持簿记平顺。我会查看讨论视图移动的在线文档。 "Dragging and Scaling" 将是一个不错的起点。

这种方法会有一些“陷阱”。如果您只是想将其作为一种技术来学习,那么我会说您的方法还可以。如果您想完成效果并按设计使用GridView 的底层实现(滚动、边缘效果、弹跳等),我建议另一种方法。

您可以通过并排对齐三个 1x3 网格视图来构建 GridView 的外观,而不是单个 3x3 GridView。 (实际上,网格视图将是 1x11 以适应垂直幻灯片的最大范围。)如果编码为支持多个网格视图,则每个网格视图都可以由单个适配器支持。由于每一列都有自己的网格视图,因此每一列都可以独立滑动。

这种方法的优点是您可以在不扭曲底层GridView 类的情况下获得您想要的效果。同样的方法可以使用您现有的使用按钮的方法。


我很好奇如何实施我的建议。下面是一个示例应用程序,上面解释了三个GridView 实现以及相同的视频。

MainActivity.java

public class MainActivity extends AppCompatActivity
        implements GridView.OnScrollListener 

    @Override
    public void onCreate(Bundle savedInstanceState) 
        final GridViewAdapter adapter = new GridViewAdapter();

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupGridView(R.id.gridview0, adapter);
        setupGridView(R.id.gridview1, adapter);
        setupGridView(R.id.gridview2, adapter);
    

    private void setupGridView(int id, GridViewAdapter adapter) 
        final GridView gridview = (GridView) findViewById(id);

        gridview.setAdapter(adapter);
        // Temporary scroll listener until initial scroll to position is done.
        // This hides the initial movement of the grid cells.
        gridview.setOnScrollListener(new AbsListView.OnScrollListener() 
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) 
                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) 
                    gridview.setOnScrollListener(MainActivity.this);
                
            

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) 
                // Do nothing
            
        );
        gridview.smoothScrollToPositionFromTop(2, 0);
    

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) 
        if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) 
            final int top = view.getChildAt(0).getTop();
            final int itemHeight = ((GridViewAdapter) (view.getAdapter())).getItemHeight();

            // top <= 0
            if (top > -(itemHeight / 2)) 
                // Less than 1/2 cell height out of place - shift down.
                view.scrollListBy(top);
             else 
                // Shift up
                view.scrollListBy(top + itemHeight);
            
        
    

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) 
        // Do nothing
    

    @SuppressWarnings("unused")
    private static final String TAG = "MainActivity";

GridViewAdapter.java

class GridViewAdapter extends BaseAdapter 

    GridViewAdapter() 
    

    @Override
    public int getCount() 
        return mStrings.length / GRID_COLUMN_COUNT;
    

    @Override
    public Object getItem(int position) 
        return null;
    

    @Override
    public long getItemId(int position) 
        return 0;
    

    // create a new TextView for each item referenced by the Adapter
    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        TextView textView;
        final int column = Integer.parseInt((String) parent.getTag());

        if (convertView == null) 
            // if it's not recycled, initialize some attributes
            textView = new TextView(parent.getContext());
            GridView.LayoutParams params =
                    new GridView.LayoutParams(GRID_ITEM_WIDTH, GRID_ITEM_HEIGHT);
            textView.setLayoutParams(params);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
            textView.setGravity(Gravity.CENTER);
         else 
            // Recycle the view but keep old attributes since they don't change.
            textView = (TextView) convertView;
        
        textView.setText(mStrings[position * GRID_COLUMN_COUNT + column]);
        return textView;
    

    int getItemHeight() 
        return GRID_ITEM_HEIGHT;
    

    private final static String[] mStrings = 
            "", "", "",
            "", "", "",
            "", "", "",
            "", "", "",
            "1", "2", "3",
            "4", "5", "6",
            "7", "8", "9",
            "", "", "",
            "", "", "",
            "", "", "",
            "", "", ""
    ;

    private static final int GRID_ITEM_HEIGHT = 150; // in pixels
    private static final int GRID_ITEM_WIDTH = 150; // in pixels
    private static final int GRID_COLUMN_COUNT = 3;


activity_main.java

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:orientation="horizontal">

    <!-- Sorry for the dimensions in pixels. It just makes everything easier.
    Non-pixel dimensions (dp) should be used here and accommodations made in the code. -->

    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/gridview0"
        android:layout_
        android:layout_
        android:columnWidth="150px"
        android:horizontalSpacing="0dp"
        android:numColumns="1"
        android:scrollbars="none"
        android:tag="0"
        android:verticalSpacing="0dp" />

    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/gridview1"
        android:layout_
        android:layout_
        android:columnWidth="150px"
        android:horizontalSpacing="0dp"
        android:numColumns="1"
        android:scrollbars="none"
        android:tag="1"
        android:verticalSpacing="0dp" />

    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/gridview2"
        android:layout_
        android:layout_
        android:columnWidth="150px"
        android:horizontalSpacing="0dp"
        android:numColumns="1"
        android:scrollbars="none"
        android:tag="2"
        android:verticalSpacing="0dp" />
</LinearLayout>

【讨论】:

【参考方案2】:

如果我将列移动超过 3 个网格单元格,那么它是否会移动。如果它移动了它移动了多少个单元格?

【讨论】:

blahti.wordpress.com/2011/10/03/drag-drop-for-android-gridview 如果不行,试试这个我可以构建代码 我已经检查了上面的链接,但它只是拖放网格的一个单元格。但我的要求有点不同。我想在触摸时移动gridview的特定列。拖放机制有些不同,我不希望这样。顺便感谢您的努力【参考方案3】:

我没有任何代码块,但我可以解释你如何完成这样的任务

你需要用这样的空单元格创建一个网格

第一个 -> - - - - - - - - -

第二个 -> - - - - - - - - -

3rd -> - - - - - - - -

4th -> - - - 1 2 3 - - -

5th -> - - - 4 5 6 - - -

6th -> - - - 7 8 9 - - -

7th -> - - - - - - - -

8th -> - - - - - - - -

9th -> - - - - - - - -

现在向上滑动获取同一列的所有元素,然后移动到上层

【讨论】:

是的。你说的对。我应该添加一个空单元格。我确实做到了。放置了 2 个箭头按钮来向下和向上移动一列。一切正常,完全按照我的意愿工作。但我想实现对网格列的触摸。现在我在点击按钮时这样做,现在我想要与触摸相同的功能 刷卡:***.com/questions/4139288/…

以上是关于在触摸该列时上下移动 Gridview 的列的主要内容,如果未能解决你的问题,请参考以下文章

在网格 xcode 中移动球

仅展开单击的列

GridView 在触摸时获取项目

在 ag-grid 中编辑后行移到顶部

【Axure】触摸屏上下滑动效果

隐藏列时如何保留表格列的宽度?