如何在android 2.2中实现拖放?

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

TouchEvent:TouchDown – > LockItemOnTouchPoint

FollowTouchDirections – > UpdateItemPosition

TouchEvent:TouchUp – > LockItemPosition

嗨,经过很长时间才能获得成功的拖放在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; } } 

在这之后创build一个类并像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> 

好吧,现在开心,我做了我的工作,也开心,因为我满意我的工作,我希望这会帮助你。 和给我的方式的链接如下。

  • rxwen -博客-东西
  • Android的拖拽和落基

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来创builddragEfect,即使我从可拖动的对象中克隆了视觉部分。 另外我不必使用布局的任何部分。 简单的把DragDropManager.class放到你的项目中。 不需要改变。 没有额外的资源。 如果一个区域完全/部分覆盖另一个区域,则可以一次击中更多区域。 你可以拖动任何东西至less是查看。 我在“活动”窗口上切换callback,所以当你拖动一些东西时,没有其他事物可以访问。 在这个解决scheme中,你永远不会从Draggable中失去焦点,而且当你从屏幕上拾起手指时,DragDrop会自动结束(callback的活动重新获得控制权)。

我没有时间向您展示所有使用的组合。 但是你可以看到有一个DropZoneListener。 您可以使用更多但记住所有监听器被调用,并且全部改变拖动状态被发送给每个监听器。

例如:Dropzones D1,D2; 听众L1,L2;

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

如果D1和D2改变L1(D1,D2)和L2(D1,D2)

但它是好的,因为你知道它是否在其他地方掉落。 而且我忘了DragItem是Object,所以当你放弃时,你必须parsing对象的types。 但是这也是好事,因为当你使用片段时,你永远不知道可以拖动哪种数据。

在我的解决scheme中,我检查对象types级别。 如果dragzone不支持的对象比你知道的。

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; } } 

);