无法在Android Studio中拖放简单的imageView。

17

我正在尝试在Android Studio中创建一个简单的拖放图像。我可以把图片拖到屏幕周围,但一旦释放它,它就消失了。在控制台中,我得到了一个“Reporting drop result: false”的提示。

这是我的代码:

ImageView mImageView;
String mString;

private android.widget.RelativeLayout.LayoutParams mLayoutParams;

    mImageView.setOnLongClickListener(new View.OnLongClickListener(){
        @Override
        public boolean onLongClick(View v){
            ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
            String[] mimeTypes = {
                    ClipDescription.MIMETYPE_TEXT_PLAIN
            };
            ClipData dragData = new ClipData(v.getTag().toString(), mimeTypes, item);
            View.DragShadowBuilder myShadow = new View.DragShadowBuilder(mImageView);

            v.startDrag(dragData, myShadow, null, 0);
            return true;
        }
    });

    mImageView.setOnDragListener(new View.OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {
            switch(event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    mLayoutParams = (RelativeLayout.LayoutParams)v.getLayoutParams();
                    Log.d(mString, "Action is DragEvent.ACTION_DRAG_STARTED");

                    // Do nothing
                    break;

                case DragEvent.ACTION_DRAG_ENTERED:
                    Log.d(mString, "Action is DragEvent.ACTION_DRAG_ENTERED");
                    int x_cord = (int) event.getX();
                    int y_cord = (int) event.getY();
                    break;

                case DragEvent.ACTION_DRAG_EXITED :
                    Log.d(mString, "Action is DragEvent.ACTION_DRAG_EXITED");
                    x_cord = (int) event.getX();
                    y_cord = (int) event.getY();
                    mLayoutParams.leftMargin = x_cord;
                    mLayoutParams.topMargin = y_cord;
                    v.setLayoutParams(mLayoutParams);
                    break;

                case DragEvent.ACTION_DRAG_LOCATION  :
                    Log.d(mString, "Action is DragEvent.ACTION_DRAG_LOCATION");
                    x_cord = (int) event.getX();
                    y_cord = (int) event.getY();
                    break;

                case DragEvent.ACTION_DRAG_ENDED   :
                    Log.d(mString, "Action is DragEvent.ACTION_DRAG_ENDED");

                    // Do nothing
                    break;

                case DragEvent.ACTION_DROP:
                    Log.d(mString, "ACTION_DROP event");

                    // Do nothing
                    break;
                default: break;
            }
            return true;
        }
    });

    mImageView.setOnTouchListener(new View.OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(mImageView);

                mImageView.startDrag(data, shadowBuilder, mImageView, 0);
                mImageView.setVisibility(View.INVISIBLE);
                return true;
            } else {
                return false;
            }
        }
    });
}

}

3个回答

8

编辑:更改为如何使用onTouch移动RelativeLayout中包含的所有视图的有效示例。我认为onDrag事件更适用于拖放数据项,而不是移动视图。

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
    private RelativeLayout mRelLay;
    private float mInitialX, mInitialY;
    private int mInitialLeft, mInitialTop;
    private View mMovingView = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRelLay = (RelativeLayout) findViewById(R.id.relativeLayout);

        for (int i = 0; i < mRelLay.getChildCount(); i++)
            mRelLay.getChildAt(i).setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        RelativeLayout.LayoutParams mLayoutParams;

        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mMovingView = view;
                mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
                mInitialX = motionEvent.getRawX();
                mInitialY = motionEvent.getRawY();
                mInitialLeft = mLayoutParams.leftMargin;
                mInitialTop = mLayoutParams.topMargin;
                break;

            case MotionEvent.ACTION_MOVE:
                if (mMovingView != null) {
                    mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
                    mLayoutParams.leftMargin = (int) (mInitialLeft + motionEvent.getRawX() - mInitialX);
                    mLayoutParams.topMargin = (int) (mInitialTop + motionEvent.getRawY() - mInitialY);
                    mMovingView.setLayoutParams(mLayoutParams);
                }
                break;

            case MotionEvent.ACTION_UP:
                mMovingView = null;
                break;
        }

        return true;
    }
}

5
给出的代码有一个问题很容易解决。应该为目标视图(或任何可能的目标视图)设置OnDragListener()。因此,源视图imageView上设置了OnLongClickListener()OnTouchListener(),然后应该有imageView2用于OnDragListener()。这是一个长说明,但应该是一个简单的修复。
请参见拖放以获取一个很好的示例。
如果正确完成,其余的解决方案会更加复杂(但是有一种解决方法)。
在开始拖动时,基本上需要将图像复制到剪贴板,然后将其粘贴到投放视图中。这需要创建一个ContentProvider,然后使用ContentResolver链接)。
剪贴板文档:ClipData 我未来计划为应用程序执行此操作,但这不会很快发生,因此,不幸的是,我无法提供任何代码。
但是,有一个较少涉及的解决方法。
在任何可能被移动的图像上设置标记。
imageView.setTag("ImageTag1");

onLongClick() 中,像问题中所做的一样设置 itemdragData

然后在 OnDragListener() 中,读取标签,确定正在拖放哪个图像,然后将该图像设置为视图。类似于这样:

case DragEvent.ACTION_DROP:
    ClipData.Item item = event.getClipData().getItemAt(0);
    CharSequence dragData = item.getText();

    if(dragData.equals("ImageTag1")) {
        // this gets jpg image from "drawable" folder,
        //      set ImageView appropriately for your usage
        ((ImageView)v).setImageResource(R.drawable.image1);                            
    } else if(dragData.equals("ImageTag2")) {
        ((ImageView)v).setImageResource(R.drawable.image2);
    }
    break;

如果出现"ACTION_DRAG_EXITED"事件,您还需要采取类似的措施。如果图像被拖放到无效区域,则将图像放回原始视图。


0
这是我在我的应用程序中的做法:
对于您想要拖动的“视图”,请在onTouchListener中设置此选项:
    public final class ChoiceTouchListener implements OnTouchListener {
    Context context;
    //int index;
    public static float offsetX = 0,offsetY = 0;

    DragShadowBuilder shadowBuilder;

    public ChoiceTouchListener(Context context) {
        super();
        this.context = context;
        //this.index = index;
    }




    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {

            //view.setTag("option"+index);
            ClipData data = ClipData.newPlainText("tag", view.getTag().toString());
            shadowBuilder = new View.DragShadowBuilder(view);

            //start dragging the item touched
            view.startDrag(data, shadowBuilder, view, 0);

            offsetX = view.getLeft();//(int)view.getX();//(int)motionEvent.getX();
            offsetY = view.getTop();//(int)view.getY();//motionEvent.getY();
            view.setVisibility(View.INVISIBLE);
            Log.v("here","it is ::" + (int)motionEvent.getX() + " , "+(int)motionEvent.getY());

            return false;



        }

        return true;

    }
}

这里有一个RelativeLayout,它将目标“view”设置在中间并监听拖放事件:
    public class DragLayout extends RelativeLayout {

    boolean DEBUG = true;

    AnimationDrawable blenderAnim;
    Handler handlerAnim2;
    Context context;

    private int dimensionInPixel = 200;
    int screenWidth,screenHeight;

    public DragLayout(Context context) {
        super(context);

        this.context = context;

        //not to include in main program
        getDimensionsofScreen();

        setLayout();
        setViews();

    }



    private void setLayout() {


        // set according to parent layout (not according to current layout)
        RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams(
                LayoutParams.MATCH_PARENT,  LayoutParams.MATCH_PARENT);
        rLp.topMargin = 2 * (screenHeight / 25); // calculating 1/10 of 4/5
        // screen


        this.setLayoutParams(rLp);

    }

    void setViews() {

        ImageView img2 = new ImageView(context);

        int dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());

        RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams(
                (screenWidth / 5), (screenHeight / 5));
        rLp.topMargin = (screenHeight / 10);
        rLp.leftMargin = (4*screenWidth / 10);
        rLp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);

        img2.setLayoutParams(rLp);
        img2.getLayoutParams().height = dimensionInDp;
        img2.getLayoutParams().width = dimensionInDp;
        img2.setImageDrawable(getResources().getDrawable(R.drawable.blender_anim));
        img2.setOnDragListener(new ChoiceDragListener(context));
        this.addView(img2);

        blenderAnim = (AnimationDrawable)img2.getDrawable();
        blenderAnim.setOneShot(true);
        blenderAnim.stop();

    }


    public ArrayList<Integer> getDimensionsofScreen() {

        //metrics that holds the value of height and width
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();;
        ArrayList<Integer> vals = new ArrayList<Integer>();

        vals.add(displayMetrics.widthPixels);
        vals.add(displayMetrics.heightPixels);
        screenHeight = displayMetrics.heightPixels;
        screenWidth = displayMetrics.widthPixels;

        return vals;
    }



    @SuppressLint("NewApi")
    @Override
    public boolean onDragEvent(DragEvent event) {

        int mCurX = (int) event.getX();
        int mCurY = (int) event.getY();

        if(event.getAction() == DragEvent.ACTION_DRAG_STARTED || event.getAction() == DragEvent.ACTION_DRAG_ENTERED) {
            if (blenderAnim.isRunning()) {
                blenderAnim.stop();
            } else {
                blenderAnim.run();

                handlerAnim2 = new Handler();
                handlerAnim2.postDelayed(
                        new Runnable(){

                            @Override
                            public void run() {
                                blenderAnim.stop();

                            }},
                        getAnimationDuration(blenderAnim));
            }
        }

        if(event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_EXITED) {

            if (blenderAnim.isRunning()) {
                blenderAnim.stop();
            } else {
                blenderAnim.run();

                handlerAnim2 = new Handler();
                handlerAnim2.postDelayed(
                        new Runnable(){

                            @Override
                            public void run() {
                                blenderAnim.stop();

                            }},
                        getAnimationDuration(blenderAnim));
            }

            Log.v("here", "it is :: " + mCurX + ", " + mCurY);

            View view1 = (View) event.getLocalState();
            view1.setVisibility(View.VISIBLE);
            ObjectAnimator animationx = ObjectAnimator.ofFloat(view1,"translationX", mCurX - ChoiceTouchListener.offsetX-(screenWidth / 10),0.0f);
            ObjectAnimator animationy = ObjectAnimator.ofFloat(view1, "translationY", mCurY - ChoiceTouchListener.offsetY - (screenHeight / 10), 0.0f);
            AnimatorSet animSet = new AnimatorSet();
            animSet.setDuration(500);
            animSet.playTogether(animationx,animationy);

            animSet.start();

        }
        if(event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_ENDED){
            if(blenderAnim.isRunning()){
                blenderAnim.stop();
            }
        }
        return true;


    }

    private int getAnimationDuration(AnimationDrawable src){
        int dur = 0;
        for(int i=0; i<src.getNumberOfFrames(); i++){
            dur += src.getDuration(i);
        }
        return dur;
    }
}

这是 DragLayout 中 ImageView 的拖动监听器:
    public class ChoiceDragListener implements View.OnDragListener {

    boolean DEBUG = true;
    Context context;
    public String TAG = "Drag Layout:";

    public ChoiceDragListener(Context context){
        this.context = context;
    }

    @Override
    public boolean onDrag(View v, DragEvent event) {
        switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
                if(DEBUG) Log.v("here","drag started");
                break;
            case DragEvent.ACTION_DRAG_ENTERED:
                break;
            case DragEvent.ACTION_DRAG_LOCATION:
                int mCurX = (int) event.getX();
                int mCurY = (int) event.getY();

                if(DEBUG) Log.v("Cur(X, Y) : " ,"here ::" + mCurX + ", " + mCurY );

                break;
            case DragEvent.ACTION_DRAG_EXITED:

                if(DEBUG)
                    Log.v("here","drag exits");

                break;
            case DragEvent.ACTION_DROP:

                //handle the dragged view being dropped over a drop view
                View view = (View) event.getLocalState();
                ClipData cd =  event.getClipData();
                ClipData.Item item = cd.getItemAt(0);
                String resp = item.coerceToText(context).toString();

                //view dragged item is being dropped on
                ImageView dropTarget = (ImageView) v;

                //view being dragged and dropped
                final ImageView dropped = (ImageView) view;

                dropped.setEnabled(false);

                //if an item has already been dropped here, there will be a tag
                final Object tag = dropTarget.getTag();

                LayoutInflater li = LayoutInflater.from(context);
                View promptsView = li.inflate(R.layout.ns_scoop_dialog, null);

                AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                        context);

                // set prompts.xml to alertdialog builder
                alertDialogBuilder.setView(promptsView);

                final EditText userInput = (EditText) promptsView
                        .findViewById(R.id.edit1);

                // set dialog message
                alertDialogBuilder
                        .setIcon(R.mipmap.ic_launcher)
                        .setTitle(dropped.getTag().toString())
                        .setCancelable(false)
                        .setPositiveButton("OK",
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog,int id) {
                                        // get user input and set it to result
                                        // edit text
                                        String inAmt = userInput.getText().toString();

                                        CreateSmoothie.nsList.add(inAmt + " Green Scoops " + dropped.getTag().toString());
                                        Log.d(TAG, inAmt + " Green Scoops " + dropped.getTag().toString() + " added to list");

                                        dialog.dismiss();

                                        //dropped.setEnabled(true);
                                    }
                                })
                        .setNegativeButton("Cancel",
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int id) {
                                        dialog.cancel();

                                        int existingID = dropped.getId();

                                        //set the original view visible again
                                        ((Activity) context).findViewById(existingID).setVisibility(View.VISIBLE);

                                        dropped.setEnabled(true);

                                    }
                                });

                // create alert dialog
                AlertDialog alertDialog = alertDialogBuilder.create();

                // show it
                alertDialog.show();
                //Button nButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
                //nButton.setBackgroundColor(Color.GREEN);
                //Button pButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
                //pButton.setBackgroundColor(Color.GREEN);

                if(tag!=null)
                {
                    //the tag is the view id already dropped here
                    int existingID = (Integer)tag;

                    //set the original view visible again
                    ((Activity) context).findViewById(existingID).setVisibility(View.VISIBLE);
                }

                break;
            case DragEvent.ACTION_DRAG_ENDED:

                if(DEBUG) Log.i("drag event", "ended::" + ChoiceTouchListener.offsetX + "," + ChoiceTouchListener.offsetY);

                /**
                 * returning false so that goes to parentView onDrag function
                 */
                return false;
            //break;
            default:
                break;
        }
        return true;
    }

}

希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接