Android:onTouchListener无法正常工作

Android:onTouchListener无法正常工作,android,android-layout,ontouchlistener,Android,Android Layout,Ontouchlistener,我目前正在开发一个应用程序,它有一个RelativeLayout,它有4个子FrameLayouts,每个FrameLayout内部都有一组图像视图,内部视图有自己的行为。在实现我在中找到的onTouchListener时,我正在尝试实现拖放到FrameLayouts。但不幸的是,拖放不能正常工作,什么也没有发生 关于如何正确实现拖放功能有什么想法吗?我错过了什么 以下是FrameLayouts的单个子级的xml代码: <?xml version="1.0" encoding="utf-

我目前正在开发一个应用程序,它有一个
RelativeLayout
,它有4个子
FrameLayouts
,每个FrameLayout内部都有一组图像视图,内部视图有自己的行为。在实现我在中找到的
onTouchListener
时,我正在尝试实现拖放到
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>

以下是针对单个孩子的Java代码:

public class Card implements OnClickListener {
    private int _resId;

    private Context _context;
    private ImageView firstImage, secondImage;
    private boolean isFirst;

    public Card(Context context, FrameLayout parent) {
        _context = context;
        firstImage = (ImageView) parent.findViewById(R.id.firstImage);
        secondImage = (ImageView) parent.findViewById(R.id.secondImage);

    }

    public void setupCards(int resId, boolean hasBackSide) {
        _resId = resId;
        Bitmap temp = BitmapFactory.decodeResource(_context.getResources(),
                _resId);
        firstImage.setImageBitmap(temp);
        if (hasBackSide) {
            temp = BitmapFactory.decodeResource(_context.getResources(),
                    R.drawable.back);
        }
        secondImage.setImageBitmap(temp);
        isFirst = true;
        secondImage.setVisibility(View.GONE);

    }

    // MORE IMPLEMENTATION
}

这是我的主要活动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;
        }
    };
}
公共类FaceUpActivity扩展活动{
框架布局第一张卡、第二张卡、第三张卡、第四张卡;
卡号1、卡号2、卡号3、卡号4;
/**在首次创建活动时调用*/
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initUI();
}
私有void initUI(){
firstCard=(FrameLayout)findviewbyd(R.id.cardNumber1);
secondCard=(FrameLayout)findViewById(R.id.cardNumber2);
thirdCard=(FrameLayout)findViewById(R.id.cardNumber3);
forthCard=(FrameLayout)findviewbyd(R.id.cardNumber4);
cardNumber1=新卡(这是第一张卡);
cardNumber2=新卡(这是第二张卡);
cardNumber3=新卡(这是第三张卡);
cardNumber4=新卡(此为forthCard);
卡号1.设置卡(R.drawable.c2,真);
卡号2.设置卡(R.drawable.d0,真);
卡号3.设置卡(R.drawable.h5,正确);
卡号4.设置卡(R.drawable.sj,真);
firstCard.setOnTouchListener(dragMe);
secondCard.setOnTouchListener(dragMe);
第三张卡片:setOnTouchListener(dragMe);
forthCard.SETONTOUCH侦听器(dragMe);
}
OnTouchListener dragMe=新的OnTouchListener(){
@凌驾
公共布尔onTouch(视图v,运动事件){
FrameLayout.LayoutParams参数=(LayoutParams)v
.getLayoutParams();
int maxWidth=getWindowManager().getDefaultDisplay().getWidth();
int maxHeight=getWindowManager().getDefaultDisplay().getHeight();
int-topMargin,leftMargin;
int cond=v.getId();
如果(cond==R.id.cardNumber1 | | cond==R.id.cardNumber2
||cond==R.id.cardNumber3 | | cond==R.id.cardNumber4){
开关(event.getAction()){
case MotionEvent.ACTION\u UP:
topMargin=(int)event.getRawY()-(v.getHeight());
leftMargin=(int)event.getRawX()-(v.getWidth())/2;
如果(上边距<0){
params.topMargin=0;
}否则如果(topMargin>maxHeight){
params.topMargin=maxHeight-v.getHeight();
}否则{
params.topMargin=topMargin;
}
如果(左边距<0){
params.leftMargin=0;
}else if(leftMargin>maxWidth){
params.leftMargin=maxWidth-(v.getWidth()/2);
}否则{
params.leftMargin=leftMargin;
}
v、 setLayoutParams(参数);
打破
case MotionEvent.ACTION\u移动:
topMargin=(int)event.getRawY()-(v.getHeight());
leftMargin=(int)event.getRawX()-(v.getWidth())/2;
如果(上边距<0){
params.topMargin=0;
}否则如果(topMargin>maxHeight){
params.topMargin=maxHeight-v.getHeight();
}否则{
params.topMargin=topMargin;
}
如果(左边距<0){
params.leftMargin=0;
}else if(leftMargin>maxWidth){
params.leftMargin=maxWidth-(v.getWidth()/2);
}否则{
params.leftMargin=leftMargin;
}
v、 setLayoutParams(参数);
打破
}
}
返回true;
}
};
}

我认为存在两个潜在问题:

  • 您确定在
    onTouch()
    中获得了正确的ID吗?(由于touch listener仅用于卡视图,因此如果检查ID,您可以删除
  • 您使用的是
    FrameLayout
    -因此使用x和y位置而不是边距编辑:我的错,您使用的是
    RelativeLayout
    ,因此边距有点正确。不过,我会使用
    FrameLayout
  • API说,如果您使用了事件,则需要在
    onTouch()
    中返回
    true
    ,否则返回
    false
    (您没有移动卡时返回
    true
    ,移动卡时什么也没有返回)

  • 为什么您的D&D不起作用:

    D&D不起作用,因为您的卡(使用内部框架布局)正在实现onClick事件,该事件“吃掉”D&D事件

    解决办法有两个:

    您可以有两个不同的区域,一个用于单击事件(卡的最大部分),一个用于d&d事件(卡的左下边缘)。您可以在实现此解决方案的Android音乐播放器中看到一个实例

    否则,您可以同时处理这两个事件:

    • 在相同的x/y位置,在相同的时间内(100毫秒以下)单击==向下+向上
    • dd==在不同的位置向下+向上
      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;
              }
          };
      }