我正在尝试将拖放动作限制为仅限Y轴,以便用户只能拍摄视图并向上或向下拖动 - 而不是向左或向右拖动.
我现在有两个视图(textView和dropZone的id).一个(textView)设置了一个触摸侦听器,另一个(dropZone)设置了一个拖动侦听器.
这是布局xml(activity_main.xml):
以下是活动代码:
package com.example.dragexperiment; import android.app.Activity; import android.content.ClipData; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.DragEvent; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.View.DragShadowBuilder; import android.view.View.OnDragListener; import android.view.View.OnGenericMotionListener; import android.view.View.OnTouchListener; import android.widget.RelativeLayout; import android.widget.TextView; public class MainActivity extends Activity { TextView tv, dz, sv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.textView); dz = (TextView) findViewById(R.id.dropZone); tv.setOnTouchListener(new MyTouchListener()); dz.setOnDragListener(new MyDragListener()); } private final class MyTouchListener implements OnTouchListener { int viewX0, viewY0, cY0, cY1, deltaCursorY; @Override public boolean onTouch(final View v,final MotionEvent event) { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: viewX0 = (int) v.getX(); viewY0 = (int) v.getY(); cY0 = (int) event.getRawY(); ClipData data = ClipData.newPlainText("", ""); DragShadowBuilder shadow = new View.DragShadowBuilder(v); v.startDrag(data, shadow, v, 0); return true; case MotionEvent.ACTION_MOVE: // cY1 = (int) event.getRawY(); // deltaCursorY = cY1 - cY0; // v.setX(viewX0); // v.setY(viewY0 + deltaCursorY); return true; } return false; } } class MyDragListener implements OnDragListener { public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: break; case DragEvent.ACTION_DRAG_ENTERED: v.setBackgroundColor(Color.BLUE); break; case DragEvent.ACTION_DRAG_EXITED: break; case DragEvent.ACTION_DROP: v.setBackgroundColor(Color.BLUE); break; case DragEvent.ACTION_DRAG_ENDED: break; default: break; } 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; } }
从上面的代码中可以看出,当用户在dropZone上拖动textView时,我尝试将dropZone视图背景颜色变为蓝色.如果我在ACTION_DOWN运动事件中使用创建DragShadowBuilder,这可以正常工作:
ClipData data = ClipData.newPlainText("", ""); DragShadowBuilder shadow = new View.DragShadowBuilder(v); v.startDrag(data, shadow, v, 0);
问题是我无法控制阴影,只能沿Y轴(垂直)轴移动.
如果我取出DragShadowBuilder代码(上面的三行),并添加代码以在ACTION_MOVE运动事件中移动拖动的视图(上面已注释掉):
cY1 = (int) event.getRawY(); deltaCursorY = cY1 - cY0; v.setX(viewX0); v.setY(viewY0 + deltaCursorY);
然后我可以控制textView只沿Y轴移动.不幸的是,如果没有DragShadowBuilder,我无法通过ACTION_DRAG_ENTERED DragEvent触发将dropZone视图变为蓝色.
如果我同时保留DragShadowBuilder代码和上面四行代码,则ACTION_MOVE运动事件仅在拖动时触发一次; 它不会继续跟随拖累.
谁有任何关于我能做什么的想法?我已经使用了一段时间,但没有运气.我甚至尝试过创建一个扩展Android View类的自定义视图,但是我无法覆盖startDrag方法,因为它被声明为final.我希望我能做得更好.:(
啊哈!我无法在任何地方找到这个答案(而且很多人都在问),所以这就是我所做的.
基本思想是使DragShadow不可见,并将Y轴移动传递到您想要"拖动"的视图.所以实际上,你正在拖动DragShadow,但是对于用户来说,可拖动视图正在移动.
draggableItem.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(final View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { ClipData data = ClipData.newPlainText("", ""); View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(new View(getApplicationContext())); view.startDrag(data, shadowBuilder, view, 0); return true; } else { return false; } } }); mDropZone.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: ViewGroup.MarginLayoutParams lParams = (ViewGroup.MarginLayoutParams) arcMenu.getLayoutParams(); _yDelta = (int) event.getY() - lParams.topMargin; break; case DragEvent.ACTION_DRAG_LOCATION: ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) arcMenu.getLayoutParams(); layoutParams.topMargin = (int) event.getY() - _yDelta; arcMenu.setLayoutParams(layoutParams); break; case DragEvent.ACTION_DROP: // Dropped, reassign View to ViewGroup View view = (View) event.getLocalState(); // Do your drop actions here view.setVisibility(View.VISIBLE); break; default: break; } return true; } });
您还需要在类中声明_yDelta变量.
希望这适用于所有酷猫!