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>
"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.