Search code examples
javaandroidlistviewandroid-cursoradapter

The wrong onclick listener is triggered


I have a list. In the list each item divided on two views. Each view got separate listener. The problem is that listener uses wrong id for intent. To inflate the list I got a data from cursor adapter. And in the logs I see that after clicking it all the time takes ID of the last element, not the id of the clicked element.

I need the intent send the user to the activity with the right ID

Code

public class ListCursorAdapter extends CursorAdapter {

    private static final String TAG = "myLogs";

    /**
     * Constructs a new {@link ListCursorAdapter}.
     *
     * @param context The context
     * @param c       The cursor from which to get the data.
     */
    public ListCursorAdapter(Context context, Cursor c) {
        super(context, c, 0 /* flags */);
    }

    /**
     * Makes a new blank list item view. No data is set (or bound) to the views yet.
     *
     * @param context app context
     * @param cursor  The cursor from which to get the data. The cursor is already
     *                moved to the correct position.
     * @param parent  The parent to which the new view is attached to
     * @return the newly created list item view.
     */
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        // Inflate a list item view using the layout specified in list_item.xml
        return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
    }

    /**
     * This method binds the pet data (in the current row pointed to by cursor) to the given
     * list item layout. For example, the name for the current pet can be set on the name TextView
     * in the list item layout.
     *
     * @param view    Existing view, returned earlier by newView() method
     * @param context app context
     * @param cursor  The cursor from which to get the data. The cursor is already moved to the
     *                correct row.
     */

    @Override
    public void bindView(View view, Context context, final Cursor cursor) {
        // Find individual views that we want to modify in the list item layout

        final TextView nameTextView = (TextView) view.findViewById(R.id.name);
        final TextView summaryTextView = (TextView) view.findViewById(R.id.summary);

        // Find the columns of pet attributes that we're interested in
        int nameColumnIndex = cursor.getColumnIndex(ListEntry.COLUMN_ITEM_NAME);
        int breedColumnIndex = cursor.getColumnIndex(ListEntry.COLUMN_ITEM_DESCRIPTION);

        // Read the pet attributes from the Cursor for the current pet
        String petName = cursor.getString(nameColumnIndex);
        String petBreed = cursor.getString(breedColumnIndex);

        // If the pet breed is empty string or null, then use some default text
        // that says "Unknown breed", so the TextView isn't blank.
        if (TextUtils.isEmpty(petBreed)) {
            petBreed = context.getString(R.string.unknown_description);
        }

        // Update the TextViews with the attributes for the current pet
        nameTextView.setText(petName);
        summaryTextView.setText(petBreed);


//
//        view.findViewById(R.id.editImageView).setOnClickListener(
//                new View.OnClickListener() {
//                    @Override
//                    public void onClick(View v) {
//                        Log.v(TAG, "--- WE ARE IN IMAGEVIEW LISTENER ---");
//
//                        Intent intent = new Intent(v.getContext(), EditorActivity.class);
//
//                        // Form the content URI that represents the specific pet that was clicked on,
//                        // by appending the "id" (passed as input to this method) onto the
//                        // {@link PetEntry#CONTENT_URI}.
//                        // For example, the URI would be "content://com.example.android.pets/pets/2"
//                        // if the pet with ID 2 was clicked on.
//                        Uri currentPetUri = ContentUris.withAppendedId(
//                                ListContract.ListEntry.CONTENT_URI,
//                                cursor.getInt(cursor.getColumnIndex(ListEntry._ID))
//                        );
//
//
//                        Log.v(TAG, "--- CONTENT URI " + cursor.getInt(cursor.getColumnIndex(ListEntry._ID)));
//
//                        // Set the URI on the data field of the intent
//                        intent.setData(currentPetUri);
//
//                        // Launch the {@link EditorActivity} to display the data for the current pet.
//                        v.getContext().startActivity(intent);
//                    }
//                }
//        );
//
//        view.findViewById(R.id.leftSide).setOnClickListener(
//                new View.OnClickListener() {
//                    @Override
//                    public void onClick(View v) {
//                        Log.v(TAG, "--- WE ARE IN LEFTSIDE LISTENER ---");
//
//                        nameTextView.setPaintFlags(nameTextView.getPaintFlags()| Paint.STRIKE_THRU_TEXT_FLAG);
//                        summaryTextView.setPaintFlags(summaryTextView.getPaintFlags()| Paint.STRIKE_THRU_TEXT_FLAG);
//
//                    }
//                }
//        );

        Boolean completed = cursor.getInt(cursor.getColumnIndex(ListEntry.COLUMN_ITEM_COMPLETED)) == 1;
        if (completed) {
            setCompleted(view);
        }
    }
    //BaseAdapter -> getView;
    public void setCompleted(View view) {

    }



}

And main activity

        public class CatalogActivity extends AppCompatActivity implements
                LoaderManager.LoaderCallbacks<Cursor> {

            private static final String TAG = "myLogs";

            /** Identifier for the pet data loader */
            private static final int LIST_LOADER = 0;

            /** Adapter for the ListView */
            ListCursorAdapter mCursorAdapter;


            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_catalog);
                // Changing font



//                typefaceName = Typeface.createFromAsset(getAssets(), "Roboto-Regular.ttf");
//                typefaceDescription = Typeface.createFromAsset(getAssets(), "OpenSans-Italic.ttf");
//
//                Typeface titleTypeface = Typeface.createFromAsset(getAssets(), "Roboto-Regular.ttf");
//                Typeface descriptionTypeface = Typeface.createFromAsset(getAssets(), "OpenSans-Italic.ttf");
//                TextView titleTextView = (TextView) findViewById(R.id.name);
//                TextView descriptionTextView = (TextView) findViewById(R.id.summary);
//                Log.v(TAG, "--- FONT IS ---" + titleTypeface );
//                if (titleTextView == null){
//                    Log.v(TAG, "*** TEXTVIEW IS EMPTY ***");
//                }
//                titleTextView.setTypeface(titleTypeface);
//                descriptionTextView.setTypeface(descriptionTypeface);

                Log.v(TAG, "--- WE ARE IN CATALOG ACTIVITY ---");

                // Setup FAB to open EditorActivity
                FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
                fab.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Intent intent = new Intent(CatalogActivity.this, EditorActivity.class);
                        startActivity(intent);
                    }
                });



                // Find the ListView which will be populated with the list data
                ListView listListView = (ListView) findViewById(R.id.list);


                // Find and set empty view on the ListView, so that it only shows when the list has 0 items.
                View emptyView = findViewById(R.id.empty_view);
                listListView.setEmptyView(emptyView);

                // Setup an Adapter to create a list item for each row of list data in the Cursor.
                // There is no items data yet (until the loader finishes) so pass in null for the Cursor.
                mCursorAdapter = new ListCursorAdapter(this, null);
                listListView.setAdapter(mCursorAdapter);

                // Setup the item click listener
                listListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                        ShoppingListBdHelper helper = new ShoppingListBdHelper(view.getContext());
                        if (helper.setCompleted(id)) {
                            mCursorAdapter.setCompleted(view);
                        }

                        if ( view.findViewById(R.id.editImageView).isSelected()){
                            Log.v(TAG, "++++++++ IF WORKS");
                        } else if (view.findViewById(R.id.leftSide).isSelected()){
                            Log.v(TAG, "+++++++ ELSE IF WORKS");
                        }
                    }
                });

                // Kick off the loader
                getSupportLoaderManager().initLoader(LIST_LOADER, null, this);
            }

            @Override
            public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu options from the res/menu/menu_catalog.xml file.
                // This adds menu items to the app bar.
                getMenuInflater().inflate(R.menu.menu_catalog, menu);
                return true;
            }

            @Override
            public boolean onOptionsItemSelected(MenuItem item) {
                // User clicked on a menu option in the app bar overflow menu
                switch (item.getItemId()) {
                    // Respond to a click on the "Insert dummy data" menu option
                    case R.id.action_share_button:
                        shareButton(mCursorAdapter.getCursor());
                        return true;
                    // Respond to a click on the "Delete all entries" menu option
                    case R.id.action_delete_all_entries:
                        deleteAllItems();
                        return true;
                }
                return super.onOptionsItemSelected(item);
            }

            /**
             * Share button
             */
            private void shareButton(Cursor cursor) {

                Log.v(TAG, "--- WE ARE IN SHARE BUTTON METHOD ---");

                List<String> test;
                test = new ArrayList<String>();
                cursor.moveToFirst();

                while(!cursor.isAfterLast()) {
                    Log.d(TAG, "field: " + cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_NAME)));

                    test.add(cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_NAME)) + " - " + cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_DESCRIPTION))); //add the item
    //                test.add(cursor.getString(cursor.getColumnIndex(ListContract.ListEntry.COLUMN_ITEM_DESCRIPTION))); //add the item
                    cursor.moveToNext();
                }

                cursor.moveToFirst();
                cursor.close();

    //            for (String comma : )

                Log.v(TAG, "--- OUR LIST INCLUDES: " + test.toString());

                Intent myIntent = new Intent();
                myIntent.setAction(Intent.ACTION_SEND);
                myIntent.putStringArrayListExtra("test", (ArrayList<String>) test);
                myIntent.putExtra(android.content.Intent.EXTRA_TEXT, test.toString());

                Log.v(TAG, "--- INTENT EXTRAS ARE: " + myIntent.getExtras());

                myIntent.setType("text/plain");
                startActivity(Intent.createChooser(myIntent, "Share using"));
            }


            /**
             * Helper method to delete all list in the database.
             */
            private void deleteAllItems() {

                Log.v(TAG, "Сработал метод удаления всех данных");
                long rowsDeleted = getContentResolver().delete(ListContract.ListEntry.CONTENT_URI, null, null);
                Log.v("CatalogActivity", rowsDeleted + " rows deleted from list database");
            }

            @Override
            public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
                Log.v(TAG, "Начал работать loader cursor");
                // Define a projection that specifies the columns from the table we care about.
                String[] projection = {
                        ListContract.ListEntry._ID,
                        ListContract.ListEntry.COLUMN_ITEM_NAME,
                        ListContract.ListEntry.COLUMN_ITEM_DESCRIPTION,
                        ListContract.ListEntry.COLUMN_ITEM_COMPLETED
                };

                // This loader will execute the ContentProvider's query method on a background thread
                return new CursorLoader(this,   // Parent activity context
                        ListContract.ListEntry.CONTENT_URI,   // Provider content URI to query
                        projection,             // Columns to include in the resulting Cursor
                        null,                   // No selection clause
                        null,                   // No selection arguments
                        null);                  // Default sort order

            }

            @Override
            public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
                // Update {@link ListCursorAdapter} with this new cursor containing updated pet data
                mCursorAdapter.swapCursor(data);
                Log.v(TAG, "Cursor adapter загрузился");
            }

            @Override
            public void onLoaderReset(Loader<Cursor> loader) {
                // Callback called when the data needs to be deleted
                mCursorAdapter.swapCursor(null);
            }


        }

XML

<RelativeLayout
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"
tools:context=".CatalogActivity">

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/list"
/>

<!-- Empty view for the list -->
<RelativeLayout
    android:id="@+id/empty_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true">

    <ImageView
        android:id="@+id/empty_shelter_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:src="@drawable/ic_empty_shelter"/>

    <TextView
        android:id="@+id/empty_title_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/empty_shelter_image"
        android:layout_centerHorizontal="true"
        android:fontFamily="sans-serif-medium"
        android:paddingTop="16dp"
        android:text="@string/empty_view_title_text"
        android:textAppearance="?android:textAppearanceMedium"/>

    <TextView
        android:id="@+id/empty_subtitle_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/empty_title_text"
        android:layout_centerHorizontal="true"
        android:fontFamily="sans-serif"
        android:paddingTop="8dp"
        android:text="@string/empty_view_subtitle_text"
        android:textAppearance="?android:textAppearanceSmall"
        android:textColor="#A2AAB0"/>
</RelativeLayout>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:layout_margin="@dimen/fab_margin"
    android:src="@drawable/ic_add_pet"/>

XML of item

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="@dimen/activity_margin">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/leftSide">


    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:fontFamily="sans-serif-medium"
        android:textAppearance="?android:textAppearanceMedium"
        android:textColor="#2B3D4D"
        android:layout_alignParentLeft="true" />

    <TextView
        android:id="@+id/summary"
        android:layout_below="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif"
        android:textAppearance="?android:textAppearanceSmall"
        android:textColor="#AEB6BD"  />
    </LinearLayout>

    <ImageView
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_margin="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif"
        android:id="@+id/editImageView"
        android:textAppearance="?android:textAppearanceSmall"
        android:src="@drawable/ic_edit"
        />
</RelativeLayout>

Solution

  • "Always the last ID" ... please show your xml of the list elements. This sounds to me as if your views overlap and by xml rules they stack on each other.

    So if your "last ID" is written below in the XML and it overlaps with the left view, it's clear, that always this view will receive the click and trigger its listener.

    UPDATE

    Thanks for posting the xml - It is exactly as i thought, your LinearLayout overlaps with the ImageView.

    Change your LinearLayout as follows:

        <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/editImageView"
        android:orientation="vertical"
        android:id="@+id/leftSide">
    

    Add toLeftOf to avoid overlap and make the height wrap_content. Then everything should work.