拖放和OnClick TextView

时间:2013-12-17 07:20:32

标签: android drag-and-drop onclicklistener ontouchlistener

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

     <?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,点击监听器调用正常,但每当我拖动文本视图时,点击监听器也会跑。 我也直接从textView获得setOnTouchListenersetOnClickListener但结果相同。

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

9 个答案:

答案 0 :(得分:3)

我遇到了和你一样的问题,你的解决方案对我没有帮助,所以我提出了这个解决方案,它是基于你以前的解决方案。

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

答案 1 :(得分: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;
      }
   });

答案 2 :(得分:1)

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

这是链接..

How to drag the TextView to the correct target other TextView

for onClick ..

textView.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // your code

        }
    });

答案 3 :(得分:1)

我有自己的问题的解决方案,我修改了我的类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 :(得分:0)

它只是一个想法,为XML中的textview设置onClick,并调用onClick方法。

android:onClick="onClickTextView"
public void onClickTextView()

{
// your actions
}

答案 5 :(得分:0)

尝试这个,只是一个想法。希望能为你效劳。

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

                    }
                });

答案 6 :(得分:0)

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

  • 使用“ onClick”属性定义了XML中的按钮,该属性引用了我的主要活动中的方法(在您的应用程序中,将“ View.OnClickListener”附加到您的TextView中)
  • 定义了一个“ OnDragListener”(由于所有拖动事件都是在附加到放置目标视图的单独的“ OnDragListener”中处理的,因此它只会返回true)
  • 定义了一个“ 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);

答案 7 :(得分:0)

尝试一下:

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"/>

您可以将任意视图设为可拖动和可点击。

答案 8 :(得分:0)

尝试一下:

#2/3rds for training
library(caret)
inTrain = createDataPartition(df$yourFactor, p = 2/3, list = FALSE)
dfTrain=df[inTrain,]
dfTest=df[-inTrain,]