Reputation: 1036
I want to implement a layout where I can drag an image and drop it to another screen similar to android launcher where we can place the app icons anywhere on a set of screens scrolling horizontally. I am not sure how to start and where to start. I am thinking of implementing a layout that would be larger than screen and then start autoscrolling as soon as the user touches the image.The position of dropping the image will be fixed. Any references or better approach to implement this?
Upvotes: 1
Views: 2214
Reputation: 11
I just wrote this: (its working for the time being)
Just addDragListener only on ViewPager. You don't need to addDragListener on gridviews.
Get Position of Drop on target Grid.
Keep track of source GridView and Target Gridview and use to get its adapter.
then Manipulate on Drop between adapter.
public void setDragListener() {
pager = getViewPager();
dragListener = new View.OnDragListener() {
GridViewAdapter sourceAdapter = null;
GridViewAdapter targetAdapter = null;
int currentOffset = 0;
@Override
public boolean onDrag(View v, DragEvent event) {
int currentX = -1;
int currentY = -1;
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
if (!pager.isFakeDragging()) {
pager.beginFakeDrag();
}
break;
case DragEvent.ACTION_DRAG_ENTERED:
pager.setCurrentItem(pager.getCurrentItem());
currentOffset = (int) (event.getX());
if (!pager.isFakeDragging()) {
pager.beginFakeDrag();
}
break;
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DRAG_LOCATION:
if (pager != null) {
if (!pager.isFakeDragging()) {
pager.beginFakeDrag();
}
if (pager.isFakeDragging()) {
int maxWidth = pager.getWidth() * pager.getCount();
int offset = (int) (event.getX());
int scrollX = getScrollX();
int dragBy = (int) -1 * (offset - currentOffset);
currentOffset = offset;
pager.fakeDragBy(dragBy * pager.getCount());
int scrolledPage = (int) (offset + scrollX) / pager.getWidth();
if (pager.getCurrentItem() != scrolledPage) {
pager.setCurrentItem(Math.abs(scrolledPage));
}
}
}
break;
case DragEvent.ACTION_DRAG_ENDED:
if (pager.isFakeDragging()) {
pager.endFakeDrag();
}
break;
case DragEvent.ACTION_DROP:
if (pager.isFakeDragging()) {
pager.endFakeDrag();
}
currentX = (int) event.getX();
currentY = (int) event.getY();
// u can use meta data and other info which u passed when longPress
// u can set sourcePage and sourcePosition in meta data.
metaMove = event.getLocalState();
sourceAdapter = // get Source Gridviews adapter
targetAdapter = // get Target GridViews Adapter ie current Page's gridviews adapter.
GridView g = // get The gridview current Page gridview
if (g != null) {
int position = g.pointToPosition(currentX + (getScrollX() - (pager.getWidth() * pager.getCurrentItem())), currentY);
metaMove.targetPosition = position;
metaMove.targetPage = currentPage;
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// u can move from source to target by inset and remove.
// use some broadcast function to reset if page does not have any item left while moving. Ur logic here.
move(sourceAdapter, targetAdapter, metaMove);
}
});
}
break;
default:
break;
}
return true;
}
};
pager.setOnDragListener(dragListener);
}
public int getScrollX() {
int maxWidth = pager.getWidth() * pager.getCount();
int scrollX = pager.getScrollX();
if (pager.getScrollX() < 0) {
scrollX = maxWidth + scrollX - pager.getWidth();
} else if (pager.getScrollX() == 0) {
if (pager.getCurrentItem() == (pager.getCount() - 1)) {
scrollX = maxWidth + scrollX - pager.getWidth();
}
}
return scrollX;
}
Use following onLongPress on your sourceGrid:
metaMove.sourcePage = // sourcePage;
metaMove.sourcePosition = position;
metaMove.targetPosition = -1; // to be set on drop
metaMove.targetPage = -1 // to be set on drop;
boolean dragStarted = view.startDrag(null,
myShadow,
metaMove,
0
);
Upvotes: 1
Reputation: 1
Note : I assume you are using gridView.setOnItemLongClickListener()
for startDrag() etc. Refer it on android site.
Upvotes: 0