【问题标题】:Drag and Drop and OnClick TextView拖放和 OnClick TextView
【发布时间】:2013-12-17 07:20:31
【问题描述】:

我正在创建拖放文本视图,我需要此文本视图也可以单击。 我的代码如下:

     <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/bg_grey"
        android:orientation="vertical" >

        <GridView
            android:id="@+id/gridview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@color/bg_grey"
            android:clickable="true"
            android:columnWidth="100dp"
            android:gravity="center"
            android:horizontalSpacing="10dp"
            android:numColumns="2"
            android:stretchMode="columnWidth"
            android:verticalSpacing="10dp" />

        <TextView
            android:id="@+id/drag_drop_button"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_marginLeft="255dp"
            android:layout_marginTop="155dp"
            android:background="@drawable/circle_button"
            android:clickable="true"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:gravity="center"
            android:text="@string/brand"
            android:textColor="@color/sign_blue"
            android:textSize="15sp"
            android:textStyle="bold" />

    </FrameLayout>


class ButtonDragListener implements OnDragListener {
        Drawable normalShape = getResources().getDrawable(
                R.drawable.circle_button);

        @Override
        public boolean onDrag(View v, DragEvent event) {
            int action = event.getAction();
            switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
                // do nothing
                break;
            case DragEvent.ACTION_DRAG_ENTERED:
                // do nothing
                break;
            case DragEvent.ACTION_DRAG_EXITED:
                // do nothing
                break;
            case DragEvent.ACTION_DROP:
                // Dropped, reassign View to ViewGroup
                View view = (View) event.getLocalState();
                view.setX(event.getX());
                view.setY(event.getY());
                ViewGroup owner = (ViewGroup) view.getParent();
                owner.removeView(view);
                FrameLayout container = (FrameLayout) v;
                container.addView(view);
                view.setVisibility(View.VISIBLE);
                break;
            case DragEvent.ACTION_DRAG_ENDED:
                // do nothing
                break;
            default:
                break;
            }
            return true;
        }
    }

        private final class ButtonTouchListener implements OnTouchListener {

            private static final int MAX_CLICK_DURATION = 200;
            private long startClickTime;

            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                    startClickTime = Calendar.getInstance().getTimeInMillis();
                    ClipData data = ClipData.newPlainText("", "");
                    DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
                            view);
                    view.startDrag(data, shadowBuilder, view, 0);
                    view.setVisibility(View.VISIBLE);

                } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                    long clickDuration = Calendar.getInstance().getTimeInMillis()
                            - startClickTime;

                    if (clickDuration < MAX_CLICK_DURATION){ 
                        view.performClick();
                    }
                }
                return true;
            }
        }

        private final class ButtonOnClickListener implements OnClickListener {

            @Override
            public void onClick(View v) {
                Log.e(TAG, "ALOHAAAAA");

            }

        }

        TextView dragDrop = (TextView) view.findViewById(R.id.drag_drop_button);
            dragDrop.setAlpha(0.7f);
            dragDrop.setOnClickListener(new ButtonOnClickListener());
            dragDrop.setOnTouchListener(new ButtonTouchListener());
        frameLayout = (FrameLayout) view.findViewById(R.id.root);
        frameLayout.setOnDragListener(new ButtonDragListener());

但是MotionEvent.ACTION_UP 永远不会被调用,我也试图将view.performClick() 移动到MotionEvent_ACTION_DOWN 内,点击监听器调用正常,但每当我拖动文本视图时,点击监听器也会运行。 我也有 setOnTouchListenersetOnClickListener 直接来自 textView 但结果是一样的。

我需要的是平滑的拖放和点击功能。请告诉我在这里做错了什么。 谢谢您,非常感谢您提供的任何帮助。

【问题讨论】:

    标签: android drag-and-drop onclicklistener ontouchlistener


    【解决方案1】:

    我和你有同样的问题,你的解决方案对我帮助不大,所以我想出了这个解决方案,它是基于你之前的解决方案。

        @Override
        public boolean onTouch(View v, MotionEvent event) {
    
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                if (Math.abs(event.getX() - mX) < MAX_X_MOVE || Math.abs(event.getY() - mY) < MAX_Y_MOVE) {
                    v.performClick();
                } else {
                    ClipData clipData = ClipData.newPlainText("", "");
                    View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
                    v.startDrag(clipData, shadowBuilder, v, 0);
                    v.setVisibility(View.INVISIBLE);
    
                    mX = event.getX();
                    mY = event.getY();
                }
    
                return true;
            }
            return false;
        }
    

    【讨论】:

    • 以上解决方案对我有用,但您最初给 mX,mY , MAX_X_MOVE,MAX_Y_MOVE 的值是多少?
    【解决方案2】:

    这是一种虽然提供了解决方案,但您必须考虑这些解决方案如何满足您的需求的问题。对于我的案例,我使用了上述想法并提出了适合我需要的解决方案。

      /**
       * Max value of X to move before we declare that we are going to do
       * drag. 
       */
       private static final float MAX_X_MOVE = 120;
    
      /**
       * Max value of Y to move before we declare that we are going to do 
       * drag.
       */
       private static final float MAX_Y_MOVE = 120;
    
       private final static int NONE = 0;
    
       private final static int DRAG = 1;
    
       private int m_mode = NONE;
    
       icon.setOnTouchListener(new View.OnTouchListener() {
         @Override
         public boolean onTouch(View v, MotionEvent event) {
    
            final int action = event.getAction();
    
             switch (action){
               case MotionEvent.ACTION_DOWN:
                m_mode = NONE;
               break;
    
               case MotionEvent.ACTION_MOVE:
                 if (Math.abs(event.getX()) > MAX_X_MOVE || 
                     Math.abs(event.getY()) > MAX_Y_MOVE) {
                     m_mode = DRAG;
                     _startDragOnFling();
                 }
               break;
    
               case MotionEvent.ACTION_UP:
                  if(m_mode == DRAG){
                   break;
                  }
                  v.performClick();
               break;
             }
    
            return true;
          }
       });
    

    【讨论】:

      【解决方案3】:

      我有自己的问题的解决方案,我修改了我的类 ButtonTouchListener 如下:

          private final class ButtonTouchListener implements OnTouchListener {
      
          private static final float MAX_X_MOVE = 70;
          private static final float MAX_Y_MOVE = 70;
      
          public boolean onTouch(View view, MotionEvent motionEvent) {
              if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                  ClipData data = ClipData.newPlainText("", "");
                  DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
                          view);
                  view.startDrag(data, shadowBuilder, view, 0);
                  view.setVisibility(View.VISIBLE);
      
                   float offset_x = motionEvent.getX(); 
                   float offset_y = motionEvent.getY();
      
      
                      Log.d(TAG,"OFFSET X = "+offset_x); 
                      Log.d(TAG,"OFFSET Y = "+offset_y); 
      
      
                      if (offset_x < MAX_X_MOVE && offset_y < MAX_Y_MOVE) { 
                          Log.d(TAG,"Here we go"); 
                          view.performClick(); 
                          }
      
      
                  return true;
      
              } else {
                  return false;
              }
      
          }
      
      }
      

      请注意,我从事件中获取指针 x 和 y,这有助于我指示 TextView 是否移动得太远,如果它移动超过 MAX_X_MOVE 和 MAX_Y_MOVE 将被视为拖动运动。 也许它可以帮助面临同样问题的其他人。欢迎任何更好的解决方案:)

      【讨论】:

        【解决方案4】:

        它已经发布了用于拖动监听器,您可以为 textView setonClickListener 方法编写..

        这是链接..

        How to drag the TextView to the correct target other TextView

        对于 onClick..

        textView.setOnClickListener(new OnClickListener() {
        
                @Override
                public void onClick(View v) {
                    // your code
        
                }
            });
        

        【讨论】:

        • 嗨 Karthick,感谢您的回复,但对我来说,拖放运行良好。我有触摸事件的问题,我想区分事件,用户是拖放还是点击。使用现有代码,我可以拖放,但点击监听器没有运行。
        【解决方案5】:

        只是一个想法,在XML中为textview设置onClick,同时调用onClick方法。

        android:onClick="onClickTextView"
        public void onClickTextView()
        
        {
        // your actions
        }
        

        【讨论】:

        • 我已经尝试了你上面的建议,但仍然没有解决我的问题,但还是感谢你的回答。
        【解决方案6】:

        试试这个,只是一个想法。希望对你有用。

        TextView dragDrop = (TextView) view.findViewById(R.id.drag_drop_button);
        dragDrop.setAlpha(0.7f);
        dragDrop.setOnClickListener(new View.OnClickListener() {
        
                            @Override
                            public void onClick(View arg0) {
                                // TODO Auto-generated method stub
        
                            }
                        });
        

        【讨论】:

          【解决方案7】:

          在我的应用程序中,可以单击或拖动一系列按钮。为了实现这一点,我有

          • 使用“onClick”属性在 XML 中定义按钮,该属性引用我的主要活动中的方法(在您的应用程序中,将“View.OnClickListener”附加到您的 TextView)
          • 定义了一个“OnDragListener”(它只返回 true,因为所有拖动事件都在附加到拖放目标视图的单独“OnDragListener”中处理)
          • 定义了一个“OnLongClickListener”
          • 在我的主要活动中覆盖了“onClick()”(我不记得这是在哪里记录的)
          • 为按钮分配了“OnLongClickListener”
          • 为按钮分配了“OnDragListener”

          这是我的实现:

          @Override
          public void onClick(View v) {  }
          
          class ScDragListenerForButton implements OnDragListener {
              @Override
              public boolean onDrag(View v, DragEvent event) {
                  return true;
              }
          }
          
          ScDragListenerForButton mDragListenerForButton = new ScDragListenerForButton();
          
          View.OnLongClickListener onLongClickListener = new View.OnLongClickListener() {
              @Override
              public boolean onLongClick(View v) {
                  Button b = (Button) v;
                  ClipData.Item item = new ClipData.Item(b.getText());
                  String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
          
                  ClipData dragData = new ClipData(b.getText(), mimeTypes, item);
                  View.DragShadowBuilder myShadow = new View.DragShadowBuilder(v);
          
                  if (Build.VERSION.SDK_INT < VERSION_CODES.N) {
                      v.startDrag(dragData, myShadow, null, 0);
                  } else {
                      v.startDragAndDrop(dragData, myShadow, null, 0);
                  }
                  return true;
              }
          };
          
          button1.setOnLongClickListener(onLongClickListener);
          button1.setOnDragListener(mDragListenerForButton);
          

          【讨论】:

            【解决方案8】:

            试试这个:

            public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
              float dX;
              float dY;
              int lastAction;
            
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
            
                final View dragView = findViewById(R.id.draggable_view);
                dragView.setOnTouchListener(this);
              }
            
              @Override
              public boolean onTouch(View view, MotionEvent event) {
                switch (event.getActionMasked()) {
                  case MotionEvent.ACTION_DOWN:
                    dX = view.getX() - event.getRawX();
                    dY = view.getY() - event.getRawY();
                    lastAction = MotionEvent.ACTION_DOWN;
                    break;
            
                  case MotionEvent.ACTION_MOVE:
                    view.setY(event.getRawY() + dY);
                    view.setX(event.getRawX() + dX);
                    lastAction = MotionEvent.ACTION_MOVE;
                    break;
            
                  case MotionEvent.ACTION_UP:
                    if (lastAction == MotionEvent.ACTION_DOWN)
                      Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
                    break;
            
                  default:
                    return false;
                }
                return true;
              }
            }
            

            还有 XML:

            <ImageButton
                    android:id="@+id/draggable_view"
                    android:background="@mipmap/ic_launcher"
                    android:layout_gravity="bottom|right"
                    android:layout_marginBottom="20dp"
                    android:layout_marginEnd="20dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            

            您可以使任何视图可拖动和可点击。

            【讨论】:

              【解决方案9】:

              试试这个:

                      public class MainActivity extends AppCompatActivity implements View.OnTouchListener, View.OnDragListener , View.OnClickListener {
              
                       @Override
                        protected void onCreate(Bundle savedInstanceState) {
                          super.onCreate(savedInstanceState);
                          setContentView(R.layout.activity_main);
              
                          final View dragView = findViewById(R.id.draggable_view);
                          dragView.setOnTouchListener(this);
                          dragView.setOnclickListener(this);
              
                        }
              
                   @Override
                      public boolean onTouch(View v, MotionEvent event) {
              
                          //if move detected it start Drag event and it's handler or click wil be handled by click listener
                          if(event.getAction()  == MotionEvent.ACTION_MOVE){
                              View.DragShadowBuilder mShadow = new View.DragShadowBuilder(v);
              
                                  dragView = v;
                                  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                      v.startDragAndDrop(null, mShadow, null, 0);
                                  } else {
                                      v.startDrag(null, mShadow, null, 0);
                                  }
                               }
                     return false;
                  }
              
               @Override
                  public void onClick(View view) {
                      switch (view.getId()){
                          case R.id.draggable_view:{
                              showToast("click detected");
                          }
                          break;
                         }
                     }
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-05-24
                • 2020-10-08
                • 2011-11-02
                • 1970-01-01
                • 2011-05-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多