我的RelativeLayout
有一张图片。我只是试图让它在整个布局中可拖动。问题是每次我拖放时,它都会回到原来的位置。这是我的
drag_layout.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"
android:id="@+id/mainView"
android:background="@drawable/bg_animation"
tools:context="com.example.activities.AnimationActivity">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_launcher"
android:id="@+id/appLogo"
android:layout_alignBottom="@+id/ba_cell_animation"
android:layout_centerHorizontal="true"
android:layout_marginBottom="47dp" />
</RelativeLayout>
AnimationActivity.java
public class AnimationActivity extends ActionBarActivity implements View.OnTouchListener, View.OnDragListener {
static ImageView mLogo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animation);
setTitle("Animation");
Typeface mAnimPromptTF = Typeface.createFromAsset(getAssets(), "fonts/Jelloween - Machinato ExtraLight.ttf");
Typeface mAnimBonusTF = Typeface.createFromAsset(getAssets(), "fonts/Jelloween - Machinato SemiBold Italic.ttf");
mAnimPrompt = (TextView) findViewById(R.id.anim_prompt);
mAnimBonus = (TextView) findViewById(R.id.anim_bonus);
mAnimPrompt.setTypeface(mAnimPromptTF);
mAnimBonus.setTypeface(mAnimBonusTF);
mLogo = (ImageView) findViewById(R.id.appLogo);
mLogo.setOnTouchListener(this);
findViewById(R.id.mainView).setOnDragListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent e) {
// TODO Auto-generated method stub
if (e.getAction() == MotionEvent.ACTION_DOWN) {
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDrag(null, shadowBuilder, v, 0);
v.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
@Override
public boolean onDrag(View v, DragEvent e) {
// TODO Auto-generated method stub
switch (e.getAction()) {
case DragEvent.ACTION_DROP:
View view = (View) e.getLocalState();
ViewGroup from = (ViewGroup) view.getParent();
from.removeView(view);
RelativeLayout to = (RelativeLayout) v;
to.addView(view);
view.setVisibility(View.VISIBLE);
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
break;
// the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
break;
default:
break;
}
return true;
}
@Override
public void onBackPressed() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
}
我尝试了以下所有链接,但仍然不知道我哪里出错:
http://www.vogella.com/tutorials/AndroidDragAndDrop/article.html
http://codingjunkie.net/android-drag-and-drop-part1
http://tech-papers.org/android-drag-and-drop
我真的尝试了很多。
答案 0 :(得分:2)
我终于找到了解决方案请参考以下代码: 就像这段代码一样简单。
@Override
public boolean onTouch(View v, MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDrag(null, shadowBuilder, v, 0);
return true;
}
return false;
}
@Override
public boolean onDrag(View mainView, DragEvent e) {
View view = (View) e.getLocalState();
switch (e.getAction()) {
case DragEvent.ACTION_DROP:
view.setX(e.getX() - (view.getWidth() / 2));
view.setY(e.getY() - (view.getHeight() / 2));
view.invalidate();
mainView.invalidate();
return true;
case DragEvent.ACTION_DRAG_STARTED:
return true;
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DRAG_ENDED:
mainView.invalidate();
return true;
default:
break;
}
return true;
}
答案 1 :(得分:0)
尝试使用此代码进行拖放操作,您可以参考此link,它可以使用它。
// Create a string for the ImageView label
private static final String IMAGEVIEW_TAG = "icon bitmap"
// Creates a new ImageView
ImageView imageView = new ImageView(this);
// Sets the bitmap for the ImageView from an icon bit map (defined elsewhere)
imageView.setImageBitmap(mIconBitmap);
// Sets the tag
imageView.setTag(IMAGEVIEW_TAG);
...
// Sets a long click listener for the ImageView using an anonymous listener object that
// implements the OnLongClickListener interface
imageView.setOnLongClickListener(new View.OnLongClickListener() {
// Defines the one method for the interface, which is called when the View is long-clicked
public boolean onLongClick(View v) {
// Create a new ClipData.
// This is done in two steps to provide clarity. The convenience method
// ClipData.newPlainText() can create a plain text ClipData in one step.
// Create a new ClipData.Item from the ImageView object's tag
ClipData.Item item = new ClipData.Item(v.getTag());
// Create a new ClipData using the tag as a label, the plain text MIME type, and
// the already-created item. This will create a new ClipDescription object within the
// ClipData, and set its MIME type entry to "text/plain"
ClipData dragData = new ClipData(v.getTag(),ClipData.MIMETYPE_TEXT_PLAIN,item);
// Instantiates the drag shadow builder.
View.DragShadowBuilder myShadow = new MyDragShadowBuilder(imageView);
// 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)
);
}
}
自定义阴影构建器
private static class MyDragShadowBuilder extends View.DragShadowBuilder {
// The drag shadow image, defined as a drawable thing
private static Drawable shadow;
// Defines the constructor for myDragShadowBuilder
public MyDragShadowBuilder(View v) {
// Stores the View parameter passed to myDragShadowBuilder.
super(v);
// Creates a draggable image that will fill the Canvas provided by the system.
shadow = new ColorDrawable(Color.LTGRAY);
}
// Defines a callback that sends the drag shadow dimensions and touch point back to the
// system.
@Override
public void onProvideShadowMetrics (Point size, Point touch)
// Defines local variables
private int width, height;
// Sets the width of the shadow to half the width of the original View
width = getView().getWidth() / 2;
// Sets the height of the shadow to half the height of the original View
height = getView().getHeight() / 2;
// The drag shadow is a ColorDrawable. This sets its dimensions to be the same as the
// Canvas that the system will provide. As a result, the drag shadow will fill the
// Canvas.
shadow.setBounds(0, 0, width, height);
// Sets the size parameter's width and height values. These get back to the system
// through the size parameter.
size.set(width, height);
// Sets the touch point's position to be in the middle of the drag shadow
touch.set(width / 2, height / 2);
}
// Defines a callback that draws the drag shadow in a Canvas that the system constructs
// from the dimensions passed in onProvideShadowMetrics().
@Override
public void onDrawShadow(Canvas canvas) {
// Draws the ColorDrawable in the Canvas passed in from the system.
shadow.draw(canvas);
}
}
拖动事件侦听器
// Creates a new drag event listener
mDragListen = new myDragEventListener();
View imageView = new ImageView(this);
// Sets the drag event listener for the View
imageView.setOnDragListener(mDragListen);
...
protected class myDragEventListener implements View.OnDragListener {
// This is the method that the system calls when it dispatches a drag event to the
// listener.
public boolean onDrag(View v, DragEvent event) {
// Defines a variable to store the action type for the incoming event
final int action = event.getAction();
// Handles each of the expected events
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
// Determines if this View can accept the dragged data
if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
// As an example of what your application might do,
// applies a blue color tint to the View to indicate that it can accept
// data.
v.setColorFilter(Color.BLUE);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
// returns true to indicate that the View can accept the dragged data.
return true;
}
// Returns false. During the current drag and drop operation, this View will
// not receive events again until ACTION_DRAG_ENDED is sent.
return false;
case DragEvent.ACTION_DRAG_ENTERED:
// Applies a green tint to the View. Return true; the return value is ignored.
v.setColorFilter(Color.GREEN);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
return true;
case DragEvent.ACTION_DRAG_LOCATION:
// Ignore the event
return true;
case DragEvent.ACTION_DRAG_EXITED:
// Re-sets the color tint to blue. Returns true; the return value is ignored.
v.setColorFilter(Color.BLUE);
// Invalidate the view to force a redraw in the new tint
v.invalidate();
return true;
case DragEvent.ACTION_DROP:
// Gets the item containing the dragged data
ClipData.Item item = event.getClipData().getItemAt(0);
// Gets the text data from the item.
dragData = item.getText();
// Displays a message containing the dragged data.
Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG);
// Turns off any color tints
v.clearColorFilter();
// Invalidates the view to force a redraw
v.invalidate();
// Returns true. DragEvent.getResult() will return true.
return true;
case DragEvent.ACTION_DRAG_ENDED:
// Turns off any color tinting
v.clearColorFilter();
// Invalidates the view to force a redraw
v.invalidate();
// Does a getResult(), and displays what happened.
if (event.getResult()) {
Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG);
} else {
Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG);
}
// returns true; the value is ignored.
return true;
// An unknown action type was received.
default:
Log.e("DragDrop Example","Unknown action type received by OnDragListener.");
break;
}
return false;
}
};
答案 2 :(得分:0)
将DragEvent.ACTION_DROP案例更改为以下
case DragEvent.ACTION_DROP:
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(e.getX(), e.getY(), 0, 0);
break;
您可以直接复制粘贴上面的代码。
答案 3 :(得分:0)
这是一个按钮,但适用于所有视图。我的按钮位于RelativeLayout中,如果您的视图位于LinearLayout中,则必须改为创建LinearLayout.LayoutParams
。
代码:
addBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_MOVE ){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(view.getLayoutParams().width, view.getLayoutParams().height);
params.setMargins(
(int) (motionEvent.getRawX() - view.getWidth()/2), // margin left
(int) (motionEvent.getRawY() - (view.getHeight()/2)), // margin top
(int) (params.width - (motionEvent.getRawX() + view.getWidth()/2)), // margin right
(int) (params.height - (motionEvent.getRawY() - (view.getHeight()/2))) // margin bottom
);
view.setLayoutParams(params);
}
return true;
}
});