• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Check if the the selected item in listview is in correct position (index)

Gel06

Newbie
I have an arraylist which is displayed in a listview. The items in this listview can be rearranged. The items are displayed in random order using Collections.shuffle. I want to rearrange the items inside the listview according to its designated procedure number.

For example:

Procedure number 4 //index 0

Procedure number 2 //index 1

Procedure number 1 //index 2

Procedure number 3 //index 3

Once the user dragged "Procedure number 3" and dropped it at index 0, this should display a toast that it is placed in the wrong position. But if it is dropped at index 2, this should display a toast that it is in the correct position of index.

Here's a snippet of my code:

Java:
mItemArray = new ArrayList<>();
    for (int i = 0; i < 8; i++) {
        mItemArray.add(new Pair<>(Long.valueOf(i), "Procedure number " + i));
    }
    Collections.shuffle(mItemArray);

    mDragListView.setDragListListener(new DragListView.DragListListenerAdapter() {
        @Override
        public void onItemDragStarted(int position) {
            mRefreshLayout.setEnabled(false);
            Toast.makeText(mDragListView.getContext(), "Start - position: " + position, Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onItemDragEnded(int fromPosition, int toPosition) {
            mRefreshLayout.setEnabled(true);
            if (fromPosition != toPosition) {
                Toast.makeText(mDragListView.getContext(), "End - position: " + toPosition, Toast.LENGTH_SHORT).show();
            }
        }
    });

How can I achieve this? Any help is appreciated. Thank you.
 
Difficult to answer, given the above code fragment, but last time I wanted a draggable Listview, I used this library

https://github.com/woxblom/DragListView

Are you setting the list adapter, something like this?

Code:
ItemAdapter listAdapter = new ItemAdapter(mItemArray, R.layout.list_item, R.id.image, false);
   mDragListView.setAdapter(listAdapter);
 
Difficult to answer, given the above code fragment, but last time I wanted a draggable Listview, I used this library

https://github.com/woxblom/DragListView

Are you setting the list adapter, something like this?

Code:
ItemAdapter listAdapter = new ItemAdapter(mItemArray, R.layout.list_item, R.id.image, false);
   mDragListView.setAdapter(listAdapter);
Yes I'm using that library and I'm setting the list adapter like that. Here is my ListFragment:

Java:
public class ListFragment extends Fragment {

    private ArrayList<Pair<Long, String>> mItemArray;
    private ArrayList<String> procedureArray;
    private DragListView mDragListView;
    private MySwipeRefreshLayout mRefreshLayout;

    public static ListFragment newInstance() {
        return new ListFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list_layout, container, false);
        mRefreshLayout = (MySwipeRefreshLayout) view.findViewById(R.id.swipe_refresh_layout);
        mDragListView = (DragListView) view.findViewById(R.id.drag_list_view);
        mDragListView.getRecyclerView().setVerticalScrollBarEnabled(true);

        mItemArray = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            mItemArray.add(new Pair<>(Long.valueOf(i), "Procedure number " + i));
        }
        Collections.shuffle(mItemArray);

        mDragListView.setDragListListener(new DragListView.DragListListenerAdapter() {
            @Override
            public void onItemDragStarted(int position) {
                mRefreshLayout.setEnabled(false);
                Toast.makeText(mDragListView.getContext(), "Start - position: " + position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemDragEnded(int fromPosition, int toPosition) {
                mRefreshLayout.setEnabled(true);
                if (fromPosition != toPosition) {
                    Toast.makeText(mDragListView.getContext(), "End - position: " + toPosition, Toast.LENGTH_SHORT).show();
                }
            }

        });

        mRefreshLayout.setScrollingView(mDragListView.getRecyclerView());
        mRefreshLayout.setColorSchemeColors(ContextCompat.getColor(getContext(), R.color.app_color));
        mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mRefreshLayout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mRefreshLayout.setRefreshing(false);
                    }
                }, 2000);
            }
        });

        setupListRecyclerView();
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Re-arrange first aid procedures");
    }


    private void setupListRecyclerView() {
        mDragListView.setLayoutManager(new LinearLayoutManager(getContext()));
        ItemAdapter listAdapter = new ItemAdapter(mItemArray, R.layout.list_item, R.id.image, false);
        mDragListView.setAdapter(listAdapter, true);
        mDragListView.setCanDragHorizontally(false);
        mDragListView.setCustomDragItem(new MyDragItem(getContext(), R.layout.list_item));
    }

    private static class MyDragItem extends DragItem {

        public MyDragItem(Context context, int layoutId) {
            super(context, layoutId);
        }

        @Override
        public void onBindDragView(View clickedView, View dragView) {
            CharSequence text = ((TextView) clickedView.findViewById(R.id.text)).getText();
            ((TextView) dragView.findViewById(R.id.text)).setText(text);
            dragView.setBackgroundColor(dragView.getResources().getColor(R.color.list_item_background));
        }
    }
}
 
Did you set a breakpoint in method onItemDragEnded() to verify that it's called? What were the values of 'fromPosition' and 'toPosition'?
 
A toast is displayed once an item stopped from dragging. The fromPosition is the starting index or position of the item, while the toPosition is its ending position or index.
 
What exactly is the problem? You said in your first post

Once the user dragged "Procedure number 3" and dropped it at index 0, this should display a toast that it is placed in the wrong position. But if it is dropped at index 2, this should display a toast that it is in the correct position of index.

Implying that the toast isn't displayed.
 
Code:
@Override123 
public void onItemDragEnded(int fromPosition, int toPosition) {
  mRefreshLayout.setEnabled(true);
  if (Long.valueOf(toPosition).equals(mItemArray.get(toPosition).getKey()) {
    // This is the correct position
  }
  else {
    // This is not the correct position
  }
}
 
Code:
@Override123
public void onItemDragEnded(int fromPosition, int toPosition) {
  mRefreshLayout.setEnabled(true);
  if (Long.valueOf(toPosition).equals(mItemArray.get(toPosition).getKey()) {
    // This is the correct position
  }
  else {
    // This is not the correct position
  }
}
Thanks for your suggestion, but it didn't worked. It always shows it is not in the correct position. And by the way there is no getKey method.
 
Ok so you're probably using the Pair class from android.support.v4.util, in which case that includes public class variables 'first' and 'second'. so the above code becomes

Code:
@Override123
public void onItemDragEnded(int fromPosition, int toPosition) {
  mRefreshLayout.setEnabled(true);
  if (Long.valueOf(toPosition).equals((Long)(mItemArray.get(toPosition).first)) {
    // This is the correct position
  }
  else {
    // This is not the correct position
  }
}

Btw, you can navigate to the Pair class definition and have a look at it yourself very easily, by hovering over the import statement at the top of your code, pressing the CTRL key and clicking the left mouse button. This takes you to the code of the Pair class. Look at the definition of it. Notice the 'first' and 'second' class variables, which correspond to the two types of objects you are using.

Code:
package android.support.v4.util;

/**
* Container to ease passing around a tuple of two objects. This object provides a sensible
* implementation of equals(), returning true if equals() is true on each of the contained
* objects.
*/
public class Pair<F, S> {
    public final F first;
    public final S second;

    ....

Pair is a generic class. Please read this to gain some understanding of what that means -

https://docs.oracle.com/javase/tutorial/java/generics/types.html

You declared mItemArray as follows

Code:
private ArrayList<Pair<Long, String>> mItemArray;

which tells the compiler to substitute types 'Long' and 'String' for the above class variable types 'F' and 'S', respectively.


Can I also strongly recommend that you become familiar with running your app in debug mode, and setting breakpoints in the code. This will allow you to examine variable values as the app is running.

It's all explained in the sticky post at the top of this forum. Being familiar with debugging techniques is the most important thing to learn for a s/w developer, believe me it will make your life a lot easier.

http://androidforums.com/threads/please-read-me-before-posting.987318/
 
Java:
boolean answerCheck = false;
while(!answerCheck) {
                    if (Long.valueOf(toPosition).equals((Long) (mItemArray.get(toPosition).first))) {
                        // This is the correct position
                        answerCheck = true;
                        checkAnswerBT.setClickable(true);
                        Toast.makeText(mDragListView.getContext(), "Correct order of steps!", Toast.LENGTH_SHORT).show();

                        checkAnswerBT.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                DisplayScoreFragment displayScoreFragment = new DisplayScoreFragment();
                                FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
                                fragmentTransaction.add(displayScoreFragment, "displayScoreFragment")
                                        .replace(R.id.fragment_container, displayScoreFragment)
                                        .addToBackStack("displayScoreFragment")
                                        .commit();
                            }
                        });
                    } else {
                        // This is not the correct position
                        answerCheck = false;
                        checkAnswerBT.setClickable(false);
                        Toast.makeText(mDragListView.getContext(), "Incorrect order of steps. Try again.", Toast.LENGTH_SHORT).show();
                        break;
                    }
Ok so you're probably using the Pair class from android.support.v4.util, in which case that includes public class variables 'first' and 'second'. so the above code becomes

Code:
@Override123
public void onItemDragEnded(int fromPosition, int toPosition) {
  mRefreshLayout.setEnabled(true);
  if (Long.valueOf(toPosition).equals((Long)(mItemArray.get(toPosition).first)) {
    // This is the correct position
  }
  else {
    // This is not the correct position
  }
}

Btw, you can navigate to the Pair class definition and have a look at it yourself very easily, by hovering over the import statement at the top of your code, pressing the CTRL key and clicking the left mouse button. This takes you to the code of the Pair class. Look at the definition of it. Notice the 'first' and 'second' class variables, which correspond to the two types of objects you are using.

Code:
package android.support.v4.util;

/**
* Container to ease passing around a tuple of two objects. This object provides a sensible
* implementation of equals(), returning true if equals() is true on each of the contained
* objects.
*/
public class Pair<F, S> {
    public final F first;
    public final S second;

    ....

Pair is a generic class. Please read this to gain some understanding of what that means -

https://docs.oracle.com/javase/tutorial/java/generics/types.html

You declared mItemArray as follows

Code:
private ArrayList<Pair<Long, String>> mItemArray;

which tells the compiler to substitute types 'Long' and 'String' for the above class variable types 'F' and 'S', respectively.


Can I also strongly recommend that you become familiar with running your app in debug mode, and setting breakpoints in the code. This will allow you to examine variable values as the app is running.

It's all explained in the sticky post at the top of this forum. Being familiar with debugging techniques is the most important thing to learn for a s/w developer, believe me it will make your life a lot easier.

http://androidforums.com/threads/please-read-me-before-posting.987318/


Thank you for your suggestion! I have one last question, I created a loop that should check if all of the items are in the correct position. If it is in correct position next button should be enabled and will be able to redirect to another fragment. But if the items or an item is/are not in correct position, the button should be disabled.

My loop doesn't work properly. Attached is my code snippet
 
Did you learn how to run your app in debug mode, and set breakpoints in the code?
 
I've tried running it in debug mode

Ok that's a start, but simply running the app in debug mode won't solve the problem.
You need to do something called "debugging". This involves applying some brain power, and working out why things are not happening the way you expect. This process is known as software development, and unfortunately, interactive debugging of code isn't really practical via an online forum. So, in order to understand why your code isn't behaving as it should, what we normally do is set breakpoints at key lines within the program. At a breakpoint, execution of the code will stop, and this enables you to examine variable values, and also step through the code line by line, and this should hopefully allow you to understand what's happening.

To get started, I suggest setting a breakpoint at the following line, and stepping through the code, line by line, to see what happens:

Code:
boolean answerCheck = false;
 
Last edited by a moderator:
Ok that's a start, but simply running the app in debug mode won't solve the problem.
You need to do something called "debugging". This involves applying some brain power, and working out why things are not happening the way you expect. This process is known as software development, and unfortunately, interactive debugging of code isn't really practical via an online forum. So, in order to understand why your code isn't behaving as it should, what we normally do is set breakpoints at key lines within the program. At a breakpoint, execution of the code will stop, and this enables you to examine variable values, and also step through the code line by line, and this should hopefully allow you to understand what's happening.

To get started, I suggest setting a breakpoint at the following line, and stepping through the code, line by line, to see what happens:

Code:
boolean answerCheck = false;
After I step through the code line by line starting from
Code:
boolean answerCheck = false;
, I noticed that after it passes through line 6 (sets the answerCheck variable to true), the variable declaration in line 2 also changes that's why it's giving me an infinite loop. Now how am I going to fix this? I need to check either if all of the items are in correct position or not.
 
the variable declaration in line 2 also changes

Sorry I don't understand what you mean by this. That statement can not change the value of answerCheck once this line has been executed.
 
What should I change in my looping statement?

That's not an answer to the question I asked. You haven't clarified "the variable declaration in line 2 also changes". It doesn't make sense.

So you said you have an infinite loop. But I don't see how, because you already said that the execution flow goes into the first block of the 'if' statement, which then sets answerCheck to true, so your loop will terminate.

And if the execution goes into the 'else' block, then you have a break statement, which will definitely terminate the loop.

So how come you have an infinite loop situation?
 
Last edited by a moderator:
That's not an answer to the question I asked. You haven't clarified "the variable declaration in line 2 also changes". It doesn't make sense.

So you said you have an infinite loop. But I don't see how, because you already said that the execution flow goes into the first block of the 'if' statement, which then sets answerCheck to true, so your loop will terminate.

And if the execution goes into the 'else' block, then you have a break statement, which will definitely terminate the loop.

So how come you have an infinite loop situation?
Sorry, the code I posted wasn't updated. My checkAnswer was set to true and not false. Anyway, I removed my looping statement, I have come up with a solution to check if all of the items are in correct position but I think this isn't the best solution.

Code:
if(mItemArray.get(0).second.contains("Wash") && mItemArray.get(1).second.contains("Apply") &&
        mItemArray.get(2).second.contains("Cover") && mItemArray.get(3).second.contains("Repeat"))

Any suggestions?
 
Sorry, the code I posted wasn't updated

FYI there is absolutely no hope in hell of anyone being able to answer your question, if you don't post the correct code in the first place.
 
FYI there is absolutely no hope in hell of anyone being able to answer your question, if you don't post the correct code in the first place.
Yeah I'm sorry about that. Anyway, like what I've said I'm checking the order of my list view like this:

Java:
if(chosenInjury.equals("Abrasion")){
                    if(mItemArray.get(0).second.startsWith("Wash") && mItemArray.get(1).second.startsWith("Apply") &&
                            mItemArray.get(2).second.startsWith("Cover") && mItemArray.get(3).second.startsWith("Repeat")){
                        goToScoreFragment();
                    } else{
                        Toast.makeText(mDragListView.getContext(), "Incorrect order of procedures. Try again.", Toast.LENGTH_SHORT).show();
                    }
                } else if(chosenInjury.equals("Fracture")){
                    if(mItemArray.get(0).second.startsWith("In") && mItemArray.get(1).second.startsWith("If")
                            && mItemArray.get(2).second.startsWith("Support") && mItemArray.get(3).second.startsWith("Raise")
                            && mItemArray.get(4).second.startsWith("Immobilize") && mItemArray.get(5).second.startsWith("Check")
                            && mItemArray.get(6).second.startsWith("Watch") && mItemArray.get(7).second.startsWith("Call")){
                        goToScoreFragment();
                    } else{
                        Toast.makeText(mDragListView.getContext(), "Incorrect order of procedures. Try again.", Toast.LENGTH_SHORT).show();
                    }
                }

This works, however, I think there's better approach or way on how to check its ordering. Any suggestions on this?
 
What was wrong with the solution I suggested in post #10?

The problem you have with what you posted above is that it's hardcoded, and not very flexible.
You already have all the information in mItemArray to check that all items are in the right position.

What I would do is iterate over all the items, and check that each item is in the correct position. No need for comparing strings, and checking that they contain certain character sequences.
All you need to do is check that the 'First' item of the Pair, is the same as the array item index.

Do you know how to create a loop that iterates over all items in a collection?
 
Last edited by a moderator:
What was wrong with the solution I suggested in post #10?

The problem you have with what you posted above is that it's hardcoded, and not very flexible.
You already have all the information in mItemArray to check that all items are in the right position.

What I would do is iterate over all the items, and check that each item is in the correct position. No need for comparing strings, and checking that they contain certain character sequences.
All you need to do is check that the 'First' item of the Pair, is the same as the array item index.

Do you know how to create a loop that iterates over all items in a collection?
I tried something like this:
Java:
if(chosenInjury.equals("Abrasion"){
for (int counter = 0; counter < abrasionProcedure.length; ++counter) {
      mDragListView.setDragListListener(new DragListView.DragListListenerAdapter() {
            @Override
            public void onItemDragEnded(int fromPosition, int toPosition) {
                if (Long.valueOf(toPosition).equals((Long)(mItemArray.get(toPosition).first))) {
                    //go to next fragment
                } else {
                    //display toast incorrect order of procedures
                }
            }
}
Is this the right way?
 
No.

You want to put the checking loop in the onItemDragEnded() method.

So the logic is:-

1. User drags item to a position in the list
2. Code goes through all items in the list array to check each item's position against where it's supposed to be
3. If any are out of position, then the user got it wrong.
4. Go to step 1 if any items are out of position
 
No.

You want to put the checking loop in the onItemDragEnded() method.

So the logic is:-

1. User drags item to a position in the list
2. Code goes through all items in the list array to check each item's position against where it's supposed to be
3. If any are out of position, then the user got it wrong.
4. Go to step 1 if any items are out of position
So I did this:
Java:
if(chosenInjury.equals("Abrasion")){
                    mDragListView.setDragListListener(new DragListView.DragListListenerAdapter(){
                        @Override
                        public void onItemDragEnded(int fromPosition, int toPosition) {
                            for (int counter = 0; counter < abrasionProcedure.length; ++counter){
                                if (Long.valueOf(toPosition).equals((Long)(mItemArray.get(toPosition).first))) {
                                    goToScoreFragment();
                                } else {
                                    Toast.makeText(mDragListView.getContext(), "ncorrect order of procedures. Try again.", Toast.LENGTH_SHORT).show();
                                }
                            }
                        }

                    });
But everytime I drag a certain item in its correct position, it immediately goes to the goToScoreFragment even though the other items are still not in their correct position. What I want to do is one time checking of all of the items in the list. Something like
Code:
if all of the items are in correct position
      then proceed to the next fragment
else
      stay in the current fragment until all of the items are in correct position
 
Back
Top Bottom