将图像视图拖动到特定位置

Dragging an imageview to certain position

我正在尝试创建一个可拖动的 imageView("chatHead" 在代码中,有点像 Facebook 的聊天头)

我按照 android 网站上的说明进行操作,但无论我将图像视图拖动到哪里,它总是在左上角结束。 (x,y坐标为(0,0) ~ (90,90))

后来我发现问题是这样的情况:MotionEvent.ACTION_MOVE 是 只有 当我的触摸在 imageView 位置周围时才输入。

而当我拖离imageView远一点时,ACTION_MOVE就不再进入了。相反,案例 DragEvent.ACTION_DRAG_EXIT 被执行。

谁能告诉我如何扩展要执行的 ACTION_MOVE 的区域,或者有什么问题。我想将 imageView 定位在屏幕上我想要的任何位置。
(你可能只关注 onDragListener,MyDragShadowBuilder 是自定义扩展 DragShawdowBuilder,onLongClickListener 只是触发拖动)

如何在应用程序关闭时保持 imageView?

public class ChatHead extends Service {

private WindowManager windowManager;
private ImageView chatHead;
private WindowManager.LayoutParams params;
private final String CHAT_TAG ="CHAT";
private int cor_x = 0;
private int cor_y = 0;



@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override public void onCreate() {
    super.onCreate();
    ImageView image = new ImageView(this);
    Log.d("", "created");
    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    chatHead = new ImageView(this);
    chatHead.setTag(CHAT_TAG);
    chatHead.setImageResource(R.drawable.chat_icon);

     params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.TOP | Gravity.LEFT;
    params.x = 300;
    params.y = 300;



    chatHead.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {



                    ClipData.Item item = new ClipData.Item(v.getTag().toString());


                    String[] mimeTypes =  {ClipDescription.MIMETYPE_TEXT_PLAIN};
                    ClipData dragData = new ClipData(v.getTag().toString(), mimeTypes,item);

                    View.DragShadowBuilder myShadow = new MyDragShadowBuilder(chatHead);

                    // Starts the drag

                    v.startDrag(dragData,  // the data to be dragged
                            myShadow,      // the drag shadow builder
                            null,          // no need to use local data
                            0              // flags (not currently used, set to 0)
                    );

            return false;}

    });



    chatHead.setOnDragListener(new View.OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {

            //cor_x = ((int) chatHead.getX());
            //cor_y = ((int) chatHead.getY());

            switch (event.getAction()){
                case DragEvent.ACTION_DRAG_ENTERED : { Log.d("", "x:"+ event.getX()+"y:"+event.getY());break;}
                case DragEvent.ACTION_DRAG_STARTED : { Log.d("", "x:"+ event.getX()+"  y:"+event.getY());break;}

                case MotionEvent.ACTION_MOVE:  {
                    cor_x = ((int) event.getX());
                    cor_y = ((int) event.getX());
                    Log.d("", "x:"+ cor_x+"  y:"+cor_y);
                    break;}
                case DragEvent.ACTION_DRAG_EXITED:{
                    Log.d("", "x:"+ cor_x+"  y:"+cor_y);
                    break;
                }


                case DragEvent.ACTION_DRAG_ENDED   :  {
                    if(windowManager!=null && params!=null){
                        params.x = cor_x;
                        params.y = cor_y;
                        Log.d("", "x:"+ cor_x+"  y:"+cor_y);
                        windowManager.removeView(chatHead);
                        windowManager.addView(chatHead, params);
                    }

                    return false;
                }

            }


            return false;
        }
    });

    windowManager.addView(chatHead, params);


}

如果我明白你的意思,你的问题是你得不到 MotionEvent.ACTION_MOVE 除非你的手指在你的图像上方。

那是因为 DragListener 的概念是注册该侦听器的视图接受事件。因此,在您的布局中注册这些事件的唯一视图是 chatHead,他只获取在他之上发生的事件。

因此,如果您想获得布局中的所有事件,您必须注册占据整个屏幕的视图 space。所以最快的解决方案是用占据整个屏幕的容器包装视图,并将它而不是 chatHead 注册到 DragListener。像这样的东西:

  windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    RelativeLayout container = new RelativeLayout(this);


    params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);

    chatHead = new ImageView(this);
    chatHead.setTag(CHAT_TAG);
    chatHead.setImageResource(R.drawable.chat_icon);

    RelativeLayout.LayoutParams chatHeadParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    chatHeadParams.addRule(Gravity.TOP | Gravity.LEFT)  ;
    chatHeadParams.leftMargin = 300;
    chatHeadParams.topMargin = 300;

    container.addView(chatHead, chatHeadParams);
    windowManager.addView(container, params);

并更改行:

    chatHead.setOnLongClickListener(new View.OnLongClickListener() {

至:

    container.setOnLongClickListener(new View.OnLongClickListener() {

您还可以调整其他内容,因为 DragEvent event.getX() 和 event.getX() 将根据视图本身和 DragEvent.Action 类型 return 不同的值.