简体   繁体   English

Android:onTouchListener无法正常工作

[英]Android: onTouchListener not working properly

I'm currently working on an app that has a RelativeLayout that has 4 child FrameLayouts , each FrameLayout has a set of ImageViews inside it and the inside View has it's own behavior. 我目前正在开发一个带有4个子FrameLayoutsRelativeLayout的应用程序,每个FrameLayout内部都有一组ImageViews,而View内部有它自己的行为。 I'm trying to implement a drag and drop to the FrameLayouts while implementing the onTouchListener I found in this tutorial . 在实现本教程中发现的onTouchListener同时,我试图实现对FrameLayouts的拖放。 but unfortunately the drag 'n drop doesn't work properly and nothing is happening. 但不幸的是,拖放操作无法正常进行,并且没有任何反应。

any thoughts on how to implement the drag and drop correctly? 关于如何正确执行拖放的任何想法? what am I missing? 我想念什么?


here is the xml code for a single child of the FrameLayouts : 这是FrameLayouts的单个子FrameLayouts的xml代码:

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="80dp" android:layout_height="108dp" > <ImageView android:id="@+id/secondImage" android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/back" /> <ImageView android:id="@+id/firstImage" android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/c2" /> </FrameLayout> 


here is the xml code for the main.xml 这是main.xml的xml代码

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/pinecropped" android:orientation="vertical" > <FrameLayout android:id="@+id/cardNumber1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:layout_marginTop="60dp" > <include layout="@layout/card" /> </FrameLayout> <FrameLayout android:id="@+id/cardNumber2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/cardNumber1" android:layout_marginLeft="50dp" android:layout_marginTop="100dp" > <include layout="@layout/card" /> </FrameLayout> <FrameLayout android:id="@+id/cardNumber3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginRight="50dp" android:layout_marginTop="60dp" > <include layout="@layout/card" /> </FrameLayout> <FrameLayout android:id="@+id/cardNumber4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@+id/cardNumber3" android:layout_marginRight="50dp" android:layout_marginTop="100dp" > <include layout="@layout/card" /> </FrameLayout> </RelativeLayout> 


here is the Java code for the single child: 这是单个孩子的Java代码:

public class FaceUpActivity extends Activity {
    FrameLayout firstCard, secondCard, thirdCard, forthCard;
    Card cardNumber1, cardNumber2, cardNumber3, cardNumber4;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        initUI();
    }

    private void initUI() {
        firstCard = (FrameLayout) findViewById(R.id.cardNumber1);
        secondCard = (FrameLayout) findViewById(R.id.cardNumber2);
        thirdCard = (FrameLayout) findViewById(R.id.cardNumber3);
        forthCard = (FrameLayout) findViewById(R.id.cardNumber4);

        cardNumber1 = new Card(this, firstCard);
        cardNumber2 = new Card(this, secondCard);
        cardNumber3 = new Card(this, thirdCard);
        cardNumber4 = new Card(this, forthCard);

        cardNumber1.setupCards(R.drawable.c2, true);
        cardNumber2.setupCards(R.drawable.d0, true);
        cardNumber3.setupCards(R.drawable.h5, true);
        cardNumber4.setupCards(R.drawable.sj, true);

        firstCard.setOnTouchListener(dragMe);
        secondCard.setOnTouchListener(dragMe);
        thirdCard.setOnTouchListener(dragMe);
        forthCard.setOnTouchListener(dragMe);

    }

    OnTouchListener dragMe = new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            FrameLayout.LayoutParams params = (LayoutParams) v
                    .getLayoutParams();
            int maxWidth = getWindowManager().getDefaultDisplay().getWidth();
            int maxHeight = getWindowManager().getDefaultDisplay().getHeight();
            int topMargin, leftMargin;

            int cond = v.getId();
            if (cond == R.id.cardNumber1 || cond == R.id.cardNumber2
                    || cond == R.id.cardNumber3 || cond == R.id.cardNumber4) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_UP:

                    topMargin = (int) event.getRawY() - (v.getHeight());
                    leftMargin = (int) event.getRawX() - (v.getWidth()) / 2;

                    if (topMargin < 0) {
                        params.topMargin = 0;
                    } else if (topMargin > maxHeight) {
                        params.topMargin = maxHeight - v.getHeight();
                    } else {
                        params.topMargin = topMargin;
                    }

                    if (leftMargin < 0) {
                        params.leftMargin = 0;
                    } else if (leftMargin > maxWidth) {
                        params.leftMargin = maxWidth - (v.getWidth() / 2);
                    } else {
                        params.leftMargin = leftMargin;
                    }

                    v.setLayoutParams(params);

                    break;

                case MotionEvent.ACTION_MOVE:

                    topMargin = (int) event.getRawY() - (v.getHeight());
                    leftMargin = (int) event.getRawX() - (v.getWidth()) / 2;

                    if (topMargin < 0) {
                        params.topMargin = 0;
                    } else if (topMargin > maxHeight) {
                        params.topMargin = maxHeight - v.getHeight();
                    } else {
                        params.topMargin = topMargin;
                    }

                    if (leftMargin < 0) {
                        params.leftMargin = 0;
                    } else if (leftMargin > maxWidth) {
                        params.leftMargin = maxWidth - (v.getWidth() / 2);
                    } else {
                        params.leftMargin = leftMargin;
                    }

                    v.setLayoutParams(params);

                    break;
                }
            }
            return true;
        }
    };
}


this is my main activity Java code: 这是我的主要活动Java代码:

 public class FaceUpActivity extends Activity { FrameLayout firstCard, secondCard, thirdCard, forthCard; Card cardNumber1, cardNumber2, cardNumber3, cardNumber4; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initUI(); } private void initUI() { firstCard = (FrameLayout) findViewById(R.id.cardNumber1); secondCard = (FrameLayout) findViewById(R.id.cardNumber2); thirdCard = (FrameLayout) findViewById(R.id.cardNumber3); forthCard = (FrameLayout) findViewById(R.id.cardNumber4); cardNumber1 = new Card(this, firstCard); cardNumber2 = new Card(this, secondCard); cardNumber3 = new Card(this, thirdCard); cardNumber4 = new Card(this, forthCard); cardNumber1.setupCards(R.drawable.c2, true); cardNumber2.setupCards(R.drawable.d0, true); cardNumber3.setupCards(R.drawable.h5, true); cardNumber4.setupCards(R.drawable.sj, true); firstCard.setOnTouchListener(dragMe); secondCard.setOnTouchListener(dragMe); thirdCard.setOnTouchListener(dragMe); forthCard.setOnTouchListener(dragMe); } OnTouchListener dragMe = new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { FrameLayout.LayoutParams params = (LayoutParams) v .getLayoutParams(); int maxWidth = getWindowManager().getDefaultDisplay().getWidth(); int maxHeight = getWindowManager().getDefaultDisplay().getHeight(); int topMargin, leftMargin; int cond = v.getId(); if (cond == R.id.cardNumber1 || cond == R.id.cardNumber2 || cond == R.id.cardNumber3 || cond == R.id.cardNumber4) { switch (event.getAction()) { case MotionEvent.ACTION_UP: topMargin = (int) event.getRawY() - (v.getHeight()); leftMargin = (int) event.getRawX() - (v.getWidth()) / 2; if (topMargin < 0) { params.topMargin = 0; } else if (topMargin > maxHeight) { params.topMargin = maxHeight - v.getHeight(); } else { params.topMargin = topMargin; } if (leftMargin < 0) { params.leftMargin = 0; } else if (leftMargin > maxWidth) { params.leftMargin = maxWidth - (v.getWidth() / 2); } else { params.leftMargin = leftMargin; } v.setLayoutParams(params); break; case MotionEvent.ACTION_MOVE: topMargin = (int) event.getRawY() - (v.getHeight()); leftMargin = (int) event.getRawX() - (v.getWidth()) / 2; if (topMargin < 0) { params.topMargin = 0; } else if (topMargin > maxHeight) { params.topMargin = maxHeight - v.getHeight(); } else { params.topMargin = topMargin; } if (leftMargin < 0) { params.leftMargin = 0; } else if (leftMargin > maxWidth) { params.leftMargin = maxWidth - (v.getWidth() / 2); } else { params.leftMargin = leftMargin; } v.setLayoutParams(params); break; } } return true; } }; } 

I think there are a couple of potential problems: 我认为有两个潜在问题:

  1. Are you sure you're getting the correct IDs in your onTouch() ? 您确定在onTouch()获得正确的ID吗? (since the touch listener is only used with your card views, you propably can remove the if checking for the IDs) (由于触摸监听器仅用于您的名片视图,因此, if检查ID, if可以删除)
  2. You are using a FrameLayout - so use the x and y position instead of margins edit: my bad, you're using RelativeLayout , so the margins are kind of right. 您正在使用 FrameLayout因此请使用x和y位置而不是margins 编辑:不好,您正在使用RelativeLayout ,因此margins是正确的。 Though, I'd use a FrameLayout instead 不过,我会改用FrameLayout
  3. the API says you need to return true in onTouch() if you consumed the event, false otherwise (you're returning true when you didn't move the cards and nothing when you did) API指出,如果您消耗了事件,则需要在onTouch()返回true ,否则返回false (当您不移动卡时,您将返回true当您不进行操作时,您将不返回)

Why your D&D is not working: 为什么您的D&D无法正常工作:

D&D is not working because your Card (that useses the internal FrameLayout) is implementing the onClick event that "eat" the d&d event. D&D无法正常工作,因为您的Card(使用内部FrameLayout)正在实现“吞噬” d&d事件的onClick事件。

Solutions are two: 解决方法有两种:

you can have 2 different areas, one for the click event (the biggest part of the card), one for the d&d event (the bottom-left edge of the card). 您可以有2个不同的区域,一个区域用于单击事件(卡的最大部分),一个区域用于d&d事件(卡的左下边缘)。 You can see a live example in the Android Music player that implements this solution. 您可以在实现此解决方案的Android音乐播放器中看到一个实时示例。

Otherwise you can handle the two events at the same time: 否则,您可以同时处理两个事件:

  • click == down+up in the same time (under 100ms) in the same x/y location 在同一x / y位置同时(= 100毫秒内)单击==向下+向上
  • dd == down+up in different times ( > 50/100ms) dd ==在不同时间向下+向上(> 50 / 100ms)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM