0

I am making an app that has a list of exercises to do displayed in a ListView. I am trying to let the user select an item from the list to start a new activity, but my OnItemClickListener is not firing. Here is my Activity, (not a listActivity, it is appCompatActivity):

ArrayList<Exercise> myExercises = new ArrayList<>();
AlertDialog.Builder alertDialogBuilder;
ArrayAdapter<Exercise> arrayAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list);
    refreshList();
    Button newExButton = (Button) findViewById(R.id.newExButton);

    arrayAdapter = new ArrayAdapter<Exercise>(
            this,
            android.R.layout.simple_list_item_1,
            myExercises );

    ListView lv = (ListView) findViewById(R.id.actList);
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            System.out.println("listener heard");
            // selected item
            int selection = position;
            startExercise(selection);
        }
    });

    lv.setAdapter(arrayAdapter);
}

public void refreshList(){
    setContentView(R.layout.activity_list);
    ListView lv = (ListView) findViewById(R.id.actList);

    lv.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
    lv.setAdapter(arrayAdapter);
}

public void startExercise(int selection){

    Intent exIntent = new Intent(this, CommenceExercise.class);
    Exercise chosenEx = myExercises.get(selection);
    Bundle info = new Bundle();
    info.putLong("duration", chosenEx.getTime());
    info.putString("name", chosenEx.getName());
    info.putString("description", chosenEx.getDescription());
    exIntent.putExtras(info);
    startActivity(exIntent);
}

The list is initially empty, but the user adds items by pressing a button. The button creates an alertDialog through the code below:

public void addNewActivity(View view) {
    //get prompts.xml view
    LayoutInflater li = LayoutInflater.from(context);
    View promptsView = li.inflate(R.layout.custom, null);

    alertDialogBuilder = new AlertDialog.Builder(
            context);

    // set prompts.xml to alertdialog builder
    alertDialogBuilder.setView(promptsView);

    final EditText userInput = (EditText) promptsView
            .findViewById(R.id.exNameInput);
    final EditText durInput = (EditText) promptsView
            .findViewById(R.id.exDurInput);

    // set dialog message
    alertDialogBuilder
            .setCancelable(false)
            .setPositiveButton("OK",
                    new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,int id) {
                                    long duration = 0;
                                    String exName;
                                    exName = userInput.getText().toString();
                                    duration = Integer.valueOf(durInput.getText().toString());
                                    myExercises.add(new Exercise(exName, duration));
                                   // create new exercise with user input
                                    refreshList();
                                }
                            })
                    .setNegativeButton("Cancel",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,int id) {
                                    dialog.cancel();
                                }
                            });
            // create alert dialog
            AlertDialog alertDialog = alertDialogBuilder.create();
            // show it
            alertDialog.show();
}

}

And here is my xml:

<android.support.constraint.ConstraintLayout   
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
tools:context="com.example.mytimer.ListActivity">

<TextView
    android:id="@+id/textView2"
    android:layout_width="146dp"
    android:layout_height="30dp"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:layout_marginTop="16dp"
    android:text="Activities"
    android:textAlignment="center"
    android:textSize="24sp"
    app:layout_constraintHorizontal_bias="0.502"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginStart="16dp"
    android:clickable="false"
    android:layout_marginEnd="16dp" />

<Button
    android:id="@+id/newExButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:layout_marginStart="16dp"
    android:layout_marginTop="87dp"
    android:onClick="addNewActivity"
    android:text="New Exercise"
    android:textSize="18sp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/textView2" />

<ListView
    android:id="@+id/actList"
    android:layout_width="328dp"
    android:layout_height="301dp"
    android:layout_marginBottom="16dp"
    android:layout_marginEnd="16dp"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:descendantFocusability="blocksDescendants"
    android:focusable="false"
    android:clickable="false"
    android:focusableInTouchMode="false"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/newExButton"
    app:layout_constraintVertical_bias="1.0">
<requestFocus/>
</ListView>

<TextView
    android:id="@+id/debugText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="36dp"
    android:text="TextView"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    android:clickable="false"
    app:layout_constraintTop_toBottomOf="@+id/textView2" />

</android.support.constraint.ConstraintLayout>

When I tap an item I've added to the list, nothing happens. I can tell that the OnItemClickListener is not being fired because the System.out line is never printed. I'm at a loss as to why I can't get it to work. Any help would be greatly appreciated. Thanks in advance.

tacitunum
  • 3
  • 3
  • just change the `refreshList` method, it'll work..[read this also](https://developer.android.com/reference/android/widget/ArrayAdapter.html#notifyDataSetChanged()) – ELITE Jul 12 '17 at 05:12
  • also try setting the adaptor before setting the click listener – Ashutosh Sagar Jul 12 '17 at 05:52

4 Answers4

0

I think problem in XML Please set ListView clickable true

please do some changes in XML

<ListView
    android:id="@+id/actList"
    android:layout_width="328dp"
    android:layout_height="301dp"
    android:layout_marginBottom="16dp"
    android:layout_marginEnd="16dp"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:descendantFocusability="blocksDescendants"
    android:focusable="true" // change this
    android:clickable="true" // change this
    android:focusableInTouchMode="true" // change this
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/newExButton"
    app:layout_constraintVertical_bias="1.0">
<requestFocus/>
</ListView>
Mayur Raval
  • 3,250
  • 6
  • 34
  • 57
0

That's really strange... your code should have worked... I would suggest you to try implementing the in your activity to include lv.setClcickable(true) and lv.setEnable(true) :

 public class MenuActivity extends AppCompatActivity implements 
 AdapterView.OnItemClickListener{    
     ArrayList<Exercise> myExercises = new ArrayList<>();
     AlertDialog.Builder alertDialogBuilder;
     ArrayAdapter<Exercise> arrayAdapter;

     @Override
     protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_list);
           refreshList();
           Button newExButton = (Button) findViewById(R.id.newExButton);

           arrayAdapter = new ArrayAdapter<Exercise>(
                     this,
                     android.R.layout.simple_list_item_1,
                     myExercises );

           ListView lv = (ListView) findViewById(R.id.actList);
           lv.setClickable(true);
           lv.setEnabled(true);
           lv.setOnItemClickListener(new AdapterView.OnItemClickListener(){
        public void onItemClick(AdapterView<?> parent, View view , int 
           position, long id)
         {
                       startExercise(position);
         }
           lv.setAdapter(arrayAdapter);
     }

     public void refreshList(){
           setContentView(R.layout.activity_list);
           ListView lv = (ListView) findViewById(R.id.actList);

           lv.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
           lv.setAdapter(arrayAdapter);
     }

     public void startExercise(int selection){

         Intent exIntent = new Intent(this, CommenceExercise.class);
         Exercise chosenEx = myExercises.get(selection);
         Bundle info = new Bundle();
         info.putLong("duration", chosenEx.getTime());
         info.putString("name", chosenEx.getName());
         info.putString("description", chosenEx.getDescription());
         exIntent.putExtras(info);
         startActivity(exIntent);
   }     


}

or add these three lines to your xml

 android:focusable="false"
 android:focusableInTouchMode="false"
 android:clickable="true
 android:descendantFocusability="blocksDescendants"

If there are any focusable child views then the first click will always be for focus And I would Suggest You to use Custom ListView with Viewholder Pattern for efficiency or the Recyclerview of support Library this will make your scroll smooth and won't create extra View Objects... It will only create the View Object that's will fit the screen

Here is the Link for RecyclerView https://guides.codepath.com/android/using-the-recyclerview

Jai
  • 3,211
  • 2
  • 17
  • 26
0

Change your refreshList method to below one

public void refreshList(){
    arrayAdapter.notifyDataSetChanged();
}

What you're doing is, inflating a ListView again and setting new data to it rather than updating old one. And when you assign new value to ListView you forgot to set onClickListener.

It'll work.

ELITE
  • 5,815
  • 3
  • 19
  • 29
0

You need to remove below listview attributes from xml:

    android:descendantFocusability="blocksDescendants"
    android:focusable="true"
    android:clickable="true" 
    android:focusableInTouchMode="true"

Also, there is no need of refreshList() this is actually bad way of doing things, instead in your addNewActivity(), once your model is ready(probably on click of positive button) add that item to arrayAdapter and then do arrayAdapter.notifyDataSetChanged().

I hope this helps you!

  • Thank you! I actually ended up starting the whole activity again from scratch and got it to work, but this time I didn't add any of the above lines to the xml file. – tacitunum Jul 18 '17 at 06:52