Android的拖放ACTION_DRAG_ENDED不触发 [英] Android Drag and Drop ACTION_DRAG_ENDED not firing

查看:371
本文介绍了Android的拖放ACTION_DRAG_ENDED不触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的有时间弄清这一个出来,找不到任何朋友相关的经验,到目前为止。这是我最后的功能之前,我释放我的第一个应用程序,所以它的驾驶我疯狂已经得到陷入了它结束在望!

I'm really having a time figuring this one out and can't find any friends with the relevant experience so far. It's my VERY LAST FEATURE before I release my VERY FIRST APP so it's driving me crazy to have gotten bogged down with it with the end in sight!

我的拖放完美的作品,如果我在一个可接受的范围下降的对象。但是,如果放弃别的地方我不明白的事件和失败的拖放操作后,无法收拾。我需要的ACTION_DRAG_ENDED事件触发。然而,这仅火灾(根据文档),如果我到ACTION_DRAG_STARTED做出响应,显示真实的(这意味着它可以接受的对象)的值。问题是ACTION_DRAG_STARTED不点火!

My drag and drop works perfectly if I drop the object in an acceptable area. However, if dropped somewhere else I do not get an event and cannot clean up after the failed drag drop operation. I need the ACTION_DRAG_ENDED event to fire. However this only fires (according to the documentation) if I respond to ACTION_DRAG_STARTED with a value of true (meaning it can accept the object). The problem is ACTION_DRAG_STARTED is not firing!

所以,我认为问题的关键是,我没有收到ACTION_DRAG_STARTED。我把东西应该是所有相关的DragDrop code(或至少几乎所有的)位置:

So I believe the crux of the matter is that I'm not getting ACTION_DRAG_STARTED. I'm putting what should be all of the relevant dragdrop code (or at least nearly all) here:

private OnTouchListener onTouchListener = new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Item current = (Item) ((View) v.getTag()).getTag();
            //ClipData data = ClipData.newPlainText("test", "testText");
            View dragView = (View) v.getTag();
            DragShadowBuilder shadowBuilder = new ItemDragShadowBuilder(dragView, 
                                new Point(v.getWidth()/2, v.getHeight()/2));
            dragSource = dragView;
            v.startDrag(null, shadowBuilder, current, 0);
            dragView.setVisibility(View.INVISIBLE);
            return true;
        } else {
            return false;
        }       
    }

};

private static class ItemDragShadowBuilder extends View.DragShadowBuilder {

    private Point touchPoint = null;
    private Point sizePoint = null;
    private View dragView = null;

    public ItemDragShadowBuilder(View dragView, Point touchPoint) {
        super();
        sizePoint = new Point(dragView.getWidth(), dragView.getHeight());
        this.touchPoint = touchPoint;
        this.dragView = dragView;
    }

    @Override
    public void onProvideShadowMetrics (Point size, Point touch) {
        size.set(sizePoint.x, sizePoint.y);
        touch.set(touchPoint.x,touchPoint.y);
    }

    @Override
    public void onDrawShadow(Canvas canvas) {

        dragView.setBackgroundColor(dragView.getContext().getResources().getColor(R.color.holoBlueDark));
        dragView.draw(canvas);

        //canvas.setBitmap(dragView.getDrawingCache());
        //canvas.drawColor(Color.WHITE);
        //dragView.setAlpha(1);

        //How do I change the transparency?
        //super.onDrawShadow(canvas);
    }



}


private View dragSource = null;

private OnDragListener onDragEventListener = new OnDragListener() {

    @Override
    public boolean onDrag(View v, DragEvent event) {
        final int action = event.getAction();

        switch (action) {
        case DragEvent.ACTION_DRAG_STARTED:
            Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString() + " started", Toast.LENGTH_SHORT/8).show();
            return true;
            //break;//DRAG AND DROP>>>START DOESN"T FIRE
        case DragEvent.ACTION_DROP:
            if ((dragSource != null) && (dragSource != v)) {
                Item source = (Item) dragSource.getTag();
                Item target = (Item) v.getTag();
                int sourcePos = source.getPosition();
                int targetPos = target.getPosition();
                if (targetPos < sourcePos)
                    source.moveUp(sourcePos - targetPos);
                else
                    source.moveDown(targetPos - sourcePos);
                dragSource.setVisibility(View.VISIBLE);
                dragSource = null;
                fireOnChecklistNeedsResetListener();
                return true;
            }
//              View view = (View) event.getLocalState();
//              Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
//              Toast.makeText(v.getContext(), ((EditText) view.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
            // Dropped, reassign View to ViewGroup
//              View view = (View) event.getLocalState();
//              ViewGroup owner = (ViewGroup) view.getParent();
//              owner.removeView(view);
//              LinearLayout container = (LinearLayout) v;
//              container.addView(view);
//              view.setVisibility(View.VISIBLE);
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            dragSource.setVisibility(View.VISIBLE);
            dragSource = null;
            fireOnChecklistNeedsResetListener();
            if (!event.getResult())
                Toast.makeText(v.getContext(), "UNHANDLED", Toast.LENGTH_SHORT/8).show();

//              View vieww = (View) event.getLocalState();
//              Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
//              Toast.makeText(v.getContext(), ((EditText) vieww.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
            break;
        case DragEvent.ACTION_DRAG_ENTERED:

            v.setBackgroundColor(v.getContext().getResources().getColor(R.color.holoBlueLight));
            return true;
            //break;
        case DragEvent.ACTION_DRAG_EXITED:        
            v.setBackgroundColor(v.getContext().getResources().getColor(android.R.color.background_light));
            return false;
            //break;
        default:
            break;
    }
        return false;
    }

};

扩展的信息:dragView是在ListView(特别是expandablelistview)的项目布局。接受触摸事件的观点是在具有小把手的视图小字形。下面是一个进展中的拖拽操作截图(使用了一些奇特的手指的工作得到这个笑):

Extended information: The dragView is an item layout in a listview (specifically an expandablelistview). The view that accepts the touch event is a small glyph on the view with a small grip. Here is a screenshot with a drag operation in progress (took some fancy finger work to get this lol):

所以,如果我是砸在另一个项目拖动的项目(这其中重新排序),它的伟大工程。如果我把它在其他地方没有任何事件触发,所以我永远无法清理。因此,例如在屏幕的,或者如果上部的列表是短内的空白区域或在底部或任何系统区域的蓝色条

So if I were to drop the dragged item on another item (this reorders them) it works great. If I drop it somewhere else no event fires so I can never clean it up. So for example in the upper part of the screen or if the list is short in a blank area or the blue bar on bottom or any of the system areas.

我可以替代解决这个问题,找出一种方法来prevent从有效面积拖着走,所以如果你知道该怎么做,这是另一种方式来解决这个问题。我的最后的选择将是实现一事件的屏幕上每一个可能的视图(再次这些列表视图布局,在列表视图,这是对的片段,它可以是对各种活动),因此显然,这将是不希望。而事实上,如果我这样做,我可能仍然有一个问题,如果它的下降在系统UI区域(如systembar或电容式按键区),但我不知道。

I could alternatively solve this problem by figuring out a way to prevent dragging away from a valid area so if you know how to do that, that's another way to solve it. My last option would be to implement an event for every possible view on the screen (again these are list view layouts, on a listview, which is on a fragment, which could be on various activities) so obviously this would not be desirable. And in fact if I do that I still may have a problem if it's dropped in a system UI area (like systembar or capacitive buttons area) but I'm not sure.

在情况下,它是有帮助这里是我分配相关的事件过程(我删除无关行)在列表视图适配器获得视图项的方法:

In case it is helpful here is where I assign the relevant event procedures (I removed irrelevant lines) in the list view adapters get view item method:

public View getGroupEdit(int groupPosition, boolean isExpanded, View convertView,
        ViewGroup parent) {
    if (convertView != null) {
                //irrelevant stuff omitted
    } else
        convertView = inf.inflate(R.layout.edit_group_item, null);
    Item group = (Item) getGroup(groupPosition);
    convertView.setTag(group);
    EditText edtParent = (EditText) convertView.findViewById(R.id.edtParent);
    edtParent.setTag(convertView);
    scatterItemText(edtParent);

            //irrelevant stuff omitted

    ImageView imgGrip = (ImageView) convertView.findViewById(R.id.imgGrip);
    imgGrip.setTag(convertView);
             //irrelevant stuff omitted     

            imgGrip.setOnTouchListener(onTouchListener);
    convertView.setOnDragListener(onDragEventListener);
    return convertView;
}

最后FWIW,这是布局的XML列表项的看法:

And finally FWIW, this is the layout XML for the list item view:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:orientation="horizontal" >
<ImageView 
    android:id="@+id/imgGrip"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:src="@drawable/dark_grip2"
    android:contentDescription="@string/strReorder"/>
<CheckBox 
    android:id="@+id/chkParent"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/imgGrip"
    android:checked="false"/>
<EditText
    android:id="@+id/edtParent"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/chkParent"
    android:layout_toLeftOf="@+id/btnInsert"
    android:textSize="17dip" 
    android:inputType="text"
    android:hint="@string/strItem"/>
<ImageButton
    android:id="@id/btnInsert"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:layout_toLeftOf="@+id/viewParent"
    android:src="@drawable/dark_content_new"
    android:clickable="true"
    android:hint="@string/strAddItemAbove"
    android:contentDescription="@string/strAddItemAbove" />   
<View 
    android:id="@id/viewParent"
    android:layout_height="match_parent"
    android:layout_width="0dp"
    android:layout_toLeftOf="@+id/btnExpand"/>    
<ImageButton 
    android:id="@id/btnExpand"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:layout_alignParentRight="true"
    android:src="@drawable/dark_add_sub_item"
    android:clickable="true"
    android:hint="@string/strViewSubItems"
    android:contentDescription="@string/strViewSubItems"/>   
</RelativeLayout>

非常感谢您的帮助!

Thanks so much for any help!

推荐答案

这需要拖动事件被通知视图必须注册 OnDragListeners 。如果他们需要知道,当特定事物或类型的东西移动,例如以改变其外观(无论是一个拖我在这里!或你怎么敢丢弃我吧!)。即使你的观点是不要放弃的对象的有效场所被拖动,如果它需要拖情境感知可以这么说,它注册了一个 OnDragListener 返回true为 ACTION_DRAG_STARTED

Views that need to be notified of drag events must register OnDragListeners. If they need to be aware when specific things or types of things move, for instance in order to change their appearance (either to a "DRAG ME HERE!" or a "DON'T YOU DARE DROP THAT ON ME!"). Even if your view is not a valid place to drop the object being dragged, if it needs to be 'drag context aware' so to speak, it registers an OnDragListener and returns true forACTION_DRAG_STARTED.

一件事,我从你的非常透彻的问题缺少的是你需要进行清理究竟是什么?如果你只是需要做一些通用的东西,都在活动范围,可以考虑增加一个不同的 OnDragListener 到基 RelativeLayout的用于注册的事件,而是等待 ACTION_DRAG_ENDED 提醒活动,以执行普通清理code

The one thing I'm missing from your very thorough question is what exactly you need to be cleaned up? If you just need to do some generic things that are in the scope of the activity, you might consider adding a different OnDragListener to the base RelativeLayout that registers for the events but waits for ACTION_DRAG_ENDED to alert the activity to perform your generic cleanup code

这篇关于Android的拖放ACTION_DRAG_ENDED不触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆