2016-12-16 4 views
19

Я пытаюсь создать простое изображение перетаскивания в студии android. Я могу заставить изображение перемещаться по экрану, оно исчезает, как только я его отпускаю. В консоли, я получаю «Отчетность результат падения: ложный»Невозможно перетащить простую картинку в андроид-студию

Вот мой код:

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

}

ответ

5

Там одна проблема с кодом, который, учитывая, что будет легко исправить. Значение OnDragListener() должно быть установлено для вида назначения (или любого возможного адресата). Таким образом, OnLongClickListener() и OnTouchListener() установлены на вид источника, imageView, тогда должно быть imageView2 для OnDragListener(). Это длинное объяснение, но должно быть легко исправить.

См. drag-drop для примера.

Остальное решение гораздо более эффективно, если сделано правильно (однако, есть работа).

При запуске перетаскивания в основном вам нужно скопировать изображение в буфер обмена, а затем вставить его в раскрывающийся список. Для этого необходимо создать ContentProvider, а затем использовать ContentResolver (link).

Clipboard документация: ClipData

У меня есть планы на будущее, чтобы сделать это для приложения, но это не будет происходить в ближайшее время, так как, к сожалению, я не в состоянии обеспечить любой код.

Однако есть обходной путь, который гораздо менее востребован.

Установить тег (ы) на любое изображение, которое потенциально может быть перемещено.

imageView.setTag("ImageTag1"); 

В onLongClick() установите item и dragData, как это делается в этом вопросе.

Затем в 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». Если изображение упало в недопустимой области, это вернет изображение в исходное представление.

8

Отредактировано: Изменено с помощью рабочего примера перемещения всех видов, содержащихся в RelativeLayout, с помощью onTouch. Я думаю, что событие 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; 
    } 
} 
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 что имеет пункт назначения «посередине» и посещает события перетаскивания:

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

Это сопротивление lis tener для ImageView в DragLayout:

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

} 

Надеюсь, что это поможет.

Смежные вопросы