我想实现一个允许用户将项目拖出的Gallery.这不应该妨碍滚动/投掷.
给定界面布局,用户只能在垂直路径中将项目拖出画廊,并水平滚动图库.
这可行吗?有没有一种简单的方法来检测水平移动,并将它们推迟到画廊的事件处理程序,并拦截垂直移动?或者我是否必须重写onInterceptTouchEvent()并自己进行数学运算?
(编辑:我正在尝试使用GestureListener,覆盖onFling和onScroll,并在垂直滚动距离低于阈值时将事件传递给Gallery)
解决方法:
我继承了Gallery,并覆盖了onScroll方法.我还没有实现drop逻辑,但是拖动和滚动工作.
当我可以节省时间时,我会在我的博客中写一篇完整的帖子,其中包含更多细节和丢弃机制.现在,一个简单的复制粘贴,以防将来某人到达此页面.
为了保持它所属的行为,我创建了这个DraggableView接口:
public interface DraggableView {
public void beforeDrag();
public DragView createDragView();
public Object getDraggedInfo();
public void afterDrop();
}
如果实现此视图,则可以将“库”中的视图拖出“库”区域.他们会在之前和之后得到通知,并且必须实现两种方法:
> createDragView()返回一个DragView对象.基本上,一个透明的悬停位图伴随着用户的运动.
> getDraggedInfo()返回应该到达放置目标的信息.
这是DragView类:
public class DragView extends ImageView {
private final LayoutParams mLayoutParams;
public DragView(Context context, Bitmap bitmap) {
super(context);
mLayoutParams = new LayoutParams();
mLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
mLayoutParams.height = LayoutParams.WRAP_CONTENT;
mLayoutParams.width = LayoutParams.WRAP_CONTENT;
mLayoutParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_NOT_TOUCHABLE;
mLayoutParams.format = PixelFormat.TRANSLUCENT;
mLayoutParams.windowAnimations = 0;
mLayoutParams.alpha = 0.5f;
setImageBitmap(bitmap);
setLayoutParams(mLayoutParams);
}
public void move(int x, int y) {
mLayoutParams.x = x;
mLayoutParams.y = y;
}
}
如您所见,它构建了一个Bitmap,并创建了一个悬停的ImageView.最后,这里是(刚刚实现的并不是很干净的)Gallery代码,以实现这一切:
public class DraggableItemGallery extends Gallery {
private boolean mDragging;
private DragView mDragView;
private DraggableView mDragViewOwner;
private WindowManager mWindowManager;
private boolean mScrollStarted;
public DraggableItemGallery(Context context) {
super(context);
initialize();
}
public DraggableItemGallery(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public DraggableItemGallery(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
public void initialize() {
mWindowManager = (WindowManager)
getContext().getSystemService("window");
}
private void startDraggingItem(DraggableView view, int x, int y) {
mDragging = true;
mDragViewOwner = view;
mDragView = view.createDragView();
mDragView.move(x, y);
mWindowManager.addView(mDragView, mDragView.getLayoutParams());
}
private void continueDraggingItem(int x, int y) {
DragView dragView = getDragView();
dragView.move(x, y);
mWindowManager.updateViewLayout(dragView, dragView.getLayoutParams());
}
private void stopDraggingItem() {
mDragging = false;
mWindowManager.removeView(mDragView);
mDragViewOwner.afterDrop();
mDragView = null;
mDragViewOwner = null;
}
private DraggableView getDraggedItem() {
return mDragViewOwner;
}
private DragView getDragView() {
return mDragView;
}
private boolean isDraggingItem() {
return (mDragging);
}
private void setScrolling(boolean scrolling) {
mScrollStarted = scrolling;
System.out.println("Scrolling " + scrolling);
}
private boolean isScrolling() {
return mScrollStarted;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if ((event.getAction() & ACTION_MASK) == ACTION_UP) {
setScrolling(false);
if (isDraggingItem())
stopDraggingItem();
}
return super.onTouchEvent(event);
}
final Rect onScroll_tempRect = new Rect();
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (isScrolling()) {
if (isDraggingItem()) {
int x = (int) e2.getX(),
y = (int) e2.getY();
System.out.println("Moving to " + x + " " + y);
continueDraggingItem(x, y);
return true;
} else {
/* Not dragging, let the Gallery handle the event */
return super.onScroll(e1, e2, distanceX, distanceY);
}
} else {
setScrolling(true);
boolean isVertical = (Math.abs(distanceY) > Math.abs(distanceX));
if (isVertical) {
int x = (int) e1.getX(),
y = (int) e1.getY();
View hitChild = null;
// A tiny optimization, declared above this method
final Rect hitRect = onScroll_tempRect;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.getHitRect(hitRect);
if (hitRect.contains(x, y)) {
hitChild = child;
break;
}
}
if (hitChild instanceof DraggableView) {
startDraggingItem((DraggableView) hitChild, x, y);
return true;
}
}
/* Either the scroll is not vertical, or the point
* of origin is not above a DraggableView. Again,
* we let the Gallery handle the event.
*/
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
}
希望能帮助到你.