【问题标题】:Can't drag and drop a simple imageView in android studio无法在android studio中拖放一个简单的imageView
【发布时间】:2017-05-02 04:19:59
【问题描述】:

我正在尝试在 android studio 中创建一个简单的拖放图像。我可以让图像在屏幕上拖动,一旦我释放它就会消失。在控制台中,我得到一个“报告丢弃结果:假”

这是我的代码:

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

}

【问题讨论】:

    标签: android android-layout drag-and-drop imageview


    【解决方案1】:

    已编辑:更改为如何使用 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;
        }
    }
    

    【讨论】:

      【解决方案2】:

      给出的代码存在一个问题,很容易修复。 OnDragListener() 应该为目标(或任何可能的目标)视图设置。所以OnLongClickListener()OnTouchListener() 在源视图上设置,imageView 那么OnDragListener() 应该有imageView2。这是一个很长的解释,但应该很容易解决。

      请参阅drag-drop 了解一个很好的例子。

      如果做得好,解决方案的其余部分会涉及更多(但是,有一种变通方法)。

      开始拖动时,基本上你需要将图像复制到剪贴板,然后将其粘贴到拖放视图中。这需要创建一个ContentProvider,然后使用ContentResolver (link)。

      剪贴板文档: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”的情况下执行类似的操作。如果图像被放置在无效区域,这会将图像恢复到原始视图。

      【讨论】:

        【解决方案3】:

        这就是我在我的应用程序中的做法:

        对于要拖动的“视图”,在 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:

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

        希望对您有所帮助。

        【讨论】:

          猜你喜欢
          • 2017-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多