在android3.0以前的版本,拖放一个视图需要使用触摸事件,而且拖动到指定区域还需要判断坐标是否落到这一区域,比较麻烦。从Android3.0以后,android SDK开始支持视图的拖放操作。
建立拖动阴影,可以直接使用View.DragShadowBuilder类,也可以继承View.DragShadowBuilder类,实现自定义的拖动阴影类。
package com.example.firstdragdrop_01; import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.view.View; import android.widget.ImageView; @SuppressLint("NewApi") public class MyGragShadowBuilder extends View.DragShadowBuilder{ //拖动阴影的区域 private static Drawable shadow; //存储新绘制的拖动阴影图像 private static Bitmap newbitmap; public MyGragShadowBuilder(View view){ super(view); shadow = new ColorDrawable(Color.LTGRAY); } @SuppressLint("NewApi") //在这个方法中绘制拖动阴影图像,也就是实例化newBitmap变量 @Override public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { // TODO Auto-generated method stub //设置拖动阴影的宽度和高度,放大为原来的1.5倍 int width,height; width = (int) (getView().getWidth()*1.5); height = (int) (getView().getHeight()*1.5); //设置拖动阴影图像绘制的区域 shadow.setBounds(width, height, width, height); //设置拖动阴影的高度和宽度 shadowSize.set(width, height); //设置手指和鼠标在拖动阴影的位置 shadowTouchPoint.set(width/2,height/2); if(getView() instanceof ImageView){ //getView方法返回的值就是构造方法传入的v的值 ImageView imageView = (ImageView) getView(); //获取imageView控件的Drawable对象 Drawable drawable = imageView.getDrawable(); //获取ImageView的图像资源(Bitmap对象) Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap(); //根据拖动阴影图像的尺寸创建一个新的可绘制的Bitmap图像 newbitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); //将Canvas与Bitmap关联在一起 Canvas canvas = new Canvas(newbitmap); //将图像绘制在画布上(图像放大50%)。注意,这里的画布只是与newBitmap绑定的完全独立的,现在还没有正式将图像绘制在拖动 //阴影图像上。实际上就是将newBitmap放大50%,然后放置在newBitmap上 canvas.drawBitmap(bitmap, new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()), new Rect(0, 0, width, height), null); } super.onProvideShadowMetrics(shadowSize, shadowTouchPoint); } @Override public void onDrawShadow(Canvas canvas) { // TODO Auto-generated method stub //将图像正式绘制在拖动阴影图像上 canvas.drawBitmap(newbitmap, 0, 0, new Paint()); super.onDrawShadow(canvas); } }现在来实现主窗口,实现OnDragListener类。
package com.example.firstdragdrop_01; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.view.DragEvent; import android.view.Menu; import android.view.View; import android.view.View.OnDragListener; import android.widget.FrameLayout; import android.widget.FrameLayout.LayoutParams; import android.widget.ImageView; @SuppressLint("NewApi") public class MainActivity extends Activity implements OnDragListener{ private FrameLayout dragdropRegin; private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dragdropRegin = (FrameLayout) findViewById(R.id.fragment_dragdrop_regin); imageView = (ImageView) findViewById(R.id.imageView); //为目标区域设置拖动监听器 dragdropRegin.setOnDragListener(this); //为要拖动的视图设置长按单击事件监听器 imageView.setOnLongClickListener(new View.OnLongClickListener() { //长按ImageView控件后开始拖动 @Override public boolean onLongClick(View v) { // TODO Auto-generated method stub //创建拖动阴影对象 View.DragShadowBuilder myShadow = new MyGragShadowBuilder(imageView); //开始拖动 v.startDrag(null, myShadow, null, 0); return true; } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @SuppressLint("NewApi") @Override public boolean onDrag(View v, DragEvent event) { // TODO Auto-generated method stub int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: System.out.println("drag_started"); break; case DragEvent.ACTION_DRAG_ENTERED: System.out.println("drag_entered"); break; case DragEvent.ACTION_DRAG_LOCATION: System.out.println("drag_location x="+event.getX()+"y="+event.getY()); break; case DragEvent.ACTION_DRAG_EXITED: System.out.println("drag_exited"); break; case DragEvent.ACTION_DROP: System.out.println("drag_drop"); //当到达目标区域时,创建一个新的ImagmeView 对象 ImageView imageView =(ImageView) getLayoutInflater().inflate(R.layout.image, null); //由于FrameLayout不能直接使用坐标设置子视图的位置,所以这里使用左边距和顶边距,注意引包要引入 android.widget.FrameLayout.LayoutParams LayoutParams layoutParams =new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); layoutParams.leftMargin = (int) (event.getX()); layoutParams.topMargin = (int) (event.getY()); dragdropRegin.addView(imageView, layoutParams); break; case DragEvent.ACTION_DRAG_ENDED: System.out.println("drag_ended"); break; default: return false; } return true; } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <FrameLayout android:id="@+id/fragment_dragdrop_regin" android:layout_width="fill_parent" android:layout_height="300dp" android:background="#F00" /> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:layout_gravity="center" android:src="@drawable/ic_launcher" /> </LinearLayout>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="50dp" android:src="@drawable/ic_launcher"/>