【问题标题】:Prevent drag drop of custom mimetype to EditText防止将自定义 mimetype 拖放到 EditText
【发布时间】:2012-08-16 00:16:15
【问题描述】:

我有一个自定义 mime 类型,我打算用它在应用程序中拖放应用程序对象。这似乎有效,但我发现 EditText 字段也接受了放置操作。我不希望这种情况发生。

首先,我定义了这样的自定义 mime 类型:

public static final String MIME_TYPE_MYNODE = "com.example.mockup/mynode";

然后,在我拥有的源对象的 onTouch 处理程序中:

  @Override
  //-----------------------------------------------------------------------------
  public boolean onTouch (View v, MotionEvent e)
  {
    ...
    else if (e.getAction() == MotionEvent.ACTION_MOVE)
    {
      String[] mimeTypes = {MIME_TYPE_MYNODE};
      ClipData data = new ClipData ("Task Tamer Note", mimeTypes, new ClipData.Item ("unused"));
      View.DragShadowBuilder shadow = new View.DragShadowBuilder(this);
      Object localState = v;
      startDrag (data, shadow, localState, 0);
      return false;
    }
  }
  ...
}

当我“放下”一个 EditText 小部件时,它会将“未使用”插入到文本区域中。我怎样才能防止这种情况? 谢谢。

【问题讨论】:

  • 你找到答案了吗?
  • 还没有。我一直让它坐下来,希望我能偶然发现一些东西或得到回应:)
  • 有任何解决方案吗?遇到同样的问题,想不出解决办法。
  • 我做了什么:首先,我为edittext的父视图实现了拖动事件,并在第一次调用时为edittextenabledfocusableactive设置到false,然后,神奇的事情发生了——edittext 第一次收到drop,下一次都没有收到。会是什么?

标签: android drag-and-drop android-edittext mime-types


【解决方案1】:

我遇到了同样的行为。我找到了原因,位于 TextView 类中。

方法 onDragEvent(DragEvent event) 在这里被覆盖,如下所示。

@Override
public boolean onDragEvent(DragEvent event) {
    switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_STARTED:
            return mEditor != null && mEditor.hasInsertionController();

        case DragEvent.ACTION_DRAG_ENTERED:
            TextView.this.requestFocus();
            return true;

        case DragEvent.ACTION_DRAG_LOCATION:
            final int offset = getOffsetForPosition(event.getX(), event.getY());
            Selection.setSelection((Spannable)mText, offset);
            return true;

        case DragEvent.ACTION_DROP:
            if (mEditor != null) mEditor.onDrop(event);
            return true;

        case DragEvent.ACTION_DRAG_ENDED:
        case DragEvent.ACTION_DRAG_EXITED:
        default:
            return true;
    }
}

如果可以插入文本 => EditText,那么任何拖动都将在那里被处理和接受。 View 类没有使用 OnDragListener,因此无法通过

来阻止这种行为
editText.setOnDragListener(null);

这里的解决方案是将EditText继承为here并覆盖onDragEvent()方法:

 public class YourEditText extends EditText {

 ...
 // other stuff
 ...

 @Override
 public boolean onDragEvent(DragEvent event) {
    switch (event.getAction()) {
       case DragEvent.ACTION_DRAG_STARTED:
           if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
               return true;
           }
           return false;
       default:
           return super.onDragEvent(event);
    }
}

}

现在 YourEditText 将只接受带有 MIMETYPE_TEXT_PLAIN 的拖动。如果你想完全禁用拖放,只需在此方法中返回 false `

@Override
public boolean onDragEvent(DragEvent event) {
    return false;    
}

就是这样。 希望它会有所帮助。

【讨论】:

  • 您可能有正确的解决方案。我不会自己尝试(无论如何,在不久的将来)。如果其他人可以插话并验证它是否有效,那就太好了。感谢您的精彩帖子!
【解决方案2】:

我遇到了类似的问题,我不希望布局接受放置操作。

通过 setOnDragListener 将拖动侦听器附加到您的编辑字段。

edtText.setOnDragListener(new MyDragListener());

检查 onDrag 事件中的目标视图是否是您的编辑文本。

class MyDragListener implements OnDragListener {

    @Override
    public boolean onDrag(View v, DragEvent event) {

      switch (event.getAction()) {
         case DragEvent.ACTION_DROP:
             //check whether it has been dropped onto your edit text
              if(v!=edtText)
                  //your code here
    }

【讨论】:

  • 谢谢。当我回到我的应用程序的那部分时,我会试试这个。我将其称为 EditText 小部件中的错误,但您的解决方法似乎不错。
  • 这对我不起作用。实际上,我认为这种行为不是由 drop 事件引起的,而是由 paste 事件引起的。我认为是这样,因为您需要ClipData 进行复制/粘贴,并且这种行为预期非常相似。现在我正在考虑如何看待这两个事件之间的区别。
  • 我从来没有尝试过这个。相反,我最终实现了我自己的最小拖放。由于我有一些特殊的需求,比如在拖动时滚动(并且还需要避免主题问题),我决定从头开始更容易。实现拖放有一些棘手的方面,但结果很好!
  • @PeriHartman 哈哈,我在滚动时遇到了同样的问题,我自己实现了它。此外,我几乎修复了 edittext 发生丢弃事件的错误,但非常脏:/
【解决方案3】:

你可以写

edit.setEnabled(false);
edit.setFocusable(false);

在调用startDrag() 之后,并在DragEvent.ACTION_DRAG_ENDED 之后恢复特定editText 控件的旧值。

但是,老实说,这是一种非常肮脏的方法。

【讨论】:

    【解决方案4】:

    返回 如果成功处理了拖动事件,则为 true;如果未处理拖动事件,则为 false。请注意, false 将触发 View 调用其 onDragEvent() 处理程序。

    这是来自 onDrag(View v, DragEvent event) 文档的声明。因此,如果您返回 false,则事件由 EditText 的 onDragEvent() 处理。因此最简单的解决方案是:

    editText.setOnDragListener(new OnDragListener() {
    
            @Override
            public boolean onDrag(View v, DragEvent event) {
                return true;
            }
        });
    

    如果您想执行某些功能,请根据 Drag 事件指定它们将被执行。

    【讨论】:

    • 除非我继承 EditText,否则我无法控制它的 OnDragListener。还是你有别的想法?
    • 设置拖动监听器不会覆盖默认实现吗?
    • 是的,我想会的。但是,您将失去默认功能。也许这不会很难重新实现 - 不确定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    相关资源
    最近更新 更多