I need to implement current tab change when the item is dragged near screen edge (left or right).
There's no problem with drag N drop feature and current tab switches. I just can't handle properly this event - when dragged item is near the edge of the screen.
How would you do that?
What I tried:
<FrameLayout
android:id="@+id/left_toggle_area"
android:layout_width="30dp"
android:layout_height="fill_parent"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true">
</FrameLayout>
<FrameLayout
android:id="@+id/right_toggle_area"
android:layout_width="30dp"
android:layout_height="fill_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true">
</FrameLayout>
<GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
... />
The idea is to change current tab programmatically when the dragged item at toggle area.
But the event DragEvent.ACTION_DRAG_ENTERED
on that area never occurs since (I believe so) the GridView
takes the entire screen and simply overlaps with toggle areas.
I've tried already bring those areas to the front when the drag start event is triggered. But that doesn't work for some reason.
FrameLayout toggleView = (FrameLayout) v;
toggleView.bringToFront();
toggleView.requestLayout();
toggleView.invalidate();
If anyone faced such problem please share your experience. Or perhaps there's another better solution for this. Please give me a hint.
DragShadowBuilder object, so the callbacks can access it to construct the drag shadow. The view doesn't have to be the View (if any) that the user selected to start the drag operation. If you use this constructor, you don't have to extend View. DragShadowBuilder or override its methods.
The current solution I came to which works (more or less) is to use TextView
nested in PagerTabStrip
title as drag area. The biggest con in this approach is that those toggle areas are too small for some reason. ENTER event triggers only at those areas.
I belive this solution would be good with oldschool tabs. Therefore here's code. Might be useful for someone.
1). Parse TextViews
from PagerTabStrip
private ArrayList <TextView> titles;
...
public void setPager(PagerTabStrip mPagerTabStrip) {
for (int i = 0; i < mPagerTabStrip.getChildCount(); ++i) {
View nextChild = mPagerTabStrip.getChildAt(i);
if (nextChild instanceof TextView) {
TextView textViewToConvert = (TextView) nextChild;
if (textViewToConvert.getText().toString().contains(TabsFragment.TAG_MONITOR)){ // I take only few tabs
if (!titles.contains(textViewToConvert)) {
titles.add(textViewToConvert);
}
}
}
}
}
public ArrayList<TextView> getTitles() {
return titles;
}
After this operation I have 3 TextViews that need drag'n'drop navigation.
2). Pass your list of TextViews
to class where you implement DragListeners
:
public void setUpDragNDropTabMoves(ArrayList<TextView> views) {
if (views != null) {
for (TextView tv : views){
tv.setOnDragListener(TabToggleDragListener);
}
}
}
3). And the listener itself
View.OnDragListener TabToggleDragListener = new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
TextView toggleView = (TextView) v;
String title = toggleView.getText().toString();
switch (event.getAction()) {
case DragEvent.ACTION_DROP:
...
break;
case DragEvent.ACTION_DRAG_ENTERED:
int tabId = -1;
//define which tab is destination
if (title.contains(TabsFragment.TAG_MONITOR1)){
tabId = 1;
} else if (title.contains(TabsFragment.TAG_MONITOR2)){
tabId = 2;
} else if (title.contains(TabsFragment.TAG_MONITOR3)){
tabId = 3;
}
//send event to tab host fragment/activity and perform tab change to passed index
//you may use EventBus or Otto for this. I used Local Broadcast
BroadcastSender.sendMessageToUI(getContext(),
BroadcastSender.TABS_FRAGMENT,
BroadcastActions.TF_TOGGLE_TAB,
tabId
);
break;
case DragEvent.ACTION_DRAG_EXITED:
...
break;
case DragEvent.ACTION_DRAG_ENDED:
...
break;
}
return true;
}
};
I take it the parent of the three views (toggle areas and the GridView
) is a RelativeLayout
. First of all, replace the GridView
, to be the first child of its parent. Leave the rest of the layout exactly as they are.
Secondly, in order to catch drop event with View.OnDragListener
interface, you need to set the minimum SDK version to 11 in the AndroidManifest.xml
. After that you can pass the listener to the toggle areas:
View.OnDragListener dragListener = new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
// you can check for event.ACTION_DRAG_ENTERED here
return true;
}
};
FrameLayout leftToggleArea = (FrameLayout) findViewById(R.id.left_toggle_area);
leftToggleArea.setOnDragListener(dragListener);
In case you still have problems, post more of your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With