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

标签 android android-layout touch android-gridview

我有一个 3x3 GridView 。想象如下。

1 2 3
4 5 6
7 8 9

现在我想要实现什么

我希望 GridView 的列在触摸时上下移动。

考虑一下, GridView 的第一列。也就是

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

最佳答案

要完成您的要求,您需要负责 GridView 的 Canvas ,将被触摸的列分隔开,并为拖动、滑动等进行您自己的绘图。一旦移动完成后,您将需要通过 GridView 对列中的 View 进行调整,以保持簿记正常。我会查看讨论 View 移动的在线文档。 "Dragging and Scaling"将是一个很好的起点。

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

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

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


我很好奇如何实现我的建议。下面是一个示例应用程序,其中包含如上所述的三个 GridView 实现以及相同的视频。

enter image description here

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_width="wrap_content"
    android:layout_height="wrap_content"
    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_width="150px"
        android:layout_height="1050px"
        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_width="150px"
        android:layout_height="1050px"
        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_width="150px"
        android:layout_height="1050px"
        android:columnWidth="150px"
        android:horizontalSpacing="0dp"
        android:numColumns="1"
        android:scrollbars="none"
        android:tag="2"
        android:verticalSpacing="0dp" />
</LinearLayout>

关于android - 在触摸该列时上下移动 Gridview 的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45431096/

相关文章:

Android:将字符串转换为整数

android - AppInvite.AppInviteApi.getInvitation() 已弃用

java - 如果我在 Android 中使用 SSLSocket 并将密码硬编码到源代码中的信任库,那不安全吗?

JavaFX TextField focusProperty 在 touchScrollEvent 上丢失

java - 将 phonegap 的 R.java 导入我的插件?

android - 从android存储器中选择图像进入android-crop库时,图像会旋转?

java - Spinner String 项目值获取(不是字符串名称)android

android - 如何在android中以全屏模式显示电池图标和Wifi图标?

jquery - First and Second touch a button,如何显示不同时间的图像?

ios - swift 中的 addsubview 命令后动画未运行