我试图在Android上实现一个ListView子类,该子类允许手动重新排序其内容。作为该过程的第一步,我将向ListView绘制的每个子视图附加一个“长击”侦听器,例如:
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
//listen for long-click events as the trigger for reordering the list
child.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (! SortableListView.this.isSortEnabled()) {
return false;
}
//capture some state about the initial position of the list
//[...]
//note the view that we're moving around
dragView = view;
dragView.setBackgroundColor(Color.argb(128, 200, 200, 255));
dragView.setElevation(2.0f);
//disable the list's default scrolling behavior
SortableListView.this.requestDisallowInterceptTouchEvent(true);
return true;
}
});
//also add a general touch listener for when we're actually sorting things
child.setOnTouchListener(this);
return super.drawChild(canvas, child, drawingTime);
}然后还有一个通用的“触摸”事件侦听器,一旦我们实际拖动一些东西,就可以处理对ListView的更新:
@Override
public boolean onTouch(final View view, MotionEvent motionEvent) {
//XXX: (0,0) is at the top-left of the screen
if (dragView == null) {
//not dragging anything yet, just note the touch location for if/when we start
dragStartX = motionEvent.getRawX();
dragStartY = motionEvent.getRawY();
return false;
}
if (view != dragView) {
//not interested in this event
return false;
}
if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
dragCurrentX = motionEvent.getRawX();
dragCurrentY = motionEvent.getRawY();
//make the cell the user tapped follow their touch
dragView.animate().xBy(dragCurrentX - dragStartX).yBy(dragCurrentY - dragStartY).setDuration(0).start();
//now look at how far the view has moved, and reposition the displayed views if necessary (this is the broken part)
//[...]
return true;
}
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
//done, put the view back
dragView.setTranslationX(0);
dragView.setTranslationY(0);
dragView.setElevation(0.0f);
dragView = null;
//enable scrolling
this.requestDisallowInterceptTouchEvent(false);
return true;
}
return false;
}问题是,虽然拖曳视图通常有效,但我也想在它移动时将它的“占位符”位置上下移动。也许最好用一些照片来说明这一点:
初始状态

在开始拖动之后

拖动一点后的

因此,目标是让“占位符”单元格跟随浮动的蓝色单元格,用户将其拖过列表。当浮动单元格移动时,我试图通过操作列表的子视图来实现这一点,但是到目前为止,没有任何东西工作。
我当前用于尝试此操作的代码(即“破损部分”)是:
int dragViewIndex = this.indexOfChild(dragView);
if (dragView.getTranslationY() > dragView.getHeight() && dragViewIndex < this.getChildCount() - 1) {
//move down 1 spot (towards bottom of list), reduce tY by height
this.detachViewFromParent(dragView);
this.attachViewToParent(dragView, dragViewIndex + 1, dragView.getLayoutParams());
dragView.setTranslationY(dragView.getTranslationY() - dragView.getHeight());
}
if (dragView.getTranslationY() < -1 * dragView.getHeight() && dragViewIndex > 0) {
//move up 1 spot (towards top of list), reduce tY by height
this.detachViewFromParent(dragView);
this.attachViewToParent(dragView, dragViewIndex - 1, dragView.getLayoutParams());
dragView.setTranslationY(dragView.getTranslationY() + dragView.getHeight());
}但是,这似乎几乎什么也没有完成(除了混淆列表之外;正如您在第三张图片中看到的那样,在UI中拖动的条目实际上出现了两次)。
是否有适当的/优雅的方法使空单元格在列表中跟随内容?或者,我是否需要考虑更激烈的措施,比如可能翻译列表中的其他单元格,以适应空白处的位置?
发布于 2017-03-22 02:22:09
似乎我对翻译列表中其他单元格的想法是正确的。这个代码实现了我想要的结果:
if (dragView.getTranslationY() - dragView.getHeight() * numShifts > dragView.getHeight() && dragViewIndex < this.getChildCount() - 1) {
//move down 1 spot (towards bottom of list)
View displacedView = this.getChildAt(dragViewIndex + 1);
if (displacedView.getTranslationY() != 0) {
displacedView = this.getChildAt(dragViewIndex);
displacedView.animate().translationY(0).setDuration(100).start();
}
else {
displacedView.animate().yBy(-1 * view.getHeight()).setDuration(100).start();
}
dragViewIndex++;
numShifts++;
}
else if (dragView.getTranslationY() - dragView.getHeight() * numShifts < -1 * dragView.getHeight() && dragViewIndex > 0) {
//move up 1 spot (towards top of list)
View displacedView = this.getChildAt(dragViewIndex - 1);
if (displacedView.getTranslationY() != 0) {
displacedView = this.getChildAt(dragViewIndex);
displacedView.animate().translationY(0).setDuration(100).start();
}
else {
displacedView.animate().yBy(view.getHeight()).setDuration(100).start();
}
dragViewIndex--;
numShifts--;
}可能会被清理一下。但是基本上,您可以观察单元格被拖到多远,每次它向上/向下移动一个完整的增量(根据它的高度),您就会根据情况上下移动它下面的单元格。这将创建在列表中移动的“占位符”单元格的外观。
注意,只有当列表中的每个项目都具有相同的高度()时,此代码才能工作。这对我的用例来说已经足够好了,但并不适合每个用例。
https://stackoverflow.com/questions/42932737
复制相似问题