Хорошо, я реализовал сетку данных Android, которая помимо прочего позволяет перетаскивать столбцы вокруг. Эта функциональность работает прекрасно (лучше, чем я ожидал).
Недавно я заметил, что если сетки были помещены в tabcontents ... кажется, что zindex не учитывается (хотя мой ACTION_DRAG_STARTED вернет false для заголовков столбцов далее в z-index, я все еще вижу эти заголовки столбцов реагирование на некоторые события (например, ACTION_DRAG_EXITED).
Пытаясь создать контролируемую среду, я разработал отдельный проект, демонстрирующий эту проблему.
Я надеюсь, что это что-то простое, что я пропустил, или, возможно, идеи о том, как обойти это. Довольно просто воспроизвести ... запустить проект, перетаскивать кнопки длинным нажатием ... менять вкладки, перетаскивать их вокруг, переходить на первую вкладку, перетаскивать. Должен начаться процесс перетаскивания, но как только вы перетащите из элемента управления, в котором вы только что находились, вы увидите «Отчет о результате отбрасывания: ложь».
Любые указатели будут с благодарностью ... Я подозреваю, что базовые представления отменяют событие перетаскивания.
BrokeDragNDropActivity.java
package cm.mc.busteddnd;
import android.app.Activity;
import android.content.ClipData;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabSpec;
import android.widget.Toast;
public class BrokeDragNDropActivity extends Activity {
public static int selectedTab =0;
Extendedbutton button1;
Extendedbutton button2;
Extendedbutton button3;
Extendedbutton button4;
Extendedbutton button5;
Extendedbutton button6;
Extendedbutton button7;
Extendedbutton button8;
Extendedbutton button9;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
final TabHost tabs = (TabHost) this.findViewById(R.id.my_tabhost);
tabs.setOnTabChangedListener(new OnTabChangeListener() {
@Override
public void onTabChanged(String arg0) {
selectedTab = tabs.getCurrentTab();
Log.i("***Selected Tab", "Im currently in tab with index::" + tabs.getCurrentTab());
}
});
tabs.setup();
TabSpec tspec1 = tabs.newTabSpec("First Tab");
tspec1.setIndicator("One");
tspec1.setContent(R.id.content);
tabs.addTab(tspec1);
TabSpec tspec2 = tabs.newTabSpec("Second Tab");
tspec2.setIndicator("Two");
tspec2.setContent(R.id.content2);
tabs.addTab(tspec2);
TabSpec tspec3 = tabs.newTabSpec("Third Tab");
tspec3.setIndicator("Three");
tspec3.setContent(R.id.content3);
tabs.addTab(tspec3);
//wire up buttons
button1 = (Extendedbutton)findViewById(R.id.button1);
button2 = (Extendedbutton)findViewById(R.id.button2);
button3 = (Extendedbutton)findViewById(R.id.button3);
button4 = (Extendedbutton)findViewById(R.id.button4);
button5 = (Extendedbutton)findViewById(R.id.button5);
button6 = (Extendedbutton)findViewById(R.id.button6);
button7 = (Extendedbutton)findViewById(R.id.button7);
button8 = (Extendedbutton)findViewById(R.id.button8);
button9 = (Extendedbutton)findViewById(R.id.button9);
//wire up listeners
button1.setGroup(1);
wireListeners(button1);
button2.setGroup(1);
wireListeners(button2);
button3.setGroup(1);
wireListeners(button3);
button4.setGroup(2);
wireListeners(button4);
button5.setGroup(2);
wireListeners(button5);
button6.setGroup(2);
wireListeners(button6);
button7.setGroup(3);
wireListeners(button7);
button8.setGroup(3);
wireListeners(button8);
button9.setGroup(3);
wireListeners(button9);
}
public void wireListeners(Extendedbutton button){
button.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View paramView) {
Extendedbutton v = (Extendedbutton)paramView;
ClipData data = ClipData.newPlainText("group_"+v.getGroup(), v.getDesc());
paramView.startDrag(data, // the data to be dragged
new View.DragShadowBuilder(paramView), // the drag shadow builder
null, // no need to use local data
0 // flags (not currently used, set to 0)
);
return true;
}
});
button.setOnDragListener(new OnDragListener(){
@Override
public boolean onDrag(View v, DragEvent event) {
// Defines a variable to store the action type for the incoming event
final int action = event.getAction();
// Handles each of the expected events
CharSequence dragData;
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
// Determines if this View can accept the dragged data
if (event.getClipDescription().getLabel().equals("group_"+(selectedTab+1))) {
// As an example of what your application might do,
// applies a blue color tint to the View to indicate that it can accept
// data.
v.setBackgroundColor(Color.BLUE);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
// returns true to indicate that the View can accept the dragged data.
return(true);
} else {
// Returns false. During the current drag and drop operation, this View will
// not receive events again until ACTION_DRAG_ENDED is sent.
return(false);
}
case DragEvent.ACTION_DRAG_ENTERED: {
// Applies a green tint to the View. Return true; the return value is ignored.
v.setBackgroundColor(Color.GREEN);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
return(true);
}
case DragEvent.ACTION_DRAG_LOCATION:
// Ignore the event
return(true);
case DragEvent.ACTION_DRAG_EXITED:
// Re-sets the color tint to blue. Returns true; the return value is ignored.
v.setBackgroundColor(Color.BLUE);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
return(true);
case DragEvent.ACTION_DROP:
// Gets the item containing the dragged data
ClipData.Item item = event.getClipData().getItemAt(0);
// Gets the text data from the item.
dragData = item.getText();
// Displays a message containing the dragged data.
Toast.makeText(BrokeDragNDropActivity.this, "Dragged data is " + dragData, Toast.LENGTH_LONG);
// Turns off any color tints
v.setBackgroundColor(Color.BLACK);
// Invalidates the view to force a redraw
v.invalidate();
// Returns true. DragEvent.getResult() will return true.
return(true);
case DragEvent.ACTION_DRAG_ENDED:
// Turns off any color tinting
v.setBackgroundColor(Color.BLACK);
// Invalidates the view to force a redraw
v.invalidate();
// Does a getResult(), and displays what happened.
if (event.getResult()) {
Toast.makeText(BrokeDragNDropActivity.this, "The drop was handled.", Toast.LENGTH_LONG);
} else {
Toast.makeText(BrokeDragNDropActivity.this, "The drop didn't work.", Toast.LENGTH_LONG);
};
// returns true; the value is ignored.
return(true);
// An unknown action type was received.
default:
Log.e("DragDrop Example","Unknown action type received by OnDragListener.");
return false;
}
}
});
}
}
ExtendedButton.java (необходимо для фильтрации групп)
package cm.mc.busteddnd;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;
public class Extendedbutton extends Button {
private int group;
private String desc;
public int getGroup() {
return group;
}
public void setGroup(int group) {
this.group = group;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Extendedbutton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public Extendedbutton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public Extendedbutton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
}
и наконец ...
main.xml
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="65px"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="200px"
android:paddingTop="65px">
<LinearLayout
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="horizontal">
<cm.mc.busteddnd.Extendedbutton android:text="Button1" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
<cm.mc.busteddnd.Extendedbutton android:text="Button2" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
<cm.mc.busteddnd.Extendedbutton android:text="Button3" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
</LinearLayout>
<LinearLayout
android:id="@+id/content2"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="horizontal">
<cm.mc.busteddnd.Extendedbutton android:text="Button4" android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
<cm.mc.busteddnd.Extendedbutton android:text="Button5" android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
<cm.mc.busteddnd.Extendedbutton android:text="Button6" android:id="@+id/button6" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
</LinearLayout>
<LinearLayout
android:id="@+id/content3"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="horizontal">
<cm.mc.busteddnd.Extendedbutton android:text="Button7" android:id="@+id/button7" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
<cm.mc.busteddnd.Extendedbutton android:text="Button8" android:id="@+id/button8" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
<cm.mc.busteddnd.Extendedbutton android:text="Button9" android:id="@+id/button9" android:layout_width="wrap_content" android:layout_height="wrap_content"></cm.mc.busteddnd.Extendedbutton>
</LinearLayout>
</FrameLayout>
</TabHost>