如何限制阻力和沿y轴只在Android的下降? [英] How do I restrict drag and drop along the y axis only in android?

查看:144
本文介绍了如何限制阻力和沿y轴只在Android的下降?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图限制拖放动作只Y轴,以便用户只能采取一个视图并将其拖动向上或向下 - 而不是向左或向右

I'm trying to restrict drag and drop motion to only the Y-axis so that a user can only take a view and drag it up or down--not left or right.

我有两个观点(TextView中和悬浮窗的IDS)现在。一(TextView中)有一个触摸监听器设置为它和另一个(悬浮窗)已经一拖监听器设置就可以了。

I've got two views (ids of textView and dropZone) right now. One (textView) has a touch listener set to it and another (dropZone) has a drag listener set on it.

这里的布局XML(activity_main.xml中):

Here's the layout xml (activity_main.xml):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

<TextView
    android:id="@+id/textView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="50dp"
    android:background="#FFFFFF00"
    android:text="Text Drag" />

<TextView
    android:id="@+id/dropZone"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="167dp"
    android:background="#FFFF0000"
    android:text="Drop Zone" />

</RelativeLayout>

以下是活动code:

The following is the activity code:

package com.example.dragexperiment;

import android.app.Activity;
import android.content.ClipData;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnGenericMotionListener;
import android.view.View.OnTouchListener;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends Activity {
TextView tv, dz, sv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView) findViewById(R.id.textView);
        dz = (TextView) findViewById(R.id.dropZone);
        tv.setOnTouchListener(new MyTouchListener());
        dz.setOnDragListener(new MyDragListener());
    }

    private final class MyTouchListener implements OnTouchListener {
        int viewX0, viewY0,
            cY0, cY1,
            deltaCursorY;

        @Override
        public boolean onTouch(final View v,final MotionEvent event) {
              switch(event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    viewX0 = (int) v.getX();
                    viewY0 = (int) v.getY();
                    cY0 = (int) event.getRawY();
                    ClipData data = ClipData.newPlainText("", "");
                    DragShadowBuilder shadow = new View.DragShadowBuilder(v);
                    v.startDrag(data, shadow, v, 0);
                    return true;
                case MotionEvent.ACTION_MOVE:
                //  cY1 = (int) event.getRawY();
                //  deltaCursorY = cY1 - cY0;
                //  v.setX(viewX0);
                //  v.setY(viewY0 + deltaCursorY);
                    return true;
              }
              return false;
        }
    }

    class MyDragListener implements OnDragListener {

        public boolean onDrag(View v, DragEvent event) {
            switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
                break;
            case DragEvent.ACTION_DRAG_ENTERED:
                v.setBackgroundColor(Color.BLUE);
                break;
            case DragEvent.ACTION_DRAG_EXITED:
                break;
            case DragEvent.ACTION_DROP:
                v.setBackgroundColor(Color.BLUE);
                break;
            case DragEvent.ACTION_DRAG_ENDED:
                break;
            default:
                break;
            }
            return true;
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

你可以从code以上,当用户在拖动悬浮窗TextView的看到,我力图把悬浮窗视图背景色为蓝色。如果我使用创建的ACTION_DOWN运动事件Drag​​ShadowBuilder这工作正常:

As you can see from the code above, when a user drags textView over dropZone, I try to turn the dropZone view background color to blue. This works fine if I use create a DragShadowBuilder in the ACTION_DOWN motion event:

    ClipData data = ClipData.newPlainText("", "");
    DragShadowBuilder shadow = new View.DragShadowBuilder(v);
    v.startDrag(data, shadow, v, 0);

的问题是,我无法控制的阴影,以便它仅沿Y轴(垂直)轴移动。

The problem is that I can't control the shadow so that it only moves along the Y-axis (vertical) axis.

如果我拿出DragShadowBuilder code(以上三条线),并在code添加到移动在ACTION_MOVE移动事件被拖动的视图(它的上面注释掉):

If I take out the DragShadowBuilder code (the three lines above), and add in code to move the dragged view in the ACTION_MOVE motion event (it's commented out above):

    cY1 = (int) event.getRawY();
    deltaCursorY = cY1 - cY0;
    v.setX(viewX0);
    v.setY(viewY0 + deltaCursorY);

然后我可以控制的TextView只沿Y轴移动。不幸的是,没有一个DragShadowBuilder,我不能得到ACTION_DRAG_ENTERED的dragEvent触发打开悬浮窗景蓝色的。

Then I can control the textView to move only along the Y-axis. Unfortunately, without a DragShadowBuilder, I can't get the ACTION_DRAG_ENTERED DragEvent to trigger to turn the dropZone view blue.

如果我离开DragShadowBuilder code和四大行code以上两者,只为一拖触发一次ACTION_MOVE运动活动;它不会继续跟随周边拖累。

If I leave both the DragShadowBuilder code and the four lines of code above, the ACTION_MOVE motion event is only triggered once for a drag; it doesn't continue to follow the drag around.

任何人有任何想法,我可以做什么?我一直在围绕工装用这一段时间,但没有运气。我甚至在一个点试图创建一个扩展Android的View类的自定义视图,而是因为它的声明为final的,我不能覆盖的startDrag方法。我希望我是在这个好。 (

Anybody have any ideas as to what I can do? I've been tooling around with this for a while, but with no luck. I even tried at one point to create a custom view that extends the Android View class, but I can't override the startDrag method because it's declared as final. I wish I were better at this. :(

推荐答案

啊哈!我没能找到这个答案的任何地方(和很多人都问),所以这里就是我所做的。

Ah ha! I wasn't able to find this answer anywhere (and a lot of people were asking), so here's what I did.

其基本思想是使DragShadow无形和Y轴的运动传递给你想拖的观点。所以在现实中,你拖着DragShadow,但它会出现的可拖动视图移动用户。

The basic idea was to make the DragShadow invisible and pass the Y axis movement to the view you want to "drag". So in reality, you're dragging the DragShadow, but it will appear to the user that the draggable view is moving.

draggableItem.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(final View view, MotionEvent motionEvent) {
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(new View(getApplicationContext()));
                view.startDrag(data, shadowBuilder, view, 0);
                return true;
            } else {
                return false;
            }
        }
    });

mDropZone.setOnDragListener(new View.OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {
                switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    ViewGroup.MarginLayoutParams lParams = (ViewGroup.MarginLayoutParams) arcMenu.getLayoutParams();
                    _yDelta = (int) event.getY() - lParams.topMargin;
                    break;
                case DragEvent.ACTION_DRAG_LOCATION:
                    ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) arcMenu.getLayoutParams();
                    layoutParams.topMargin = (int) event.getY() - _yDelta;
                    arcMenu.setLayoutParams(layoutParams);
                    break;
                case DragEvent.ACTION_DROP:
                    // Dropped, reassign View to ViewGroup
                    View view = (View) event.getLocalState();

                    // Do your drop actions here

                    view.setVisibility(View.VISIBLE);
                    break;
                default:
                    break;
            }
            return true;
        }
    });

您还需要声明的 _yDelta 变量在你的类。

You'll also need to declare the _yDelta variable in your class.

希望这适用于所有你很酷的猫在那里!

Hope this works for all you cool cats out there!

这篇关于如何限制阻力和沿y轴只在Android的下降?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆