Android的拖放技术

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

}

布局文件:fragment_dragdrop_regin。xml

<?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>


image.xml

<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"/>


代码我注释的很清楚。看看就可以拖动复制一个ImageView 了,这是一件很神奇的事情。

你可能感兴趣的:(Android的拖放技术)