将图像视图拖动到特定位置
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 不同的值.
我正在尝试创建一个可拖动的 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 不同的值.