有没有办法在 API 8 Android 中实现拖放功能?
看这里,但它出现在 API 11 之后。
我需要将视图从一个拖到LinearLayout
另一个。我可以在 API 8 上实现这个吗?
像这样试试
import android.app.Activity;
import android.content.ClipData;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
ListView source = null;
TextView target1 = null;
TextView target2 = null;
TextView target3 = null;
String[] listItems = {"Samsung", "Apple", "Google", "Nokia"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
source = (ListView)findViewById(R.id.dragSource);
target1 = (TextView) findViewById(R.id.dragTarget1);
target2 = (TextView) findViewById(R.id.dragTarget2);
target3 = (TextView) findViewById(R.id.dragTarget3);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listItems);
source.setAdapter(adapter);
// Start Drag
source.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String item = listItems[position];
ClipData data = ClipData.newPlainText("DragIt", item);
source.startDrag(data, new MyShadowBuilder(view), null, 0);
}
});
// Handle Drag
target1.setOnDragListener(new MyDragListener());
target2.setOnDragListener(new MyDragListener());
target3.setOnDragListener(new MyDragListener());
}
// Drag Shadow
private class MyShadowBuilder extends DragShadowBuilder {
public MyShadowBuilder(View v) {
super(v);
}
@Override
public void onDrawShadow(Canvas canvas) {
// Set Drag image background or anything you want
int width = getView().getWidth();
int height = getView().getHeight();
Paint paint = new Paint();
paint.setColor(0x55858585);
canvas.drawRect(new Rect(0, 0, width, height), paint);
super.onDrawShadow(canvas);
}
@Override
public void onProvideShadowMetrics(Point shadowSize,
Point shadowTouchPoint) {
int width = getView().getWidth();
int height = getView().getHeight();
shadowSize.set(width, height);
shadowTouchPoint.set(width/2, height);
}
}
// Drag Listener
private class MyDragListener implements OnDragListener {
private final int DEFAULT_BG_COLOR = 0xFF858585;
private final int HIGHLIGHT_BG_COLOR = 0xFF0000FF;
@Override
public boolean onDrag(View v, DragEvent event) {
if(event.getAction() == DragEvent.ACTION_DRAG_ENTERED) {
v.setBackgroundColor(HIGHLIGHT_BG_COLOR);
}
else if(event.getAction() == DragEvent.ACTION_DRAG_EXITED) {
v.setBackgroundColor(DEFAULT_BG_COLOR);
}
else if(event.getAction() == DragEvent.ACTION_DROP) {
// Perform drop
ClipData clip = event.getClipData();
ClipData.Item item = clip.getItemAt(0);
String text = item.getText().toString();
((TextView) v).setText(text);
v.setBackgroundColor(DEFAULT_BG_COLOR);
}
// Send true to listen All Drag Events.
return true;
}
}
}
XML就像:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="161dp"
android:layout_height="fill_parent"
android:background="#FF858585"
android:orientation="vertical" >
<TextView
android:id="@+id/dragTarget1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/dragTarget2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/dragTarget3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/dragSource"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Try another approach by using WindowManager :
package com.example.cooldraganddrop;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
public class CoolDragAndDropGridView extends SpanVariableGridView implements `View.OnTouchListener {`
private static final int ITEM_HOVER_DELAY = 450;
private int mDragPointX;
private int mDragPointY;
private int mDragOffsetX;
private int mDragOffsetY;
private int mDragPosition = AdapterView.INVALID_POSITION;
private int mDropPosition = AdapterView.INVALID_POSITION;
private int mCurrentPosition = AdapterView.INVALID_POSITION;
private Runnable mDelayedOnDragRunnable = null;
ScrollingStrategy mScrollingStrategy = null;
WindowManager mWindowManager = null;
WindowManager.LayoutParams mWindowParams = null;
private ImageView mDragImageView = null;
private boolean mDragAndDropStarted = false;
private DragAndDropListener mDragAndDropListener = null;
private OnTrackTouchEventsListener mOnTrackTouchEventsListener = null;
public static interface OnTrackTouchEventsListener {
void trackTouchEvents(final MotionEvent motionEvent);
};
public static interface DragAndDropListener {
void onDragItem(int from);
void onDraggingItem(int from, int to);
void onDropItem(int from, int to);
boolean isDragAndDropEnabled(int position);
}
public CoolDragAndDropGridView(Context context) {
super(context);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
private void initialize() {
setOnTouchListener(this);
setChildrenDrawingOrderEnabled(true);
}
public void startDragAndDrop() {
mDragAndDropStarted = true;
}
public void setDragAndDropListener(DragAndDropListener dragAndDropListener) {
mDragAndDropListener = dragAndDropListener;
}
private void destroyDragImageView() {
if (mDragImageView != null) {
mWindowManager.removeView(mDragImageView);
BitmapDrawable bitmapDrawable = (BitmapDrawable) mDragImageView.getDrawable();
if (bitmapDrawable != null) {
final Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
}
mDragImageView.setImageDrawable(null);
mDragImageView = null;
}
}
private ImageView createDragImageView(final View v, final int x, final int y) {
v.destroyDrawingCache();
v.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(v.getDrawingCache());
mDragPointX = x - v.getLeft();
mDragPointY = y - v.getTop();
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.alpha = 0.7f;
mWindowParams.windowAnimations = 0;
ImageView iv = new ImageView(getContext());
iv.setBackgroundColor(Color.parseColor("#ff555555"));
iv.setImageBitmap(bm);
mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
mWindowManager.addView(iv, mWindowParams);
return iv;
}
private void startDrag(final int x, final int y) {
final View v = getChildAt(mDragPosition);
destroyDragImageView();
mDragImageView = createDragImageView(v, x, y);
v.setVisibility(View.INVISIBLE);
if (mDragAndDropListener != null) {
mDragAndDropListener.onDragItem(mDragPosition);
}
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {
if (mCurrentPosition == -1)
return i;
else if (i == childCount - 1)
return mCurrentPosition;
else if (i >= mCurrentPosition)
return i + 1;
return i;
}
private void onDrop() {
destroyDragImageView();
removeCallbacks(mDelayedOnDragRunnable);
View v = getChildAt(mDropPosition);
v.setVisibility(View.VISIBLE);
v.clearAnimation();
if (mDragAndDropListener != null && mDropPosition != AdapterView.INVALID_POSITION) {
mDragAndDropListener.onDropItem(mDragPosition, mDropPosition);
}
mDragPosition = mDropPosition = mCurrentPosition = AdapterView.INVALID_POSITION;
mDragAndDropStarted = false;
}
public void setScrollingStrategy(ScrollingStrategy scrollingStrategy) {
mScrollingStrategy = scrollingStrategy;
}
private void onDrag(final int x, final int y) {
if (mScrollingStrategy != null && mScrollingStrategy.performScrolling(x, y, this)) {
removeCallbacks(mDelayedOnDragRunnable);
return;
}
final int tempDropPosition = pointToPosition(mCurrentPosition, x, y);
if (mDragAndDropListener != null && mDropPosition != tempDropPosition && tempDropPosition != AdapterView.INVALID_POSITION) {
removeCallbacks(mDelayedOnDragRunnable);
if (mDragAndDropListener.isDragAndDropEnabled(tempDropPosition)) {
mDropPosition = tempDropPosition;
mDelayedOnDragRunnable = new Runnable() {
@Override
public void run() {
mDragAndDropListener.onDraggingItem(mCurrentPosition, tempDropPosition);
performDragAndDropSwapping(mCurrentPosition, tempDropPosition);
final int nextDropPosition = pointToPosition(tempDropPosition, x, y);
if (nextDropPosition == AdapterView.INVALID_POSITION) {
mCurrentPosition = mDropPosition = tempDropPosition;
}
}
};
postDelayed(mDelayedOnDragRunnable, ITEM_HOVER_DELAY);
} else {
mDropPosition = mDragPosition;
}
}
if (mDragImageView != null) {
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowManager.updateViewLayout(mDragImageView, mWindowParams);
}
}
public void setOnTrackTouchEventListener(OnTrackTouchEventsListener onTrackTouchEventsListener) {
mOnTrackTouchEventsListener = onTrackTouchEventsListener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mOnTrackTouchEventsListener != null) {
mOnTrackTouchEventsListener.trackTouchEvents(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (mDragAndDropListener != null && mDragAndDropStarted) {
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(true);
return launchDragAndDrop(event);
}
break;
default:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.onInterceptTouchEvent(event);
}
private boolean launchDragAndDrop(final MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
mCurrentPosition = mDragPosition = mDropPosition = pointToPosition(mDragPosition, x, y);
if (mDragPosition != AdapterView.INVALID_POSITION && mDragAndDropListener.isDragAndDropEnabled(mDragPosition)) {
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
startDrag(x, y);
return true;
}
return false;
}
@Override
public boolean onTouch(View view, MotionEvent event) {
if (mDragPosition != AdapterView.INVALID_POSITION && mDragImageView != null) {
final int x = (int) event.getX();
final int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
onDrag(x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
onDrop();
resetLongClickTransition();
getParent().requestDisallowInterceptTouchEvent(false);
return false;
default:
}
return true;
}
return false;
}
}
Sample using this approach of a drag and drop is here