Android: reorder views using drag and drop

I am trying to rearrange views (specifically maps) using drag-and-drop.

My initial thought for a simple implementation is to move the view by removing it from the parent and then adding it to the spot on the left or right.

This seems to work fine without animation, but once I start using animation, sometimes the cards get stuck. I am getting the error:

java.lang.NullPointerException: Attempting to read from field 'android.view.IWindowSession android.view.View $ AttachInfo.mSession' on null object reference in android.view.View.startDrag (View.java:18353) at cz.cvut .mazelmir.cards.Cards $ AFragment $ 2.onTouch (Anagram.java:158)

I'm not really sure what to do with this, as the things passed to onTouch

are touch the view (shouldn't be null) and the newly created parameters.

Are there any clues as to why this is happening and what I can do to fix it? Or at least some hints on how best to implement this drag and drop functionality? (Possibly a simple frame view where I just animated the cards?)

Here's the code for the snippet containing the maps: (The slice layout is just a linear layout, and the map layout contains a text image.)

public static class AFragment extends Fragment {

    String s = "string";
    ViewGroup emptyContainer;
    View[] cards;
    float[] cardLoc;

    public AFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, final ViewGroup container,
                             Bundle savedInstanceState) {
        LinearLayout linearLayout = (LinearLayout) inflater.inflate(R.layout.fragment_anagram, container, false);
        emptyContainer = null;
        cards = null;
        cardLoc = null;

        createCards(inflater, linearLayout, s);

        linearLayout.setOnDragListener(new View.OnDragListener() {
            @Override
            public boolean onDrag(View view, DragEvent event) {
                View draggedItem = (View) event.getLocalState();
                ViewGroup viewGroup = (ViewGroup) view;
                switch (event.getAction()) {
                    case DragEvent.ACTION_DRAG_STARTED:
                        if (cardLoc == null)
                            createPositions();
                        emptyContainer = viewGroup;
                        draggedItem.setVisibility(View.INVISIBLE);
                        break;
                    case DragEvent.ACTION_DRAG_LOCATION:
                        int emptyPos = (int)draggedItem.getTag(R.id.position_tag);
                        float currentX = event.getX();

                        // To the right?
                        if (emptyPos < cardLoc.length - 1 && currentX > cardLoc[emptyPos + 1]) {
                            viewGroup.removeView(cards[emptyPos + 1]);
                            viewGroup.addView(cards[emptyPos + 1], emptyPos);

                            TranslateAnimation translateAnimation = new TranslateAnimation(cardLoc[emptyPos + 1] - cardLoc[emptyPos], 0, 0, 0);
                            translateAnimation.setDuration(200);
                            cards[emptyPos + 1].startAnimation(translateAnimation);

                            View tempView = cards[emptyPos + 1];
                            cards[emptyPos + 1] = cards[emptyPos];
                            cards[emptyPos] = tempView;

                            draggedItem.setTag(R.id.position_tag, emptyPos + 1);
                            tempView.setTag(R.id.position_tag, emptyPos);
                        }
                        // To the left?
                        else if (emptyPos > 0 && currentX < cardLoc[emptyPos]) {
                            viewGroup.removeView(cards[emptyPos - 1]);
                            viewGroup.addView(cards[emptyPos - 1], emptyPos);

                            TranslateAnimation translateAnimation = new TranslateAnimation(cardLoc[emptyPos - 1] - cardLoc[emptyPos], 0, 0, 0);
                            translateAnimation.setDuration(200);
                            cards[emptyPos - 1].startAnimation(translateAnimation);

                            View tempView = cards[emptyPos - 1];
                            cards[emptyPos - 1] = cards[emptyPos];
                            cards[emptyPos] = tempView;

                            draggedItem.setTag(R.id.position_tag, emptyPos - 1);
                            tempView.setTag(R.id.position_tag, emptyPos);
                        }

                        break;
                    case DragEvent.ACTION_DRAG_ENDED:
                        draggedItem.setVisibility(View.VISIBLE);
                        break;
                    default:
                        break;
                }
                return true;
            }
        });

        return linearLayout;
    }

    private void createCards(LayoutInflater inflater, LinearLayout container, String s) {
        cards = new View[s.length()];
        int j = 0;
        for (char c : s.toCharArray()) {
            String letter = String.valueOf(c);

            View letterCard = inflater.inflate(R.layout.letter_container, container, false);
            TextView letterTextView = (TextView) letterCard.findViewById(R.id.letter_text);
            letterTextView.setText(letter);
            letterCard.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        ClipData data = ClipData.newPlainText("", "");
                        View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
                        v.startDrag(data, shadowBuilder, v, 0);
                        return true;
                    }
                    return false;
                }
            });
            cards[j] = letterCard;
            container.addView(letterCard);

            letterCard.setTag(R.id.position_tag, j);
            letterCard.setTag(R.id.letter_tag, letter);

            j++;
        }
    }

    public void createPositions() {
        cardLoc = new float[cards.length];
        for (int i = 0; i < cards.length; i++) {
            cardLoc[i] = cards[i].getX();
        }
    }
}
}

      

+3


source to share





All Articles