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. I'm trying to implement a drag and drop to the FrameLayouts
while implementing the onTouchListener
I found in this tutorial . 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?
FrameLayouts
:
<?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>
main.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>
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;
}
};
}
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:
onTouch()
? (since the touch listener is only used with your card views, you propably can remove the if
checking for the IDs) FrameLayout
- so use the x and y position instead of margins
RelativeLayout
, so the margins are kind of right. Though, I'd use a FrameLayout
instead 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) Why your D&D is not working:
D&D is not working because your Card (that useses the internal FrameLayout) is implementing the onClick event that "eat" the d&d event.
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). You can see a live example in the Android Music player that implements this solution.
Otherwise you can handle the two events at the same time:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.