好的,我已经实现了一个android数据网格,其中包括让你拖放列。此功能非常有效(比我预期的要好)。
我最近注意到如果将网格放在tabcontents中......似乎没有考虑zindex(即使我的ACTION_DRAG_STARTED将在z-index中进一步返回false标题,我仍然会看到那些列标题回应某些事件(如ACTION_DRAG_EXITED)。
尝试拥有一个受控制的环境,我继续建立了一个独立的项目来演示这个问题。
我希望我错过了一些简单的东西,或者想知道如何解决它。复制非常简单...运行项目,长按拖动按钮...更改标签,拖动它们,更改回第一个标签,拖动。它应该开始拖动过程,但是一旦你拖出你刚刚进入的控件,就会看到“报告丢弃结果:false”。
任何指针都会非常感激......我怀疑底层视图正在取消拖动事件。
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>