我有一个 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
实现以及相同的视频。
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/