Gee*_*ugs 17 android drag-and-drop
我真的有时间搞清楚这个,到目前为止找不到任何有相关经验的朋友.在我发布我的第一个应用程序之前,这是我非常最后的功能,所以它让我疯狂,因为它已经陷入困境,最终即将结束!
如果我将物体放在可接受的区域,我的拖放效果会很好.但是,如果丢弃在其他地方我没有得到事件,并且在失败的拖放操作后无法清理.我需要触发ACTION_DRAG_ENDED事件.但是,如果我使用值为true的ACTION_DRAG_STARTED响应(意味着它可以接受该对象),则仅触发(根据文档).问题是ACTION_DRAG_STARTED没有解雇!
所以我认为问题的关键在于我没有得到ACTION_DRAG_STARTED.我在这里放置了所有相关的拖拽代码(或至少几乎全部):
private OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Item current = (Item) ((View) v.getTag()).getTag();
//ClipData data = ClipData.newPlainText("test", "testText");
View dragView = (View) v.getTag();
DragShadowBuilder shadowBuilder = new ItemDragShadowBuilder(dragView,
new Point(v.getWidth()/2, v.getHeight()/2));
dragSource = dragView;
v.startDrag(null, shadowBuilder, current, 0);
dragView.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
};
private static class ItemDragShadowBuilder extends View.DragShadowBuilder {
private Point touchPoint = null;
private Point sizePoint = null;
private View dragView = null;
public ItemDragShadowBuilder(View dragView, Point touchPoint) {
super();
sizePoint = new Point(dragView.getWidth(), dragView.getHeight());
this.touchPoint = touchPoint;
this.dragView = dragView;
}
@Override
public void onProvideShadowMetrics (Point size, Point touch) {
size.set(sizePoint.x, sizePoint.y);
touch.set(touchPoint.x,touchPoint.y);
}
@Override
public void onDrawShadow(Canvas canvas) {
dragView.setBackgroundColor(dragView.getContext().getResources().getColor(R.color.holoBlueDark));
dragView.draw(canvas);
//canvas.setBitmap(dragView.getDrawingCache());
//canvas.drawColor(Color.WHITE);
//dragView.setAlpha(1);
//How do I change the transparency?
//super.onDrawShadow(canvas);
}
}
private View dragSource = null;
private OnDragListener onDragEventListener = new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString() + " started", Toast.LENGTH_SHORT/8).show();
return true;
//break;//DRAG AND DROP>>>START DOESN"T FIRE
case DragEvent.ACTION_DROP:
if ((dragSource != null) && (dragSource != v)) {
Item source = (Item) dragSource.getTag();
Item target = (Item) v.getTag();
int sourcePos = source.getPosition();
int targetPos = target.getPosition();
if (targetPos < sourcePos)
source.moveUp(sourcePos - targetPos);
else
source.moveDown(targetPos - sourcePos);
dragSource.setVisibility(View.VISIBLE);
dragSource = null;
fireOnChecklistNeedsResetListener();
return true;
}
// View view = (View) event.getLocalState();
// Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
// Toast.makeText(v.getContext(), ((EditText) view.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
// Dropped, reassign View to ViewGroup
// View view = (View) event.getLocalState();
// ViewGroup owner = (ViewGroup) view.getParent();
// owner.removeView(view);
// LinearLayout container = (LinearLayout) v;
// container.addView(view);
// view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
dragSource.setVisibility(View.VISIBLE);
dragSource = null;
fireOnChecklistNeedsResetListener();
if (!event.getResult())
Toast.makeText(v.getContext(), "UNHANDLED", Toast.LENGTH_SHORT/8).show();
// View vieww = (View) event.getLocalState();
// Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
// Toast.makeText(v.getContext(), ((EditText) vieww.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
break;
case DragEvent.ACTION_DRAG_ENTERED:
v.setBackgroundColor(v.getContext().getResources().getColor(R.color.holoBlueLight));
return true;
//break;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackgroundColor(v.getContext().getResources().getColor(android.R.color.background_light));
return false;
//break;
default:
break;
}
return false;
}
};
Run Code Online (Sandbox Code Playgroud)
扩展信息:dragView是列表视图中的项目布局(特别是expandablelistview).接受触摸事件的视图是视图上具有小抓地力的小字形.这是一个正在进行拖动操作的屏幕截图(花了一些花哨的手指来获得这个大声笑):

因此,如果我将拖动的项目放在另一个项目上(这会重新排序它们),它的效果很好.如果我把它放在其他地方没有事件发生,所以我永远无法清理它.例如,在屏幕的上半部分,或者如果列表在空白区域或底部的蓝色条或任何系统区域中是短的.
我可以通过找出一种方法来防止拖离有效区域来解决这个问题,所以如果你知道如何做到这一点,那就是解决它的另一种方法.我的最后一个选择是为屏幕上的每个可能的视图实现一个事件(同样这些列表视图布局,在列表视图上,它位于一个片段上,可能在各种活动上),所以显然这是不可取的.事实上,如果我这样做,如果它被丢弃在系统UI区域(如systembar或电容按钮区域),我仍然可能有问题,但我不确定.
如果在这里有用,我在列表视图适配器中分配相关事件过程(我删除了不相关的行),获取视图项方法:
public View getGroupEdit(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
if (convertView != null) {
//irrelevant stuff omitted
} else
convertView = inf.inflate(R.layout.edit_group_item, null);
Item group = (Item) getGroup(groupPosition);
convertView.setTag(group);
EditText edtParent = (EditText) convertView.findViewById(R.id.edtParent);
edtParent.setTag(convertView);
scatterItemText(edtParent);
//irrelevant stuff omitted
ImageView imgGrip = (ImageView) convertView.findViewById(R.id.imgGrip);
imgGrip.setTag(convertView);
//irrelevant stuff omitted
imgGrip.setOnTouchListener(onTouchListener);
convertView.setOnDragListener(onDragEventListener);
return convertView;
}
Run Code Online (Sandbox Code Playgroud)
最后是FWIW,这是列表项视图的布局XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:orientation="horizontal" >
<ImageView
android:id="@+id/imgGrip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:src="@drawable/dark_grip2"
android:contentDescription="@string/strReorder"/>
<CheckBox
android:id="@+id/chkParent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgGrip"
android:checked="false"/>
<EditText
android:id="@+id/edtParent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/chkParent"
android:layout_toLeftOf="@+id/btnInsert"
android:textSize="17dip"
android:inputType="text"
android:hint="@string/strItem"/>
<ImageButton
android:id="@id/btnInsert"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_toLeftOf="@+id/viewParent"
android:src="@drawable/dark_content_new"
android:clickable="true"
android:hint="@string/strAddItemAbove"
android:contentDescription="@string/strAddItemAbove" />
<View
android:id="@id/viewParent"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_toLeftOf="@+id/btnExpand"/>
<ImageButton
android:id="@id/btnExpand"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/dark_add_sub_item"
android:clickable="true"
android:hint="@string/strViewSubItems"
android:contentDescription="@string/strViewSubItems"/>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
非常感谢您的帮助!
JRa*_*ond 12
需要通知拖动事件的视图必须注册OnDragListeners.如果他们需要知道特定事物或事物的类型何时移动,例如为了改变它们的外观(要么是"DRAG ME HERE!",要么是"你不要把它丢在我身上!").即使你的视图不是放弃拖动对象的有效位置,如果它需要"拖动上下文感知"可以这么说,它会注册一个OnDragListener并返回true ACTION_DRAG_STARTED.
从你非常彻底的问题中我遗漏的一件事是你究竟需要清理什么?如果您只需要执行活动范围内的一些通用事项,您可以考虑OnDragListener为RelativeLayout注册事件的基础添加不同的内容,但是等待ACTION_DRAG_ENDED提醒活动执行通用清理代码
| 归档时间: |
|
| 查看次数: |
12805 次 |
| 最近记录: |