如何在Android 2.2中实现拖放功能?

3

我正在尝试开发一款安卓应用程序,用户应该能够将图片从一个网格单元拖到另一个网格单元。为了实现这个功能,我需要使用在Android 3.0中引入的拖放API,但是我的应用程序应该在Android 2.2上运行。那么,有没有办法使用触摸事件来实现这个功能?如果是,那么请提供给我一些代码片段或任何描述它的链接。


以下链接将帮助您解决问题.... http://techdroid.kbeanie.com/2010/04/simple-drag-n-drop-on-android.html - himanshu
可能是在Android 2.2中拖放视图的重复问题 - Leo supports Monica Cellio
4个回答

15

很久以后,我终于成功地在Android 2.2上实现了拖放功能。

这里是我的代码,可以帮助你实现成功。我的主类在此处。

 package info.tempDD;

    import android.app.Activity;
    import android.graphics.Rect;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnTouchListener;
    import android.view.ViewGroup;
    import android.view.ViewGroup.LayoutParams;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;

   public class TempDDActivity extends Activity implements OnTouchListener {
        /** Called when the activity is first created. */
        private View selected_item = null;
        private int offset_x = 0;
        private int offset_y = 0;
        Boolean touchFlag=false;
        boolean dropFlag=false;
        LayoutParams imageParams;
        ImageView imageDrop,image1,image2;
        int crashX,crashY;
        Drawable dropDrawable,selectDrawable;
        Rect dropRect,selectRect;
        int topy,leftX,rightX,bottomY;

        int dropArray[];    

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            this.requestWindowFeature(Window.FEATURE_NO_TITLE);
            this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
            setContentView(R.layout.main);
            ViewGroup container = (ViewGroup) findViewById(R.id.container);
            imageDrop=(ImageView) findViewById(R.id.ImgDrop);       
            image1=(ImageView) findViewById(R.id.img);      
            image2=(ImageView) findViewById(R.id.img2);
            container.setOnTouchListener(new View.OnTouchListener() 
            {
                public boolean onTouch(View v, MotionEvent event) 
                {
                    if(touchFlag==true)
                    {
                        System.err.println("Display If  Part ::->"+touchFlag);
                        switch (event.getActionMasked()) 
                        {
                        case MotionEvent.ACTION_DOWN :

                             topy=imageDrop.getTop();
                             leftX=imageDrop.getLeft();
                             rightX=imageDrop.getRight();   
                             bottomY=imageDrop.getBottom();
                            System.err.println("Display Top-->"+topy);      
                            System.err.println("Display Left-->"+leftX);
                            System.err.println("Display Right-->"+rightX);
                            System.err.println("Display Bottom-->"+bottomY);                


                            //opRect.
                            break;
                        case MotionEvent.ACTION_MOVE:
                            crashX=(int) event.getX();
                            crashY=(int) event.getY();
                            System.err.println("Display Here X Value-->"+crashX);
                            System.err.println("Display Here Y Value-->"+crashY);

                            int x = (int) event.getX() - offset_x;
                            int y = (int) event.getY() - offset_y;                                          
                            //int w = getWindowManager().getDefaultDisplay().getWidth() - 100;
                            //int h = getWindowManager().getDefaultDisplay().getHeight() - 100;
                            int w = getWindowManager().getDefaultDisplay().getWidth() - 50;
                            int h = getWindowManager().getDefaultDisplay().getHeight() - 10;
                            if (x > w)
                                x = w;
                            if (y > h)
                                y = h;                      
                            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(new ViewGroup.MarginLayoutParams(  RelativeLayout.LayoutParams.WRAP_CONTENT,   RelativeLayout.LayoutParams.WRAP_CONTENT));
                            lp.setMargins(x, y, 0, 0);                  

                            //Drop Image Here                       
                            if(crashX > leftX && crashX < rightX && crashY > topy && crashY < bottomY )                     
                            {                           
                                Drawable temp=selected_item.getBackground();                            
                                imageDrop.setBackgroundDrawable(temp);
                                imageDrop.bringToFront();                           
                                dropFlag=true;
                                selected_item.setVisibility(View.INVISIBLE);
                            }
                            //Drop Image Here                       
                            selected_item.setLayoutParams(lp);
                            break;  
                        case MotionEvent.ACTION_UP:
                            //                      
                            touchFlag=false;
                            if(dropFlag==true)
                            {
                                dropFlag=false;
                            }
                            else
                            {
                                selected_item.setLayoutParams(imageParams);
                            }                       
                            break;
                        default:
                            break;
                        }
                    }else
                    {
                        System.err.println("Display Else Part ::->"+touchFlag);
                    }               
                    return true;
                }
            });

            image1.setOnTouchListener(this);
            image2.setOnTouchListener(this);
        }

        public boolean onTouch(View v, MotionEvent event) 
        {   
            switch (event.getActionMasked()) 
            {
            case MotionEvent.ACTION_DOWN:
                touchFlag=true;
                offset_x = (int) event.getX();
                offset_y = (int) event.getY();
                selected_item = v;
                imageParams=v.getLayoutParams();
                break;
            case MotionEvent.ACTION_UP:
                selected_item=null;
                touchFlag=false;
                break;
            default:
                break;
            }       
            return false;
        }
    }

创建一个类并将其扩展为您的主布局,例如RelativeLayout

package info.tempDD;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

public class TouchInterceptor extends RelativeLayout {
    public TouchInterceptor(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        return super.onInterceptTouchEvent(ev);
    }

}

同时,这是我的主要Xml文件。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/ImgDrop"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:layout_marginTop="50dp"
        android:background="#FFFFFF" >
    </ImageView>

    <ImageView
        android:id="@+id/img"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:background="@drawable/ic_launcher" >
    </ImageView>

    <ImageView
        android:id="@+id/img2"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:background="@drawable/ic_launcher" >
    </ImageView>

</RelativeLayout>

好的,现在我完成了我的工作并感到非常满意,希望这能对您有所帮助。下面是提供给我的链接:


Zala,实际上我从http://blahti.wordpress.com/2011/10/03/drag-drop-for-android-gridview/找到了我的解决方案。因此,我没有测试过你的代码。 - Chandra Sekhar
Zala,请不要在我的博客上发布任何与该网站相关的评论。你可以在这里发表评论,我会从这里回复你。如果你对我的博客主题有任何问题,那么你可以在那里发表评论。 - Chandra Sekhar

2

view.setOnTouchListener(new View.OnTouchListener() {

意思是设置一个触摸监听器,当用户在视图上进行触摸操作时,就会调用相应的方法。
        public boolean onTouch(View v, MotionEvent me) {


            if (me.getAction() == MotionEvent.ACTION_MOVE) {


                v.setX(me.getRawX() - (v.getWidth() / 2));
                v.setY(me.getRawY() - (float)(v.getHeight()* 1.5 / 2));

            }

            return true;
        }
    }

);


2

DragDropManager.class

package com.example.dragdrop;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.PopupWindow;

public class DragDropManager
{
    private static DragDropManager instance;
    private Activity mActivity;
    private List<View> dropzones;
    private Map<View, Integer> dropzonestates;
    private Map<View, DropZoneListener> dropzonelisteners;
    private PopupWindow popoup;
    private MotionEvent firstEvent;
    private Rect rect;
    private Object item;

    public static DragDropManager getInstance()
    {
        if (instance == null) instance = new DragDropManager();
        return instance;
    }

    private DragDropManager()
    {
    }

    public void init(Activity a)
    {
        mActivity = a;
        dropzones = new ArrayList<View>();
        dropzonelisteners = new HashMap<View, DropZoneListener>();
        dropzonestates = new HashMap<View, Integer>();
        rect = new Rect();
    }

    public void addDropZone(View zone, DropZoneListener zonelistener)
    {
        dropzones.add(zone);
        dropzonelisteners.put(zone, zonelistener);
        dropzonestates.put(zone, 0);
    }

    public void clearZones()
    {
        dropzones.clear();
        dropzonelisteners.clear();
        dropzonestates.clear();
    }

    public void clearZone(View zone)
    {
        dropzones.remove(zone);
        dropzonelisteners.remove(zone);
        dropzonestates.remove(zone);
    }

    private void checkDropZones(MotionEvent event)
    {
        boolean isOver;
        HashSet<DropZoneListener> listeners = new HashSet<DropZoneListener>(dropzonelisteners.values());

        for (View zone : dropzones)
        {
            int[] location = new int[2];
            zone.getLocationInWindow(location);
            zone.getDrawingRect(rect);
            rect.offset(location[0], location[1]);
            isOver = rect.contains((int) event.getRawX(), (int) event.getRawY());

            switch (dropzonestates.get(zone))
            {
                case 0:
                    if (isOver)
                    {
                        for(DropZoneListener listener:listeners)
                        {
                            listener.OnDragZoneEntered(zone, item); 
                        }
                        dropzonestates.put(zone, 1);
                    }

                    break;
                case 1:
                    if (!isOver)
                    {
                        for(DropZoneListener listener:listeners)
                        {
                            listener.OnDragZoneLeft(zone, item);    
                        }
                        dropzonestates.put(zone, 0);
                    }
                    else if (isOver && event.getAction()==MotionEvent.ACTION_UP)
                    {
                        for(DropZoneListener listener:listeners)
                        {
                            listener.OnDropped(zone, item); 
                        }
                        dropzonestates.put(zone, 0);
                    }
                    break;
            }
        }
    }

    public void startDragging(final View dragView, Object item)
    {
        this.item = item;
        // Copy view Bitmap (Clone Object visual)
        ImageView view = new ImageView(mActivity);
        view.measure(dragView.getWidth(), dragView.getHeight());

        Bitmap returnedBitmap = Bitmap.createBitmap(dragView.getWidth(), dragView.getHeight(),Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(returnedBitmap);
        dragView.draw(canvas);

        view.setBackgroundDrawable(new BitmapDrawable(dragView.getResources(), returnedBitmap));

        // Set up Window
        popoup = new PopupWindow(view, dragView.getWidth(), dragView.getHeight());
        popoup.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        // set window at position
        int[] location = new int[2];
        dragView.getLocationInWindow(location);
        popoup.showAtLocation(mActivity.getWindow().getDecorView(), Gravity.NO_GRAVITY, location[0], location[1]);
        // Switch call Backs
        callbackDefault = mActivity.getWindow().getCallback();
        mActivity.getWindow().setCallback(callback);
    }

    private android.view.Window.Callback callbackDefault;

    private android.view.Window.Callback callback = new android.view.Window.Callback()
    {

        @Override
        public boolean dispatchGenericMotionEvent(MotionEvent event)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean dispatchKeyEvent(KeyEvent event)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean dispatchKeyShortcutEvent(KeyEvent event)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean dispatchTouchEvent(MotionEvent event)
        {
            checkDropZones(event);

            if (event.getAction() == MotionEvent.ACTION_DOWN)
            {
                // popoup.update((int)event.getRawX(), (int)event.getRawY(), -1,
                // -1);
            }

            if (event.getAction() == MotionEvent.ACTION_MOVE)
            {
                if (firstEvent == null) firstEvent = MotionEvent.obtain(event);

                // Log.v("EVENT","X:"+event.getRawX() + " _X:" + location[0] +
                // " __X:" + firstEvent.getRawX());
                // Log.v("EVENT","Y:"+event.getRawY() + " _Y:" + location[1] +
                // " __Y:" + firstEvent.getRawY());

                float pos_x = event.getRawX() + (-popoup.getWidth() / 2);
                float pos_y = event.getRawY() + (-popoup.getHeight() / 2);

                popoup.update((int) pos_x, (int) pos_y, -1, -1);

            }

            if (event.getAction() == MotionEvent.ACTION_UP)
            {
                popoup.dismiss();
                mActivity.getWindow().setCallback(callbackDefault);
            }

            return false;
        }

        @Override
        public boolean dispatchTrackballEvent(MotionEvent event)
        {
            return false;
        }

        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        @Override
        public void onActionModeFinished(ActionMode mode)
        {
            // TODO Auto-generated method stub

        }

        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        @Override
        public void onActionModeStarted(ActionMode mode)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAttachedToWindow()
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void onContentChanged()
        {
            // TODO Auto-generated method stub

        }

        @Override
        public boolean onCreatePanelMenu(int featureId, Menu menu)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public View onCreatePanelView(int featureId)
        {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void onDetachedFromWindow()
        {
            // TODO Auto-generated method stub

        }

        @Override
        public boolean onMenuItemSelected(int featureId, MenuItem item)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onMenuOpened(int featureId, Menu menu)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void onPanelClosed(int featureId, Menu menu)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public boolean onPreparePanel(int featureId, View view, Menu menu)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onSearchRequested()
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams attrs)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void onWindowFocusChanged(boolean hasFocus)
        {
            // TODO Auto-generated method stub

        }

        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        @Override
        public ActionMode onWindowStartingActionMode(Callback callback)
        {
            // TODO Auto-generated method stub
            return null;
        }

    };

    public interface DropZoneListener
    {

        void OnDragZoneEntered(View zone, Object item);

        void OnDragZoneLeft(View zone, Object item);

        void OnDropped(View zone, Object item);

    }
}

MainActivity.class

package com.example.dragdrop;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.example.dragdrop.DragDropManager.DropZoneListener;

public class MainActivity extends Activity implements OnLongClickListener, OnTouchListener
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DragDropManager.getInstance().init(this);

        Button b1 = (Button) findViewById(R.id.button1);
        Button b2 = (Button) findViewById(R.id.button2);
        Button b3 = (Button) findViewById(R.id.button3);

        EditText et1 = (EditText) findViewById(R.id.editText1);
        TextView tv1 = (TextView) findViewById(R.id.textView1);

        Button b4 = (Button) findViewById(R.id.button4);
        Button b5 = (Button) findViewById(R.id.button5);
        Button b6 = (Button) findViewById(R.id.button6);

        b1.setOnTouchListener(this);
        b2.setOnLongClickListener(this);
        b3.setOnTouchListener(this);

        et1.setOnTouchListener(this);
        tv1.setOnTouchListener(this);

        DragDropManager.getInstance().addDropZone(b4, dropZoneListener1);
        DragDropManager.getInstance().addDropZone(b5, dropZoneListener1);
        DragDropManager.getInstance().addDropZone(b6, dropZoneListener1);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    DropZoneListener dropZoneListener1 = new DropZoneListener()
    {

        @Override
        public void OnDropped(View zone, Object item)
        {
            Log.v("ddddd","drop time");
            switch(zone.getId())
            {
                case R.id.button4:
                    if (item instanceof String) 
                        ((Button)zone).setText("DROP ITEM OK");
                    else    
                        ((Button)zone).setText("DROP ITEM ERR");

                    break;
                case R.id.button5:
                    ((Button)zone).setText("DROP");
                    break;
                case R.id.button6:
                    if (item instanceof Integer) 
                        ((Button)zone).setText("DROP ITEM OK");
                    else    
                        ((Button)zone).setText("DROP ITEM ERR");
                    break;
            }

        }

        @Override
        public void OnDragZoneLeft(View zone, Object item)
        {

            switch(zone.getId())
            {
                case R.id.button4:
                    ((Button)zone).setText("LEFT");
                    break;
                case R.id.button5:
                    ((Button)zone).setText("LEFT");
                    break;
                case R.id.button6:
                    ((Button)zone).setText("LEFT");
                    break;
            }
        }

        @Override
        public void OnDragZoneEntered(View zone, Object item)
        {
            switch(zone.getId())
            {
                case R.id.button4:
                    if (item instanceof String) 
                        ((Button)zone).setText("ENTER ITEM OK");
                    else    
                        ((Button)zone).setText("ENTER ITEM ERR");
                    break;
                case R.id.button5:
                    ((Button)zone).setText("ENTER");
                    break;
                case R.id.button6:
                    if (item instanceof Integer) 
                        ((Button)zone).setText("ENTER ITEM OK");
                    else    
                        ((Button)zone).setText("ENTER ITEM ERR");
                    break;
            }
        }
    };

    @Override
    public boolean onLongClick(View v)
    {
        DragDropManager.getInstance().startDragging(v, 0);
        return false;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        DragDropManager.getInstance().startDragging(v, "String");
        return false;
    }

}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="14dp"
        android:text="Click" />

    <Button
        android:id="@+id/button2"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignLeft="@+id/button1"
        android:layout_below="@+id/button1"
        android:layout_marginTop="29dp"
        android:text="Long" />

    <Button
        android:id="@+id/button3"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignLeft="@+id/button2"
        android:layout_below="@+id/button2"
        android:layout_marginTop="16dp"
        android:text="Click" />

    <Button
        android:id="@+id/button6"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_alignTop="@+id/button3"
        android:layout_marginLeft="39dp"
        android:layout_toRightOf="@+id/button3"
        android:text="Drop3" />

    <Button
        android:id="@+id/button5"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignLeft="@+id/button4"
        android:layout_centerVertical="true"
        android:text="Drop2" />

    <Button
        android:id="@+id/button4"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_above="@+id/button5"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="35dp"
        android:layout_marginRight="20dp"
        android:text="Drop1" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button3"
        android:layout_below="@+id/button3"
        android:layout_marginTop="17dp"
        android:ems="10" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button6"
        android:layout_alignParentLeft="true"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

我从MobileAnarchyWidget获得了一些启示,但我改进了一些东西。

正如您所看到的,我使用PopupWindow创建了拖动效果,甚至克隆了可拖动对象的可视部分。另外,我不需要使用任何布局的一部分。只需将DragDropManager.class放入您的项目中即可。无需更改。没有额外的资源。如果一个区域完全/部分覆盖另一个区域,则可以同时击中更多区域。您可以拖动任何至少是视图的内容。我在Activity窗口上切换回调,因此当您拖动某些内容时,其他内容无法访问事件。在这个解决方案中,您永远不会失去对可拖动对象的关注,并且当您从屏幕上抬起手指时,DragDrop将自动结束(Activity重新获得控制回调)。

我没有时间向您展示所有使用组合。但是,正如您所看到的,只有一个DropZoneListener。您可以使用更多,但请记住,所有侦听器都会被调用,并且所有更改的拖动状态都会被发送到每个侦听器。

例如: Dropzones D1、D2; Listener L1、L2;

如果D1或D2更改 L1(Dx)和L2(Dx)

如果D1和D2更改 L1(D1、D2)和L2(D1、D2)

但这很好,因为您知道它是否被放置在其他地方。我忘记了DragItem是对象,因此当其被放下时,您必须解析对象的类型。但这也很好,因为当您使用片段时,永远不知道可以拖动什么类型的数据。

在我的解决方案中,我会检查对象类型级别。如果对象不受拖放区支持,那么您将知道。


1
我尝试了你的示例,但在第一次拖放后就卡住了,你有任何修复bug的方法吗? - user1234813
哎呀,我不行。这是很久以前的事了。它确实可以在2.2 Froyo上运行。但似乎在更新的版本上不行了。想法是从Activity onTouch视图中捕获Window回调DispatchMouseEvent,并将对象位图缓冲区复制到PopupWindow中,其中x、y由mousemove更改。 - Mertuarez

-3
TouchEvent:TouchDown -> LockItemOnTouchPoint FollowTouchDirections -> UpdateItemPosition TouchEvent:TouchUp -> LockItemPosition
触摸事件:按下 -> 锁定触点上的项目 跟随触摸方向 -> 更新项目位置 触摸事件:抬起 -> 锁定项目位置

你能否简要解释一下?或者你能分享一篇解释这个的链接吗? - Chandra Sekhar
这只是解决这个问题的一般方法。请按照@himanshu给出的链接进行操作。 - Matthias Bruns
你能分享一段代码片段,解释如何在触摸点上锁定物品以及如何跟随触摸方向吗? - Chandra Sekhar
3
我见过的最傲慢的回答...如果你努力解释一下你写的内容,那就好了。 - azfar
同意@azfar的观点,无法相信Chandra Sekhar甚至将其标记为正确答案。 - Leo supports Monica Cellio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接