I'm looking for a direction to go with this one. I have a card melding game (Five Kings) which has been up for about 6 months; my latest version 0.9.22 has been stable since March. However, recently I have been getting reports of users unable to drag discards to the discard pile, and the common thread seems to be Samsung S7 with Android 6.0 . When you drag a card from your hand, the places you can drag turn transparent and when you drag over them they go back to normal (alpha=1). Other places you can drag seem to be working ok, but the discard pile doesn't go dim or bright, which makes me think the Drag Event listener isn't working.
Here's the DiscardPileDragEventListener
:
class DiscardPileDragEventListener implements View.OnDragListener {
// This is the method that the system calls when it dispatches a drag event to the
// listener.
@Override
public boolean onDrag(final View v, final DragEvent event) {
//that we are not ready to accept the drag if not at the right point of the play
CardView cv = (CardView)v;
// Defines a variable to store the action type for the incoming event
final int action = event.getAction();
// Handles each of the expected events
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
// Determines if this View can accept the dragged data
if (cv.isAcceptDrag() && event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
//fades out of the draw pile
cv.startAnimation(Utilities.instantFade(FiveKings.HALF_TRANSPARENT_ALPHA, FiveKings.HALF_TRANSPARENT_ALPHA));
// returns true to indicate that the View can accept the dragged data.
return true;
} else {
//remind user what they should be doing if in the first few rounds
((FiveKings) cv.getContext()).setShowHint(null, FiveKings.HandleHint.SHOW_HINT, FiveKings.GameDifficulty.EASY);
// Returns false. During the current drag and drop operation, this View will
// not receive events again until ACTION_DRAG_ENDED is sent.
return false;
}
case DragEvent.ACTION_DRAG_ENTERED:
cv.clearAnimation();
return true;
case DragEvent.ACTION_DRAG_LOCATION:
// Ignore the event
return true;
case DragEvent.ACTION_DRAG_EXITED:
cv.startAnimation(Utilities.instantFade(FiveKings.HALF_TRANSPARENT_ALPHA, FiveKings.HALF_TRANSPARENT_ALPHA));
return true;
case DragEvent.ACTION_DROP:
cv.clearAnimation();
// Gets the item containing the dragged data
ClipData.Item item = event.getClipData().getItemAt(0); //this is the View index to recover which card
// Gets the text data from the item.
String dragData = item.getText().toString();
//Handle exception here and return false (drop wasn't handled) if it wasn't found
int iView = -1;
try {
iView = Integer.parseInt(dragData);
}catch (NumberFormatException e) {
return false;
}
return ((FiveKings)cv.getContext()).discardedCard(iView);
case DragEvent.ACTION_DRAG_ENDED:
if (cv.isAcceptDrag()) cv.clearAnimation();
return true;
// An unknown action type was received.
default:
Log.e("DiscardPileDragEventListener", "Unknown action type received by OnDragListener.");
}
return false;
}
}
Here's the code snippets which sets up the actual dragged card; in this CardView is a subclass of ImageView:
for (Card card : meld) {
//highlight wildcards unless no dragging (Computer turn, or Human final turn)
CardView cv = new CardView(this, card, iView, allowDragging ? highlightWildCardRank : null);
cv.setTag(iView); //allows us to pass the index into the dragData without dealing with messy object passing
...
cv.bringToFront();
cv.setClickable(false); //TODO:B: Allow selection by clicking for multi-drag?
if (allowDragging) {//no dragging of computer cards or Human cards after final turn
cv.setOnDragListener(new CardViewDragEventListener()); //needed per-card to reset the dragged card to normal visibility (alpha)
cv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN) return false;
// Create a new ClipData using the tag as a label, the plain text MIME type, and
// the string containing the View index. This will create a new ClipDescription object within the
// ClipData, and set its MIME type entry to "text/plain"
ClipData dragData = ClipData.newPlainText("Discard", v.getTag().toString());
View.DragShadowBuilder cardDragShadow = new CardViewDragShadowBuilder(v);
v.startAnimation(Utilities.instantFade(FiveKings.HALF_TRANSPARENT_ALPHA, FiveKings.HALF_TRANSPARENT_ALPHA));
// Starts the drag
v.startDrag(dragData, cardDragShadow, null, 0);
return true;
}//end onClick
});
}//end if allowDragging
...
And in the onCreate, I set up the Discard Pile onDragListener: ... mDiscardPile.setOnDragListener(new DiscardPileDragEventListener()); ...
One wrinkle is that I also have a an onDragListener in the parent view of the Discard Pile, to provide a message as you drag your card to the Discard Pile. This has worked fine in my testing, but I just wonder if it's related somehow.
Would appreciate any suggestions as to which direction to head.
Aucun commentaire:
Enregistrer un commentaire