2

I have a ListView in one of my activities that I have bound to an ArrayList using a custom ArrayAdapter. I have set an OnItemClickListener to the ListView which should call a method that starts another activity. However, I find that when I click on the ListView items, it only sometimes works. Sometimes it will start the activity as it should; other times it seems to detect the click (the ripple effect appears on the list item) but does nothing; other times it doesn't even appear to detect the click (the ripple effect doesn't appear).

I've tried all the usual suggestions that I've come across: blocking descendants on the parent view item, setting clickable and focusable to false on all the components of the item views, setting isEnabled to return true in the custom adapter, etc, but the behavior remains the same. Any help appreciated. Here is the relevant code:

Activity containing the ListView:

    public class ViewCollectionActivity extends AppCompatActivity {

    private final String className = this.getClass().getSimpleName();
    private CollectionHandler collectionHandler;
    private Context context;
    private ArrayList<Game> displayedCollection;
    private GameCollectionAdapter collectionAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_collection);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        context = this;

        collectionHandler = CollectionHandler.getInstance(this);

        TextView view = null;
        if (collectionHandler.getDisplayedCollection().size() > 0) {
            view = (TextView) findViewById(R.id.no_items_textview);
            view.setVisibility(View.GONE);
        }
        String currentDate = collectionHandler.getDateLastSynchronised();

        view = (TextView) findViewById(R.id.last_updated_textview);
        view.setText("Last synchronised: " + currentDate + "   Total games: " + String.valueOf(collectionHandler.getDisplayedCollection().size()));

        collectionAdapter = collectionHandler.getCollectionAdapter();
        ListView listView = (ListView) findViewById(R.id.collection_list_view);
        listView.setAdapter(collectionAdapter);
        AdapterView.OnItemClickListener collectionItemClickListener = new AdapterView.OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                launchGameDetailsActivity(position);
            }
        };
        listView.setOnItemClickListener(collectionItemClickListener);

    }

    public void launchGameDetailsActivity(int position){
        Log.d(className,"Starting lauchGameDetailsActivity method");
        collectionHandler.setSelectedGame(position);
        Intent intent = new Intent(this,ViewGameDetailsActivity.class);
        startActivity(intent);
        Log.d(className, "Ending lauchGameDetailsActivity method");
    }

The XML for the activity:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.bleachedlizard.ludome.viewcollection.ViewCollectionActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Synchronise Collection"
        android:onClick="synchroniseCollection"/>

    <TextView
        android:id="@+id/last_updated_textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Last synchronised: "
        android:textAlignment="center"
        />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Display Collection"
        android:visibility="gone"
        android:onClick="displayCollection"/>

    <ListView
        android:id="@+id/collection_list_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">


    </ListView>
    <TextView
        android:id="@+id/no_items_textview"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="You have no items in your collection."
        android:textAlignment="center"
        android:textSize="20sp"/>

</LinearLayout>

The XML for the item views:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/collection_item_layout"
    android:layout_width="match_parent"
    android:layout_height="75dp"
    android:orientation="horizontal"
    android:clickable="false"
    android:descendantFocusability="blocksDescendants"
    android:focusable="false"
    android:focusableInTouchMode="false">

    <ImageView
        android:id="@+id/collection_item_image"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:src="@drawable/testimage"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:clickable="false"
        />

    <TextView
        android:id="@+id/collection_item_name"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:padding="16dp"
        android:singleLine="false"
        android:textColor="@android:color/darker_gray"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:clickable="false"
        android:textIsSelectable="false"/>

    <TextView
        android:id="@+id/collection_item_plays"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:padding="8dp"
        android:textColor="@android:color/darker_gray"
        android:text="Plays: 0"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:clickable="false"
        android:textIsSelectable="false"/>

</LinearLayout>

The code for the custom adapter:

    public class GameCollectionAdapter extends ArrayAdapter<Game> {

    private ArrayList<Game> collection;

    public GameCollectionAdapter(Context context, int resource, ArrayList<Game> collection){
        super(context, resource, collection);

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LinearLayout gameView = (LinearLayout) convertView;
        LayoutInflater mInflater = LayoutInflater.from(getContext());

        if (gameView == null) {
            gameView = (LinearLayout) mInflater.inflate(R.layout.collection_item_view, null);

        }

        //Game game = collection.get(position);
        Game game = super.getItem(position);


        if (game != null) {

            // This is how you obtain a reference to the TextViews.
            // These TextViews are created in the XML files we defined.

            TextView gameTitle = (TextView) gameView.findViewById(R.id.collection_item_name);
            TextView numOfPlays = (TextView) gameView.findViewById(R.id.collection_item_plays);
            ImageView thumbnail = (ImageView) gameView.findViewById(R.id.collection_item_image);

            // check to see if each individual textview is null.
            // if not, assign some text!
            if (gameTitle != null){
                gameTitle.setText(game.getTitle());
            }
            if (numOfPlays != null){
                numOfPlays.setText("Plays: " + String.valueOf(game.getNumOfPlays()));
            }
            if (thumbnail != null){
                thumbnail.setImageBitmap(game.getThumbnail());
            }
        }

        // the view must be returned to our activity
        return gameView;
    }

    @Override
    public boolean isEnabled(int position) {
        return true;
    }

}
halfer
  • 19,824
  • 17
  • 99
  • 186
Chris J Davis
  • 101
  • 2
  • 6
  • Does it show you both the logs from `launchGameDetailsActivity` method? – Rohit5k2 Feb 27 '16 at 19:29
  • On the occasions when nothing happens, no - it shows neither log. – Chris J Davis Feb 27 '16 at 21:18
  • Can you try adding onClickListener directly to the view inflated in getView? – aelimill Feb 27 '16 at 21:55
  • Why are your list items set to not clickable or focusable? Won't that stop the click listener? – OneCricketeer Feb 27 '16 at 22:25
  • @aelimill - I'll try that and report back, though won't be at my computer again until Monday. – Chris J Davis Feb 28 '16 at 00:09
  • @cricket_007 - my understanding is that you have to disable clickable and focusable in all *child* views, otherwise the UI may only pick up clicks on those elements (to which there is no onClick listener set). – Chris J Davis Feb 28 '16 at 00:10
  • Are you trying to attach click listeners to items in the rows of the listview? If not, then you shouldn't need to disable the focus, clickablity, or the descendantFocus. I also found this,but not sure if it helps. http://stackoverflow.com/a/24156156/2308683 – OneCricketeer Feb 28 '16 at 00:15
  • @aelimill - I tried adding the click listener directly to the view, but I still couldn't get it to work. This is the code I added to my custom adapter:gameView.setOnClickListener(new View.OnClickListener() { Override public void onClick(View v) { int gameId = game.getGameID(); Intent intent = new Intent(context,ViewGameDetailsActivity.class); intent.putExtra("gameId",gameId); context.startActivity(intent); } }); – Chris J Davis Feb 29 '16 at 20:14
  • Urgh - didn't realise comments don't preserve formatting. Sorry about that. :/ – Chris J Davis Feb 29 '16 at 20:15
  • @Chris: you can format code "inline", either in comments or post bodies, using `backtick` characters. However, code in comments does tend to be frowned upon here, since it isn't very readable, and comments are sometimes deleted to reduce chat that might not be useful to readers in the future. – halfer Mar 05 '16 at 13:19
  • 1
    @halfer Thanks - I'll keep that in mind! – Chris J Davis Mar 05 '16 at 19:28

2 Answers2

1

I think the issue is due to the position of the item selection whenever you click you have an list position which is passed to your method launchGameDetailActivity(int position) check with log or toast on item click what all the position you are getting do the needful.

Here is my code try this like this if it helps.

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Toast.makeText(RecipeClass.this, "Position is" + position, Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(RecipeClass.this, RecipeIngredients.class)
            intent.putExtra("position", position);
            startActivity(intent);
        }

Check your arraylist value also whether they are not null.

halfer
  • 19,824
  • 17
  • 99
  • 186
Sayyaf
  • 316
  • 1
  • 4
  • 12
1

I discovered what was causing the problem: the way I had set up the array that backed the ListView meant that it was downloading and storing the Bitmaps for every element in the array all the time. Once I changed the implementation so that it only downloaded the images as the ListView required them, then that seemed to improve performance and the onClickListener started to work fine.

The implementation I used was the exact same one shown here:

http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

Chris J Davis
  • 101
  • 2
  • 6