如果我犯了任何愚蠢的错误,我很抱歉,但我找不到这个的来源: 我正在尝试在我的EditText" etItem"上实现一个onDrag监听器。 这是我的代码:
etItem.setOnDragListener(new OnDragListener(){
@Override
public boolean onDrag(View v, DragEvent dragevent) {
if(null!=dragevent && null!=v){
if( dragevent.getAction() == DragEvent.ACTION_DROP )
{
View view = (View) dragevent.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
int itemNum = (Integer) view.getTag();
itemAmounts[itemNum] = 0;
owner.removeView(view);
return true;
}
}
return false;
}});
这在我的Samsng Galaxy Grand上工作得很好,但在Nexus上给了我一个nullpointer。
stackTrace:
03-26 15:47:21.185: E/AndroidRuntime(1439): FATAL EXCEPTION: main
03-26 15:47:21.185: E/AndroidRuntime(1439): java.lang.NullPointerException
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.widget.Editor.onDrop(Editor.java:1797)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.widget.TextView.onDragEvent(TextView.java:8350)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.View.dispatchDragEvent(View.java:16375)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1237)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewRootImpl.handleDragEvent(ViewRootImpl.java:3838)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewRootImpl.access$600(ViewRootImpl.java:95)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2999)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.os.Handler.dispatchMessage(Handler.java:99)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.os.Looper.loop(Looper.java:137)
03-26 15:47:21.185: E/AndroidRuntime(1439): at android.app.ActivityThread.main(ActivityThread.java:5041)
03-26 15:47:21.185: E/AndroidRuntime(1439): at java.lang.reflect.Method.invokeNative(Native Method)
03-26 15:47:21.185: E/AndroidRuntime(1439): at java.lang.reflect.Method.invoke(Method.java:511)
03-26 15:47:21.185: E/AndroidRuntime(1439): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-26 15:47:21.185: E/AndroidRuntime(1439): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-26 15:47:21.185: E/AndroidRuntime(1439): at dalvik.system.NativeStart.main(Native Method)
03-26 15:47:21.345: W/ActivityManager(297): Force finishing activity com.listcalc.main/.MainActivityFree
答案 0 :(得分:5)
我认为这是EditText
小部件和Android中的拖放API的错误。我在其他解决方案中添加了一个链接到问题跟踪器的帖子,但我会在这里重现它以便于阅读。如果你遇到这个问题, please go to the tracker虽然明星这个问题有希望让Android工程师意识到这一点(一厢情愿,我知道)。
我在尝试使用拖放API在EditText
(非常简单的目标)中移动FrameLayout
时遇到了4.4.2中的崩溃/错误。我的OnDragListener
上只设置了FrameLayout
,但显然框架会调用所有孩子View
的{{1}}回调,如崩溃堆栈跟踪中所示
崩溃发生在内部类OnDragEvent()
中,该方法尝试从传递给方法的android.widget.Editor.onDrop()
访问ClipData
信息。
<强> From 4.4.2 source 强>
DragEvent
在第1830行1828 void onDrop(DragEvent event) {
1829 StringBuilder content = new StringBuilder("");
1830 ClipData clipData = event.getClipData();
1831 final int itemCount = clipData.getItemCount();
1832 for (int i=0; i < itemCount; i++) {
1833 Item item = clipData.getItemAt(i);
1834 content.append(item.coerceToStyledText(mTextView.getContext()));
1835 }
....
返回event.getClipData()
。然后在第1831行null
将触发NPE。这似乎只发生在clipData.getItemCount()
,因为他们有一个EditText
实例字段,这让我觉得这是一个错误/疏忽。
我找到了两个解决方法。
与注释#1中提出的变通方法类似,您可以在将接收Drag事件的Views层次结构中的android.widget.Editor
个对象上设置虚拟OnDragListener
。但是,虚拟听众可以简单地
EditText
只需为所有Drag事件返回myEditText.setOnDragListener( new View.OnDragListener() {
@Override
public boolean onDrag( View v, DragEvent event) {
return true;
}
});
,无论Action的类型是什么(即通过调用{{{{{{{{{{{{{{{{{{{{ 1}})。这意味着您将拦截Drag事件,并且它不会再被传递给View的实际true
回调,因此避免了我们在堆栈跟踪中看到的崩溃。
对于此虚拟侦听器,如果在注释#1中看到event.getAction()
,则没有必要具有单独的条件,因为如果您为OnDragEvent()
返回false,则您将永远不会收到无论如何(event.getAction() == DragEvent.ACTION_DROP)
事件(您可以通过在ACTION_DRAG_STARTED
条件中放置日志打印消息来确认这一点,并且您会注意到它永远不会被调用,因为您已在ACTION_DROP
中返回ACTION_DROP
{1}}条件)。
由于在尝试访问false
中的else
null
时发生了NPE,因此您可以在开始时向ClipData
提供虚拟Editor.onDrop()
拖动过程。
这就是我为我的场景所做的:
ClipData
我选择使用辅助方法DragEvent
为我创建一个简单的纯文本... <other code>
ClipData dummyData = ClipData.newPlainText("dummyData", ""); // don't forget to pass empty String
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDrag(dummyData, shadowBuilder, v, 0);
...
,因为你不能用它的构造函数和{{构造一个ClipData.newPlainText
1}}参数,因为这也会导致崩溃。
因此,无论您使用ClipData
开始拖动过程,请务必提供此虚拟ClipData
。通过这种解决方法,我不需要虚拟null
,我也不会遇到任何NPE崩溃。
注意:如果您使用第一种解决方法,请知道通过从虚拟View.startDrag()
返回ClipData
,您将有效地阻止DragEvent传播到{{ 1}}所以没有任何代码存在于那里。我不确定这有什么副作用,但它绝对不是一个空洞的方法。
*编辑:在使用OnDragListener
小部件进行拖放操作时,我发现true
有一些非常奇怪的行为,这是如果你选择第二种解决方法,最终会调用什么。我注意到在使用我建议的虚拟OnDragListener
时,&#34; dummyData &#34;如果您尝试将小部件拖动一点同时同时在文本框中移动插入符号,或者键入,则作为第二个参数传递给TextView.onDragEvent()
的字符串有时会粘贴/插入EditText
进入TextView.onDragEvent()
,然后拖动它。
解释起来很困惑,但我能够可靠地重现它。任何读者都可以take a look at the source code获得该方法,如果他们想要尝试并理解它,但我老老实实地厌倦了试图找出Android工程师对此的奇怪意图。由于这种奇怪的行为,我改变了我的第二种解决方法,将空字符串作为第二个参数传递。这似乎缓解了这个问题。
就我个人而言,我最终扩展了ClipData
课程并制作了自己的课程,并简单地覆盖了ClipData.newPlainText()
到EditText
而没有打电话给超类(即EditText
。这是本质上与第一个解决方法相同,但我还是需要扩展EditText
类以添加一些额外的功能。无论onDragEvent()
中的原始代码是什么,跳过它都没有&#39这似乎影响了我的个人用例,我没有发现任何我需要的功能缺失。
答案 1 :(得分:0)
NVM,发现了这个问题。 结果可能是框架中的一个错误。
https://code.google.com/p/android/issues/detail?id=21775
报告了与nexus相同的问题。