Tôi muốn triển khai thư viện cho phép người dùng kéo các mục ra khỏi thư viện đó. Điều này sẽ không cản trở việc cuộn/vuốt.
Với cách bố trí giao diện, người dùng chỉ có thể kéo các mục ra khỏi thư viện theo đường dọc và cuộn thư viện theo chiều ngang.
Điều này có thể thực hiện được không? Có cách nào dễ dàng để phát hiện các chuyển động theo chiều ngang, trì hoãn chúng cho trình xử lý sự kiện của thư viện và chặn các chuyển động theo chiều dọc không? Hay tôi phải viết lại onInterceptTouchEvent()
Và tự mình tính toán?
(Chỉnh sửa: Tôi đã thử sử dụng GestureListener, ghi đè onFling và onScroll, đồng thời chuyển sự kiện đến thư viện khi khoảng cách cuộn dọc giảm xuống dưới ngưỡng)
Tôi đã kế thừa Thư viện và ghi đè phương thức onScroll. Tôi chưa triển khai logic kéo và thả nhưng thao tác kéo và cuộn đã hoạt động.
Khi có thời gian, tôi sẽ viết một bài đầy đủ trên blog của mình trình bày chi tiết về cơ chế thả. Bây giờ, bạn có thể sao chép đơn giản và dán phòng trường hợp có người truy cập trang này trong tương lai.
Để duy trì hành vi ở đúng nơi, tôi đã tạo giao diện DraggableView này:
giao diện công cộng DraggableView {
khoảng trống công khai beforeDrag();
công khai DragView createDragView();
Đối tượng công khai getDraggedInfo();
khoảng trống công khai afterDrop();
}
Xem trong Thư viện Nếu Chế độ xem này được triển khai, bạn có thể kéo ra khỏi khu vực thư viện. Họ được thông báo trước và sau và phải thực hiện hai phương pháp:
createDragView()
Trả về đối tượng DragView. Về cơ bản, một bitmap di chuột trong suốt đi kèm với chuyển động của người dùng.
getDraggedInfo()
Trả về thông tin cần đạt được mục tiêu thả.
Đây là lớp DragView:
lớp công khai DragView mở rộng ImageView {
cuối cùng riêng tư LayoutParams mLayoutParams;
public DragView(Ngữ cảnh, bitmap bitmap) {
siêu (bối cảnh);
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;
}
}
Như bạn có thể thấy, phải mất mộtBản đồ bit
, và tạo một di chuộtXem hình ảnh
. Cuối cùng, đây là mã thư viện giúp thực hiện điều này (mới được triển khai nhưng chưa rõ ràng lắm):
lớp công khai DraggableItemGallery mở rộng Thư viện {
mDragging boolean riêng tư;
mDragView riêng tư của DragView;
riêng tư DraggableView mDragViewOwner;
WindowManager riêng tư mWindowManager;
mScrollStarted boolean riêng tư;
công khai DraggableItemGallery(Ngữ cảnh bối cảnh) {
siêu (bối cảnh);
khởi tạo();
}
public DraggableItemGallery(Context context, Attrs Attrs) {
super(bối cảnh, attrs);
khởi tạo();
}
public DraggableItemGallery(Context context, AttrsAttrs, int defStyle) {
super(bối cảnh, attrs, defStyle);
khởi tạo();
}
khoảng trống công khai khởi tạo() {
mWindowManager = (WindowManager)
getContext().getSystemService("window");
}
void void startDraggingItem(Chế độ xem DraggableView, int x, int y) {
mKéo = đúng;
mDragViewOwner = lượt xem;
mDragView = view.createDragView();
mDragView.move(x, y);
mWindowManager.addView(mDragView, mDragView.getLayoutParams());
}
khoảng trống riêng tư continueDraggingItem(int x, int y) {
DragView dragView = getDragView();
dragView.move(x, y);
mWindowManager.updateViewLayout(dragView, dragView.getLayoutParams());
}
khoảng trống riêng tư stopDraggingItem() {
mKéo = sai;
mWindowManager.removeView(mDragView);
mDragViewOwner.afterDrop();
mDragView = null;
mDragViewOwner = null;
}
riêng tư DraggableView getDraggedItem() {
trả về mDragViewOwner;
}
riêng tư DragView getDragView() {
trả về mDragView;
}
boolean riêng tư isDraggingItem() {
trở lại (mDragging);
}
void void setScrolling(cuộn boolean) {
mScrollStarted = cuộn;
System.out.println("Cuộn " + cuộn);
}
boolean riêng tư isScrolling() {
trả về mScrollStarted;
}
@Ghi đè
boolean công khai onTouchEvent(sự kiện MotionEvent) {
if ((event.getAction() & ACTION_MASK) == ACTION_UP) {
setScrolling(false);
nếu (isDraggingItem())
stopDraggingItem();
}
trả về super.onTouchEvent(sự kiện);
}
Rect cuối cùng onScroll_tempRect = new Rect();
@Ghi đè
boolean công khai onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
nếu (isScrolling()) {
nếu (isDraggingItem()) {
int x = (int) e2.getX(),
y = (int) e2.getY();
System.out.println("Di chuyển tới " + x + " " + y);
continueDraggingItem(x, y);
trả về đúng sự thật;
} khác {
/* Không kéo, để Gallery xử lý sự kiện */
trả về super.onScroll(e1, e2, distanceX, distanceY);
}
} khác {
setScrolling(true);
boolean isVertical = (Math.abs(distanceY) > Math.abs(distanceX));
nếu (isVertical) {
int x = (int) e1.getX(),
y = (int) e1.getY();
Xem hitChild = null;
// Một sự tối ưu hóa nhỏ, được khai báo ở trên phương thức này
cuối cùng Rect hitRect = onScroll_tempRect;
for (int i = 0; i < getChildCount(); i++) {
Xem con = getChildAt(i);
child.getHitRect(hitRect);
if (hitRect.contains(x, y)) {
hitChild = con;
phá vỡ;
}
}
if (hitChild instanceof DraggableView) {
startDraggingItem((DraggableView) hitChild, x, y);
trả về đúng sự thật;
}
}
/* Cuộn không thẳng đứng hoặc điểm
* nguồn gốc không nằm trên DraggableView Một lần nữa,
* chúng tôi để Thư viện xử lý sự kiện này.
*/
trả về super.onScroll(e1, e2, distanceX, distanceY);
}
}
}
Hy vọng điều này sẽ giúp.
Tôi là một lập trình viên xuất sắc, rất giỏi!