我想在应用程序的顶部有 1 行项目,在每个框内都会有一个图标或一个字母。您可以按任何顺序水平排列它们。真的很容易交换,不像按住然后移动。我会为此使用什么样的控件?
1 回答
首先让我澄清一下任务。您是否只需要水平列表中的一组预定义项目(选项 A)?
或带有滚动的水平列表(选项 B):
让我们假设一下option A
是相关的,所以你需要:
- 横向列表实现
- 正确的拖放处理
步骤1
有几种可用的水平列表实现,但其中一些是旧的并且不受支持,所以我建议检查Horizontal Variable ListView:
Android 的水平列表视图。基于官方 ListView 谷歌代码。它支持 ListView 小部件的几乎所有功能。支持的属性有细微差别,例如“dividerWidth”而不是默认的“dividerHeight”。
顺便说一句,它支持Android 4.2.2
,请参阅演示示例。
第2步
此时您真正需要的只是正确处理拖放操作。
最简单的解决方案是遵循标准且众所周知的示例:音乐应用程序中使用的TouchInterceptor 类。它扩展,因此使用与Horizontal Variable ListViewListView
相同的方法应该不是问题。
特别注意:
public boolean onInterceptTouchEvent(MotionEvent ev) {
和
public boolean onTouchEvent(MotionEvent ev) {
第 3 步:高级实施
个人认为option A
只能作为demo使用,所以还要解决滚动问题。上面的示例显示了如何处理滚动,但可能需要更多。
还有另一个项目(再次停产)可以用作高级示例,因为它解决了几个问题,支持动画等:
DragSortListView (DSLV)是 Android ListView 的扩展,可以对列表项进行拖放重新排序。这是对 TouchInterceptor (TI) 的一次重大彻底改写,旨在为拖拽排序提供优雅的感觉。一些主要特点是:
- 干净的拖放
- 拖动时直观流畅的滚动。
- 支持异构项目高度。
- 公共 startDrag() 和 stopDrag() 方法。
- 自定义浮动视图的公共接口。
DragSortListView 对各种优先列表都很有用:收藏夹、播放列表、清单等。
它似乎有据可查且易于理解。从垂直模式切换到水平模式应该没有那么难。
public class DragSortListView extends ListView {
/**
* The View that floats above the ListView and represents
* the dragged item.
*/
private View mFloatView;
/**
* The float View location. First based on touch location
* and given deltaX and deltaY. Then restricted by callback
* to FloatViewManager.onDragFloatView(). Finally restricted
* by bounds of DSLV.
*/
private Point mFloatLoc = new Point();
private Point mTouchLoc = new Point();
/**
* The middle (in the y-direction) of the floating View.
*/
private int mFloatViewMid;
/**
* Flag to make sure float View isn't measured twice
*/
private boolean mFloatViewOnMeasured = false;
/**
* Watch the Adapter for data changes. Cancel a drag if
* coincident with a change.
*/
private DataSetObserver mObserver;
/**
* Transparency for the floating View (XML attribute).
*/
private float mFloatAlpha = 1.0f;
private float mCurrFloatAlpha = 1.0f;
/**
* While drag-sorting, the current position of the floating
* View. If dropped, the dragged item will land in this position.
*/
private int mFloatPos;