Dynamically Changing Toolbar Item Visibility in on RecyclerView Click (Without the LongClick) - java

I have an app (based on this tutorial), and it has an activity that allows user to choose several friends to send messages to. Now, I also have the check icon in the upper right corner. When the user clicks on it, selected contacts are sent to parent activity. When the user clicks on a contact in recyclerview, contact's status changes from unselected to selected and vice versa.
Most tutorials and stack overflow answers suggest changing the toolbar on long click, but what I want to do is change it on recyclerview item click, ie. when the user clicks on recyclerview item I want to show the check button if the number of selected users is not 0 (selectedContacts != null), and hide the button if it is 0. I would also like to show hide it when the user starts the activity, based on the same condition. As I said, I have looked at a lot of SO answers, but I couldn't find any that worked for me. Some of the answers I tried: this, this, this, this, this, this...
This is what it looks like:
activity_choose_contacts_action.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/add"
android:icon="#drawable/ic_icon_check_white"
android:title="#string/add"
app:showAsAction="always" />
</menu>
choose_contacts.xml:
<LinearLayout 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:orientation="vertical"
tools:context=".contactprofile.ChooseContactsActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/chooseContactsToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/ppdColorOrange"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ToolbarWhiteBackArrow">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/selectContactTextView"
style="#style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/select_contacts"
android:textColor="#color/white" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:id="#+id/contacts_list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:divider="#color/list_divider"
android:dividerHeight="1dp"
app:srcCompat="#drawable/ic_icon_user" />
</LinearLayout>
ChooseContactsActivity.java:
adapter = new ChooseContactsAdapter(contactList, getApplicationContext());
recyclerView.setAdapter(adapter);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new ChooseContactsActivity.ClickListener() {
#Override
public void onClick(View view, int position) {
if (selectedContacts != null) {
addContacts.setImageResource(R.drawable.ic_icon_check_white);
} else {
addContacts.setVisibility(View.GONE);
}
}
#Override
public void onLongClick(View view, int position) {
}
}));
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new ChooseContactsActivity.ClickListener() {
#Override
public void onClick(View view, int position) {
}
#Override
public void onLongClick(View view, int position) {
}
}));
........
Call<ContactsResponse> call = apiService.getMyContact(userId);
call.enqueue(new Callback<ContactsResponse>() {
#Override
public void onResponse(Call<ContactsResponse> call, retrofit2.Response<ContactsResponse> response) {
List<Contact> contact = response.body().getResults();
contactList.addAll(contact);
adapter.notifyDataSetChanged();
RecyclerView recyclerView = findViewById(R.id.contacts_list);
// Checking previously selected contacts
if (selectedContacts != null) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
List<Integer> selectedIndexes = new ArrayList<>();
// Finding indexes of selected contact ids
for (int i = 0; i < contactList.size(); i++) {
if (selectedContacts.contains(contactList.get(i).getUserId())) {
selectedIndexes.add(i);
}
}
// Triggering click on each selected item
for (int j = 0; j < selectedIndexes.size(); j++) {
recyclerView.getChildAt(selectedIndexes.get(j)).performClick();
}
}, 500);
}
}
........
interface ClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
private static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ChooseContactsActivity.ClickListener clickListener;
RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ChooseContactsActivity.ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildLayoutPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildLayoutPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_choose_contacts_action, menu);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
getSupportActionBar().setDisplayShowHomeEnabled(true);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.add:
ArrayList<String> selectedIds = adapter.selectedIds;
String text = "abc";
Intent intent = new Intent();
intent.putStringArrayListExtra("contacts_added", selectedIds);
setResult(RESULT_OK, intent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
ContactsAdapter.java:
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// toggle selection
toggleSelection(position);
// Change background color of the selected items in list view
holder.itemView.setBackgroundColor(selectedItems.get(position) ? context.getResources().getColor(R.color.ppdColorOrangeSelection) : Color.TRANSPARENT);
if (position != RecyclerView.NO_POSITION) {
Contact contact = contactList.get(position);
applyIconAnimation(holder, position);
String userId = contact.getUserId();
if (!selectedIds.contains(userId)) {
selectedIds.add(userId);
} else {
selectedIds.remove(userId);
}
}
applyIconAnimation(holder, position);
getSelectedItemCount();
getSelectedItems();
resetAnimationIndex();
getSelectedItemCount();
}
});
}
#Override
public int getItemViewType(int position) {
return position;
}
private void applyProfilePicture(ChooseContactsViewHolder holder, Contact contact) {
Picasso.with(context)
.load(AppConfig.URL_PROFILE_PHOTO + contact.getThumbnailUrl())
.placeholder(textDrawable)
.error(textDrawable)
.transform(new CircleTransform())
.into(holder.thumbNail);
}
private void applyIconAnimation(ChooseContactsViewHolder holder, int position) {
if (selectedItems.get(position, false)) {
holder.iconFront.setVisibility(View.GONE);
resetIconYAxis(holder.iconBack);
holder.iconBack.setVisibility(View.VISIBLE);
holder.iconBack.setAlpha(1);
if (currentSelectedIndex == position) {
FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, true);
resetCurrentIndex();
}
} else {
holder.iconBack.setVisibility(View.GONE);
resetIconYAxis(holder.iconFront);
holder.iconFront.setVisibility(View.VISIBLE);
holder.iconFront.setAlpha(1);
if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, false);
resetCurrentIndex();
}
}
}
private void toggleSelection(int pos) {
currentSelectedIndex = pos;
if (selectedItems.get(pos, false)) {
selectedItems.delete(pos);
animationItemsIndex.delete(pos);
} else {
selectedItems.put(pos, true);
animationItemsIndex.put(pos, true);
}
//notifyItemChanged(pos);
}
private void clearSelections() {
reverseAllAnimations = true;
selectedItems.clear();
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return contactList.size();
}
private int getSelectedItemCount() {
return selectedItems.size();
}
private List<Integer> getSelectedItems() {
List<Integer> items =
new ArrayList<>(selectedItems.size());
for (int i = 0; i < selectedItems.size(); i++) {
items.add(selectedItems.keyAt(i));
}
return items;
}

Here to simplify the approach I use CheckBox as the RecyclerView item and hide it's button. And After that it'll act like a TextView but also having a check change property. Then I set OnCheckedChangeListener to that CheckBox. I increase an integer counter on every true onCheckedChanged result and also decrease on false. And then through an Interface I pass that counter's value back to the base activity. And there check if the counter is greater than 0 or not and that would set the visibility of the item. Below is the reference code for the task.
Interface
public interface ShareValue {
void getValue(int count);
}
onCheckedChanged
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean
isChecked) {
count = isChecked ? count++ : count--;
shareValue.getValue(count);
}
onCreateOptionsMenu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
item = menu.getItem(0);
item.setVisible(false);
return true;
}
#Override
public void getValue(int count) {
item.setVisible(count > 0);
}
}

So I found a solution. I added this:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_choose_contacts_action, menu);
if (adapter.getSelectedItemCount() == 0) {
menu.findItem(R.id.add).setVisible(false);
} else {
menu.findItem(R.id.add).setVisible(true);
}
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
getSupportActionBar().setDisplayShowHomeEnabled(true);
return true;
}
.....
// Checking previously selected contacts
if (selectedContacts != null) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
List<Integer> selectedIndexes = new ArrayList<>();
// Finding indexes of selected contact ids
for (int i = 0; i < contactList.size(); i++) {
if (selectedContacts.contains(contactList.get(i).getUserId())) {
selectedIndexes.add(i);
}
}
// Triggering click on each selected item
for (int j = 0; j < selectedIndexes.size(); j++) {
recyclerView.getChildAt(selectedIndexes.get(j)).performClick();
}
invalidateOptionsMenu();
}, 500);
......
#Override
public void onClick(View view, int position) {
// invalidateOptionsMenu(); (resetting onCreateOptionsMenu) executed with 600 millis delay, otherwise it will happen before the 500 millis
// delay when checking previously selected contacts
new Handler(Looper.getMainLooper()).postDelayed(() -> invalidateOptionsMenu(), 600);
}

Related

Check a list view item from adapter when long clicked

I have a listview for a note application set with my adapter. The list view component consists of some textviewsand a checkbox which pops up delete icon when a listviewitem is long clicked.
Am automatically making the checkboxes visible from the adapter when the delete icon becomes visible so that the user could select the items he wants to delete.
The problem is i want a single list item to be automatically checked when long clicked. How do i go about this? My logic does not work.
listcomponent.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_marginTop="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:background="#F5F5F5"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/verticallineview"
android:layout_width="4dp"
android:layout_height="match_parent"
android:background="#color/toast_color"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/list_note_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:padding="1dp"
android:textStyle="bold"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/light_black" />
<TextView
android:id="#+id/list_note_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="1dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/colorPrimary"
android:text=""
/>
<TextView
android:id="#+id/list_note_content_preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="1dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text=""
android:textColor="#color/light_black"
/>
</LinearLayout>
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:layout_marginEnd="5dp"
android:theme="#style/checkBoxStyle"
android:visibility="gone"
android:gravity="center"
android:layout_gravity="center"
android:layout_marginRight="5dp" />
</LinearLayout>
</LinearLayout>
Adapter
class NoteListAdapter extends ArrayAdapter<Note>{
private List<Note> objects;
private List<Note> originalList = new ArrayList<>();
boolean isLongPressed;
// boolean isChecked;
boolean[] isChecked;
private boolean isItemsChecked;
NoteListAdapter(Context context, int resource, List<Note> objects) {
super(context, resource, objects);
this.objects = objects;
this.originalList.addAll(objects);
isLongPressed = false;
// isChecked = false;
isChecked = new boolean[objects.size()];
for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
}
#Override
public int getCount() {
return objects.size();
}
#Nullable
#Override
public Note getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_component, parent, false);
}
Note note = getItem(position);
if (note != null) {
TextView title = convertView.findViewById(R.id.list_note_title);
TextView content = convertView.findViewById(R.id.list_note_content_preview);
TextView date = convertView.findViewById(R.id.list_note_date);
// setting checkbox logic on the adapter
CheckBox checkBox = convertView.findViewById(R.id.checkbox);
// now i wanna toggle checked items from a checkbox on my header
if (isItemsChecked) {
checkBox.setChecked(true);
} else {
checkBox.setChecked(false);
}
if (isLongPressed) {
checkBox.setVisibility(View.VISIBLE);
} else {
checkBox.setVisibility(View.GONE);
}
// also handle checks for all list view items
checkBox.setChecked(isChecked[position]);
checkBox.setTag(position);
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
int checkedPosition = (int)cb.getTag();
isChecked[checkedPosition] = cb.isChecked();
notifyDataSetChanged();
}
});
}
return convertView;
}
void showCheckbox(int clickedPosition) {
isLongPressed = true;
for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
isChecked[clickedPosition] = true;
notifyDataSetChanged(); // Required for update
}
void removeCheckbox() {
isLongPressed = false;
notifyDataSetChanged(); // Required for update
}
void Check() {
isItemsChecked = true;
notifyDataSetChanged(); // Required for update
}
void Uncheck() {
isItemsChecked = false;
notifyDataSetChanged(); // Required for update
}
NoteActivity.java
private void listViewLongClick() {
mListNotes.setLongClickable(true);
mListNotes.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// universal button controls all checked items
Checkbox universalCheckBox = findViewById(R.id.check_all);
universalCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
na.Check();
} else {
na.Uncheck();
}
}
});
mDeleteButton = findViewById(R.id.delete_icon);
na.showCheckbox();
deleteButtonIn();
return true;
}
});
}
The problem here is you have set the visibility of the checkBox from only one holder. Your logic is right but you haven't changed the visibility of checkBoxes from all the holders. You have to create a arrayList for holders and initialize them with null items.
private ArrayList<View> collectionOfViews = new ArrayList<>();
for (int i = 0; i < objects.size(); i++) {
collectionOfViews.add(null);
}
This is my getView() from the adapter. Also to store checkStatus from all the boxes add a element checkStatus in your Note object.
if (note != null) {
final TextView textView = convertView.findViewById(R.id.textView);
final CheckBox checkBox = convertView.findViewById(R.id.checkBox);
checkBox.setChecked(note.getCheckStatus());
textView.setText(note.getTextView());
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (checkBox.getVisibility() != View.GONE) {
note.changeCheckStatus();
checkBox.setChecked(note.getCheckStatus());
}
}
});
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
note.changeCheckStatus();
checkBox.setChecked(note.getCheckStatus());
}
});
//setting holder in your array
collectionOfViews.set(position, convertView);
convertView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
note.changeCheckStatus();
checkBox.setChecked(note.getCheckStatus());
return true;
}
});
checkBoxStatus();
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checkBoxStatus();
}
});
}
The visibility of the checkBox is handled from checkBoxStatus()
void checkBoxStatus(){
int count = 0;
for (Note noteCheck : mData) {
if (!noteCheck.getCheckStatus()) {
count++;
}
}
if (count == mData.size()) {
for (View view : collectionOfViews) {
if (view != null) {
CheckBox checkBoxInside = view.findViewById(R.id.checkBox);
checkBoxInside.setVisibility(View.GONE);
}
}
}else{
for (View view : collectionOfViews) {
if (view != null) {
CheckBox checkBoxInside = view.findViewById(R.id.checkBox);
checkBoxInside.setVisibility(View.VISIBLE);
}
}
}
notifyDataSetChanged();
}
Read this article this may help you. I got this idea of storing views in array from here.
I hope this helps.
Try the code below:
Adapter:
class NoteListAdapter extends ArrayAdapter<Note>{
private List<Note> objects;
private List<Note> originalList = new ArrayList<>();
boolean isLongPressed;
// boolean isChecked;
boolean[] isChecked;
NoteListAdapter(Context context, int resource, List<Note> objects) {
super(context, resource, objects);
this.objects = objects;
this.originalList.addAll(objects);
isLongPressed = false;
// isChecked = false;
isChecked = new boolean[objects.size()];
for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
}
#Override
public int getCount() {
return objects.size();
}
#Nullable
#Override
public Note getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_component, parent, false);
}
Note note = getItem(position);
if (note != null) {
TextView title = convertView.findViewById(R.id.list_note_title);
TextView content = convertView.findViewById(R.id.list_note_content_preview);
TextView date = convertView.findViewById(R.id.list_note_date);
// setting checkbox logic on the adapter
CheckBox checkBox = convertView.findViewById(R.id.checkbox);
// now i wanna toggle checked items from a checkbox on my header
// if (isItemsChecked) {
// checkBox.setChecked(true);
// } else {
// checkBox.setChecked(false);
// }
if (isLongPressed) {
checkBox.setVisibility(View.VISIBLE);
} else {
checkBox.setVisibility(View.GONE);
}
// also handle checks for all list view items
checkBox.setChecked(isChecked[position]);
checkBox.setTag(position);
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
int checkedPosition = (int)cb.getTag();
isChecked[checkedPosition] = cb.isChecked();
notifyDataSetChanged();
}
});
}
return convertView;
}
void showCheckbox(int clickedPosition) {
isLongPressed = true;
for(int i=0; i<isChecked.length; i++) isChecked[i] = false;
isChecked[clickedPosition] = true;
notifyDataSetChanged(); // Required for update
}
void removeCheckbox() {
isLongPressed = false;
notifyDataSetChanged(); // Required for update
}
void checkboxAllChange(boolean state) {
isLongPressed = true;
for(int i=0; i<isChecked.length; i++) isChecked[i] = state;
notifyDataSetChanged(); // Required for update
}
// void Check() {
// isChecked = true;
// notifyDataSetChanged(); // Required for update
// }
// void Uncheck() {
// isChecked = false;
// notifyDataSetChanged(); // Required for update
// }
}
In Activity:
mListNotes.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
deleteButtonIn();
na.showCheckBox(position);
return true;
}
});
Checkbox universalCheckBox = findViewById(R.id.check_all);
universalCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
na.checkboxAllChange(buttonView.isChecked());
}
});

Can't Open Context Menu on Click of Menu Button in Android

I have a problem with the contextual menu, I have to control "MenuButton" without using of "Contextual Action bar menu (CAB)" when you make a long click and short click displays a context menu.I need to display the contextual menu with using of "Contextual Action bar menu (CAB)".when you make short click on "MenuButton" CAB menu also called on a short click, not a long click. I need to display the contextual menu with a short click. is this possible?
MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_internal);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
title = (TextView) findViewById(R.id.txt_name_file);
past = (ImageView) findViewById(R.id.img_paste);
home = (ImageView) findViewById(R.id.img_home);
menu_item = (ImageView) findViewById(R.id.img_more);
list_in = (ListView) findViewById(R.id.list_in);
past.setVisibility(View.INVISIBLE);
fileManager = new FileManager();
arrayList = new ArrayList<>();
adapter = new InternalAdapter(getApplicationContext(), arrayList);
list_in.setAdapter(adapter);
list_in.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int i, long id) {
if (selectCount > 0) {
if (actionMode == null) {
actionMode = InternalActivity.this.startActionMode(callback);
Toast.makeText(getApplicationContext(), "S>0", Toast.LENGTH_SHORT).show();
}
toggleselection(i);
actionMode.setTitle(selectCount + " " + "Selected");
if (selectCount == 0) {
actionMode.finish();
}
} else if (selectCount == 0) {
Toast.makeText(getApplicationContext(), "2", Toast.LENGTH_SHORT).show();
String S = arrayList.get(i).getPathFile();
File file = new File(S);
if (arrayList.get(i).isFile() == false) {
pathItem = arrayList.get(i).getPathFile();
title.setText(pathItem.substring(pathItem.lastIndexOf("/") + 1));
readFile(pathItem);
} else if (file.canRead()) {
Intent intent = FileManager.createIntent(file);
if (getPackageManager().queryIntentActivities(intent, 0).size() > 0) {
startActivity(intent);
} else {
Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
}
}
}
}
});
list_in.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (actionMode == null) {
actionMode = InternalActivity.this.startActionMode(callback);
Toast.makeText(getApplicationContext(), "L", Toast.LENGTH_SHORT).show();
}
toggleselection(position);
actionMode.setTitle(selectCount + " " + "Selected");
if (selectCount == 0) {
actionMode.finish();
}
return true;
}
});
readFile(FileManager.PATH);
loadFileItem();
}
ArrayList<FileItem> selectedFile = new ArrayList<>();
private void toggleselection(int position) {
arrayList.get(position).isSelected = !arrayList.get(position).isSelected;
if (arrayList.get(position).isSelected) {
selectedFile.add(arrayList.get(position));
selectCount++;
} else {
selectedFile.add(arrayList.get(position));
selectCount--;
}
adapter.notifyDataSetChanged();
}
private ActionMode.Callback callback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater menuInflater = mode.getMenuInflater();
menuInflater.inflate(R.menu.internal_context_menu, menu);
MenuItem mi = menu.getItem(0);
mi.setTitle(mi.getTitle().toString());
actionMode = mode;
selectCount = 0;
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.i_de:
mode.finish();
break;
}
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
if (selectCount > 0) {
deSelect();
}
actionMode = null;
}
};
private void deSelect() {
for (int i = 0; i < arrayList.size(); i++) {
arrayList.get(i).isSelected = false;
}
selectCount = 0;
adapter.notifyDataSetChanged();
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.select_file, menu);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.copy:
copyFolder(pos);
break;
case R.id.delete:
deleteFolder(pos);
break;
case R.id.rename:
renameFile(pos);
break;
}
return super.onContextItemSelected(item);
}
public class InternalAdapter extends BaseAdapter {
ArrayList<FileItem> arrayList;
Context context;
ViewHolder viewHolder;
public InternalAdapter(Context context, ArrayList<FileItem> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public FileItem getItem(int position) {
return arrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(context).inflate(R.layout.activity_internal_adapter, parent, false);
viewHolder.imgFolder = (ImageView) view.findViewById(R.id.img_folder);
viewHolder.txtNameFile = (TextView) view.findViewById(R.id.txt_name_folder);
viewHolder.txtDate = (TextView) view.findViewById(R.id.txt_date);
viewHolder.imgCreate = (ImageView) view.findViewById(R.id.img_create);
viewHolder.view = view.findViewById(R.id.view_internal);
viewHolder.linearLayout = (LinearLayout) view.findViewById(R.id.lv_image);
FileItem fileItem = getItem(position);
if (fileItem.isSelected) {
viewHolder.view.setAlpha(0.5f);
} else {
viewHolder.view.setAlpha(0.0f);
}
if (fileItem.isDirectory()) {
viewHolder.imgFolder.setImageResource(R.drawable.ic_folder_black_24dp);
} else if (fileItem.isFile()) {
viewHolder.imgFolder.setImageResource(R.drawable.ic_insert_drive_file_black_24dp);
}
viewHolder.txtNameFile.setText(fileItem.getName());
viewHolder.txtDate.setText(fileItem.getDate());
viewHolder.imgCreate.setLongClickable(false);
registerForContextMenu(viewHolder.imgCreate);
viewHolder.imgCreate.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
unregisterForContextMenu(v);
Toast.makeText(getApplicationContext(), "111", Toast.LENGTH_SHORT).show();
return false;
}
});
viewHolder.imgCreate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pos = position;
openContextMenu(v);
Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_SHORT).show();
}
});
return view;
}
private class ViewHolder {
ImageView imgFolder;
TextView txtNameFile;
TextView txtDate;
ImageView imgCreate;
View view;
LinearLayout linearLayout;
}
}
}

ItemView may not be null

I'm trying to retrieve all the checkboxes from my RecyclerView in order to uncheck them. However, this error is shown. Below are the classes that LogCat points to.
java.lang.IllegalArgumentException: itemView may not be null
at android.support.v7.widget.RecyclerView$ViewHolder.<init>(RecyclerView.java:10314)
at br.com.ufrn.marceloaugusto.tasklist.adapter.ProdutoAdapter$ProdutosViewHolder.<init>(ProdutoAdapter.java:0)
at br.com.ufrn.marceloaugusto.tasklist.MainActivity.onOptionsItemSelected(MainActivity.java:93)
MainActivity.java
public class MainActivity extends BaseActivity {
//private SQLiteDatabase banco;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpToolbar();
if (savedInstanceState == null) {
FragmentProdutos frag = new FragmentProdutos();
getSupportFragmentManager().beginTransaction().add(R.id.container, frag).commit();
}
//FAB
findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
snack(view, "Adicionar produto");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_desmarkAll) {
RecyclerView recycler = (RecyclerView) findViewById(R.id.recyclerView);
ProdutoAdapter.ProdutosViewHolder holder = null;
int id = 0;
for (int i = 0; i < recycler.getAdapter().getItemCount(); i++) {
holder = new ProdutoAdapter.ProdutosViewHolder(recycler.getChildAt(i)); **//Line 93**
if (holder.checkBox.isChecked()) {
holder.checkBox.setChecked(false);
}
}
return true;
}
return super.onOptionsItemSelected(item);
}}
ProdutoAdapter.java
public class ProdutoAdapter extends RecyclerView.Adapter<ProdutoAdapter.ProdutosViewHolder> {
private final Context context;
private final List<Produto> produtos;
//Interface para expor os eventos de toque na lista
private ProdutoOnClickListener produtoOnClickListener;
private ProdutoOnCheckListener produtoOnCheckListener;
public ProdutoAdapter(Context context, List<Produto> produtos, ProdutoOnClickListener produtoOnClickListener, ProdutoOnCheckListener produtoOnCheckListener) {
this.context = context;
this.produtos = produtos;
this.produtoOnClickListener = produtoOnClickListener;
this.produtoOnCheckListener = produtoOnCheckListener;
}
#Override
public int getItemCount() {
return this.produtos != null ? this.produtos.size() : 0;
}
#Override
public ProdutosViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.adapter_produto, parent, false);
ProdutosViewHolder holder = new ProdutosViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(final ProdutosViewHolder holder, final int position) {
Produto p = produtos.get(position);
holder.tNome.setText(p.getNome());
//holder.tPreco.setText(String.valueOf(p.getPreco()));
if (produtoOnClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
produtoOnClickListener.onClickProduto(view, position);
}
});
}
if (produtoOnCheckListener != null) {
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
produtoOnCheckListener.onCheckProduto(view, position);
}
});
}
}
public interface ProdutoOnClickListener {
public void onClickProduto(View view, int idx);
}
public interface ProdutoOnCheckListener {
public void onCheckProduto(View view, int position);
}
public static class ProdutosViewHolder extends RecyclerView.ViewHolder {
public TextView tNome;
//public TextView tPreco;
CardView cardView;
public CheckBox checkBox;
public ProdutosViewHolder(View view) {
super(view);
tNome = (TextView) view.findViewById(R.id.nomeProduto);
//tPreco = (TextView) view.findViewById(R.id.precoProduto);
cardView = (CardView) view.findViewById(R.id.card_view);
checkBox = (CheckBox) view.findViewById(R.id.checkProduto);
}
}
}
Method getChildAt is method of ViewGroup, so recycler.getChildAt(i) will be null for you. In your case you should use produtos list, iterate over it and set its field associated to "checked" state to "false", invoke notifyDataSetChanged() method of your adapter and then onBindViewHolder() will automatically change holder's checkBox values.
So instead of
for (int i = 0; i < recycler.getAdapter().getItemCount(); i++) {
holder = new ProdutoAdapter.ProdutosViewHolder(recycler.getChildAt(i)); **//Line 93**
if (holder.checkBox.isChecked()) {
holder.checkBox.setChecked(false);
}
}
use this one:
for (Product product : produtos){
product.setChecked(false);
}
recycler.getAdapter().notifyDataSetChanged();
I supppose your class Project has such method.
In a RecyclerView the item views are recycled so you dont have as many itemviews as item in your List. Instead those itemviews are recycled and shows differents elements of your productos List.
Your problem is that you are in a for loop with the length of the List but inside you are using that index to access itemviews wich has not that much elements.
Instead, you should define a variable in Producto.class and update every time that check/uncheck the CheckBox of the item. And set this variable to false when you want to uncheck all and call
adapter.notifyDataSetChanged();
UPDATE:
ProdutoAdapter.java
Define a method to access list produtos and update onBindViewHolder like this:
if (produtoOnCheckListener != null) {
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
produtos.get(position).setCheckBoxState(b);
produtoOnCheckListener.onCheckProduto(view, position);
}
});
}
MainActivity.class Define a ProductoAdapter variable and access to list productos to update the boolean value of each producto
[...]
ProductoAdapter productoAdapter = new ProductoAdapter();
[...]
for (int i = 0; i < productoAdapter.getItemCount(); i++) {
productoAdapter.getListProductos().get(i).setCheckBoxState(false);
}
productoAdapter.notifyDataSetChanged();

Issue with selector on RecycleView

I have my drawable selector.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/selected" android:state_activated="true"/>
<item android:drawable="#drawable/selected" android:state_pressed="true"/>
<item android:drawable="#drawable/selected" android:state_checked="true"/>
<item android:drawable="#drawable/selected" android:state_focused="true"/>
<item android:drawable="#drawable/unselected"/>
and this my RecycleView adapter
public class AdapterMain extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
List<String> data = Collections.emptyList();
DataMain current;
int currentPos = 0;
List<Integer> pos;
List<String> mDataset = data;
private SparseBooleanArray selectedItems;
private int focusedItem = 0;
// create constructor to innitilize context and data sent from MainActivity
public AdapterMain(Context context, List<String> data) {
this.context = context;
this.data = data;
}
#Override
public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
// Handle key up and key down and attempt to move selection
recyclerView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
// Return false if scrolled to the bounds and allow focus to move off the list
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
return tryMoveSelection(lm, 1);
} else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
return tryMoveSelection(lm, -1);
}
}
return false;
}
});
}
// Inflate the layout when viewholder created
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.container_main, parent, false);
MyHolder holder = new MyHolder(view);
return holder;
}
private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) {
int tryFocusItem = focusedItem + direction;
// If still within valid bounds, move the selection, notify to redraw, and scroll
if (tryFocusItem >= 0 && tryFocusItem < getItemCount()) {
notifyItemChanged(focusedItem);
focusedItem = tryFocusItem;
notifyItemChanged(focusedItem);
lm.scrollToPosition(focusedItem);
return true;
}
return false;
}
// Bind data
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//final String element = mDataset.get(position);
// Get current position of item in recyclerview to bind data and assign values from list
MyHolder myHolder = (MyHolder) holder;
String current = data.get(position);
myHolder.textTitle.setText(current);
//myHolder.textPrice.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
// load image into imageview using glide
// Glide.with(context).load("http://192.168.1.7/test/images/" +
current.fishImage)
// .placeholder(R.drawable.ic_img_error)
// .error(R.drawable.ic_img_error)
// .into(myHolder.ivFish);
}
// return total item from List
#Override
public int getItemCount() {
return data.size();
}
private class MyHolder extends RecyclerView.ViewHolder {
TextView textTitle;
ImageView ivAds;
TextView textPrice;
// create constructor to get widget reference
public MyHolder(View itemView) {
super(itemView);
textTitle = (TextView) itemView.findViewById(R.id.itemMainJson);
itemView.setClickable(true);
itemView.hasFocusable();
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Redraw the old selection and the new
notifyItemChanged(focusedItem);
focusedItem = getLayoutPosition();
notifyItemChanged(focusedItem);
}
});
}
}
}
my container_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_selector"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/all_haraj"
android:id="#+id/itemMainJson"
android:textSize="#dimen/text_main"
android:textColor="#color/black"
android:paddingRight="#dimen/padding_for_frogs"
android:paddingLeft="#dimen/padding_for_frogs"
android:paddingTop="#dimen/fab_press_translation_z"
android:paddingBottom="#dimen/fab_press_translation_z"/>
<ImageView
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="#drawable/horizontal_line"
android:paddingTop="2dp"
android:paddingBottom="2dp"/>
</LinearLayout>
My RecycleView OnCLick Class
public class ItemClickSupport {
private final RecyclerView mRecyclerView;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
}
};
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if (mOnItemLongClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
return false;
}
};
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
= new RecyclerView.OnChildAttachStateChangeListener() {
#Override
public void onChildViewAttachedToWindow(View view) {
if (mOnItemClickListener != null) {
view.setOnClickListener(mOnClickListener);
}
if (mOnItemLongClickListener != null) {
view.setOnLongClickListener(mOnLongClickListener);
}
}
#Override
public void onChildViewDetachedFromWindow(View view) {
}
};
private ItemClickSupport(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mRecyclerView.setTag(R.id.item_click_support, this);
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
}
public static ItemClickSupport addTo(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support == null) {
support = new ItemClickSupport(view);
}
return support;
}
public static ItemClickSupport removeFrom(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support != null) {
support.detach(view);
}
return support;
}
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
return this;
}
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
mOnItemLongClickListener = listener;
return this;
}
private void detach(RecyclerView view) {
view.removeOnChildAttachStateChangeListener(mAttachListener);
view.setTag(R.id.item_click_support, null);
}
public interface OnItemClickListener {
void onItemClicked(RecyclerView recyclerView, int position, View v);
}
public interface OnItemLongClickListener {
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
}
}
my problem with selector, when I chose item, I have to click twice to make interaction, and before I added clickable and focusable and focusableTouchMode to my Layout, action generated after first click but selector disappear quickly and doesn't focused, I want to make it focused on item I selected but with one click not twice.
Thanks in advance :)
If you just want a selector that changes the item's background when the user touches it, this can be implemented with just a few lines of xml (without changing the java code at all).
I did wonder why you have "checked" and "focused" among your states, but not "selected". I'd normally code a selector drawable like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/selected" android:state_activated="true"/>
<item android:drawable="#drawable/selected" android:state_pressed="true"/>
<item android:drawable="#drawable/selected" android:state_selected="true"/>
<item android:drawable="#drawable/unselected"/>
</selector>
But the first thing I'd do is temporarily get rid of the selector background and verify that the code's doing what you want when a user touches an item. That way, you can make sure that the basic code is working. Once you've done that,
you can just add the drawable back to your item_view layout like this.
android:background="#drawable/item_selector"
And that's how I'd usually do it (without changing a line of code). I hope you find this answer helpful.

Unable to listen to setOnItemClickListener in ListView - Android

I have a ListView in my MainActivity which has a customAdapter to it. I am implementing a slider on each of the list items. I have also attached a footerView to my listView. Now my problem is that, the setOnClickListener is not fired, and I am not able to print the position's of the listView. It only print's for the footerView alone, which I have attached.
The code for MainActivity is
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private Context mContext;
private ListView mainListView;
private TextView addContact;
private EditText inputName;
private List<String> contactList = new ArrayList<String>();
private MainListAdapter mainAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mContext = this;
init();
}
private void init() {
mainListView = (ListView)findViewById(R.id.lv_main);
initListData();
View footerView = getLayoutInflater().inflate(R.layout.listview_item_main, null);
footerView.setBackgroundColor(getResources().getColor(R.color.gold));
addContact = (TextView)footerView.findViewById(R.id.tv_item_name);
addContact.setText(getString(R.string.plus));
mainListView.addFooterView(footerView);
mainAdapter = new MainListAdapter(mContext, contactList);
mainListView.setAdapter(mainAdapter);
mainListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e(TAG, "on click item " + position);
if (position == contactList.size()) {
addContact.setVisibility(View.GONE);
inputName.setVisibility(View.VISIBLE);
}
}
});
inputName = (EditText)footerView.findViewById(R.id.et_input_name);
inputName.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_GO) {
InputMethodManager imm = (InputMethodManager)mContext
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive()) {
imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0);
}
String strInput = inputName.getText().toString();
contactList.add(strInput);
addContact.setVisibility(View.VISIBLE);
inputName.getText().clear();
inputName.setVisibility(View.GONE);
}
return false;
}
});
}
private void initListData() {
// temp data
contactList.add("Jacob");
contactList.add("Nicolas");
contactList.add("David");
contactList.add("Jacob");
contactList.add("Nicolas");
contactList.add("David");
}
}
Then the code for my CustomAdapter is
public class MainListAdapter extends BaseAdapter {
private static final String TAG = "MainListAdapter";
private Context mContext;
private LayoutInflater layoutInflater;
private MyViewPager itemViewPager;
private View viewMain;
private View viewSlide;
private TextView cancel;
private TextView delete;
private ArrayList<View> views;
private PagerAdapter pagerAdapter;
private List<String> mList;
public MainListAdapter(Context context, List<String> list) {
mContext = context;
layoutInflater = LayoutInflater.from(mContext);
mList = list;
}
#Override
public int getCount() {
return mList != null ? mList.size() : 0;
}
#Override
public Object getItem(int position) {
return mList != null ? mList.get(position) : null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.listview_item, null);
}
viewMain = layoutInflater.inflate(R.layout.listview_item_main, null);
viewSlide = layoutInflater.inflate(R.layout.listview_item_slide, null);
cancel = (TextView)viewSlide.findViewById(R.id.tv_menu_cancel);
delete = (TextView)viewSlide.findViewById(R.id.tv_menu_delete);
cancel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v(TAG, "on click cancel");
MyViewPager currPagerView = (MyViewPager)v.getParent().getParent();
currPagerView.setCurrentItem(0, true);
notifyDataSetChanged();
}
});
delete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v(TAG, "on click cancel");
itemViewPager.setCurrentItem(0, true);
notifyDataSetChanged();
MyViewPager currPagerView = (MyViewPager)v.getParent().getParent();
deleteContact(currPagerView.getSelfIndex());
}
});
views = new ArrayList<View>();
views.add(viewMain);
views.add(viewSlide);
itemViewPager = (MyViewPager)convertView.findViewById(R.id.vp_list_item);
itemViewPager.setSelfIndex(position);
pagerAdapter = new PagerAdapter() {
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((MyViewPager)container).removeView(views.get(position));
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
((MyViewPager)container).addView(views.get(position));
// Log.v("PagerAdapter", "curr item positon is" + position);
return views.get(position);
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
#Override
public int getCount() {
return views.size();
}
};
fillItemData(convertView, position, viewMain);
itemViewPager.setAdapter(pagerAdapter);
itemViewPager.setCurrentItem(0);
itemViewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
Log.v(TAG, "onPageSelected");
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
Log.v(TAG, "onPageScrolled, " + "arg0=" + arg0 + ", arg1=" + arg1 + ", arg2="
+ arg2);
}
#Override
public void onPageScrollStateChanged(int arg0) {
Log.v(TAG, "onPageScrollStateChanged");
}
});
// notifyDataSetChanged();
// pagerAdapter.notifyDataSetChanged();
return convertView;
}
private void fillItemData(View convertView, int position, View viewMain) {
int[] colorCollection = {
R.color.green, R.color.royalblue, R.color.violet
};
for (int i = 0; i < colorCollection.length; i++) {
colorCollection[i] = mContext.getResources().getColor(colorCollection[i]);
}
int currColor = colorCollection[position % colorCollection.length];
convertView.setBackgroundColor(currColor);
TextView itemName = (TextView)viewMain.findViewById(R.id.tv_item_name);
itemName.setText(mList.get(position));
// Log.v(TAG, "item name is " + itemName.getText());
}
private void deleteContact(int postion) {
mList.remove(postion);
}
}
Then finally the ViewPagerAdapter code is
public class MyViewPager extends ViewPager {
private static final String TAG = "MyViewPager";
private float xDown;
private float xMove;
private float yDown;
private float yMove;
private boolean isScroll = false;
private int selfIndex;
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setSelfIndex(int index) {
selfIndex = index;
}
public int getSelfIndex() {
return selfIndex;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
Log.v(TAG, "on intercept");
if (event.getAction() == MotionEvent.ACTION_UP) {
}
return super.onInterceptTouchEvent(event);
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v(TAG, "on dispatch");
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
xDown = ev.getRawX();
yDown = ev.getRawY();
Log.v(TAG, "action down: " + xDown + ", " + yDown);
} else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
xMove = ev.getRawX();
yMove = ev.getRawY();
Log.v(TAG, "action move: " + xMove + ", " + yMove);
if (isScroll) {
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
if (Math.abs(yMove - yDown) < 5 && Math.abs(xMove - xDown) > 20) {
isScroll = true;
} else {
return false;
}
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
isScroll = false;
}
return super.dispatchTouchEvent(ev);
}
}
The MainActivity layout is
<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"
android:background="#color/background"
tools:context="${packageName}.${activityClass}" >
<ListView
android:id="#+id/lv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#android:color/transparent"
android:listSelector="#android:color/transparent" />
</RelativeLayout>
The layout for listview_item is
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minHeight="100dp" >
<com.example.yo.view.MyViewPager
android:id="#+id/vp_list_item"
android:layout_width="fill_parent"
android:layout_height="100dp" />
</RelativeLayout>
Added all XML Layouts
listview_item_main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:minHeight="100dp" >
<TextView
android:id="#+id/tv_item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/main_list_text"
android:textSize="48sp"
android:textStyle="bold" />
<EditText
android:id="#+id/et_input_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/add_contact_hint"
android:textColorHint="#color/main_list_text"
android:textColor="#color/main_list_text"
android:textSize="30sp"
android:textStyle="bold"
android:inputType="textCapCharacters"
android:background="#null"
android:textCursorDrawable="#null"
android:singleLine="true"
android:imeOptions="actionDone"
android:visibility="gone" />
</RelativeLayout>
listview_item_slide
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minHeight="100dp"
android:orientation="horizontal" >
<TextView
android:id="#+id/tv_menu_cancel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:focusableInTouchMode="true"
android:background="#color/gold"
android:gravity="center"
android:text="#string/cancel"
android:textColor="#color/main_list_text"
android:textSize="28sp"
android:textStyle="bold" />
<TextView
android:id="#+id/tv_menu_delete"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#color/green"
android:gravity="center"
android:text="#string/delete"
android:textColor="#color/main_list_text"
android:textSize="28sp"
android:textStyle="bold" />
<TextView
android:id="#+id/tv_menu_block"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#color/royalblue"
android:gravity="center"
android:text="#string/block"
android:textColor="#color/main_list_text"
android:textSize="28sp"
android:textStyle="bold" />
</LinearLayout>
Please help me to listen to the onItemClickListener in the MainActivity's list. I am not able to figure out where I went wrong. Thanks in advance.
you have to put your "setOnItemClickListener" to your Adapter class insted of MainActivity.
public View getView(final int position, View convertView, ViewGroup parent) {
// Declare Variables
ViewHolder holder;
View iView = convertView;
if (convertView == null) {
iView = inflater.inflate(R.layout.listview_item, parent, false);
holder = new ViewHolder();
holder.txt_name = (TextView) iView.findViewById(R.id.name);
Typeface custom_fontG = Typeface.createFromAsset(
context.getAssets(), "KozGoPr6N-Regular.otf");
holder.txt_name.setTypeface(custom_fontG);
holder.txt_desc = (TextView) iView.findViewById(R.id.detail);
holder.ivProfile = (ImageView) iView.findViewById(R.id.flag);
iView.setTag(holder);
} else {
holder = (ViewHolder) iView.getTag();
}
// Get the position
resultp = data.get(position);
// Locate the TextViews in listview_item.xml
// Capture position and set results to the TextViews
holder.txt_name.setText(resultp.get(OurTeam.TAG_NAME));
holder.txt_desc.setText(resultp.get(OurTeam.TAG_DETAIL));
imageLoader.displayImage(TAG_IMAGEURL + resultp.get((OurTeam.TAG_IMG)),
holder.ivProfile, options);
// Capture ListView item click
iView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// Get the position
// your code
}
});
return iView;
}
At a time you can handle click event either in Adapter class of in Activity. in your case you are doing both.
And to manage
addContact.setVisibility(View.GONE);
inputName.setVisibility(View.VISIBLE);
Write above on click event of what ever is main view in listview_item layout (Do not forget to pass addContact and inputName views to your CustomAdapter).
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private Context mContext;
private ListView mainListView;
private TextView addContact;
private EditText inputName;
private List<String> contactList = new ArrayList<String>();
private MainListAdapter mainAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mContext = this;
init();
}
private void init() {
mainListView = (ListView)findViewById(R.id.lv_main);
initListData();
View footerView = getLayoutInflater().inflate(R.layout.listview_item_main, null);
footerView.setBackgroundColor(getResources().getColor(R.color.gold));
addContact = (TextView)footerView.findViewById(R.id.tv_item_name);
addContact.setText(getString(R.string.plus));
mainListView.addFooterView(footerView);
mainAdapter = new MainListAdapter(mContext, contactList);
mainListView.setAdapter(mainAdapter);
/* mainListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e(TAG, "on click item " + position);
if (position == contactList.size()) {
addContact.setVisibility(View.GONE);
inputName.setVisibility(View.VISIBLE);
}
}
});*/
inputName = (EditText)footerView.findViewById(R.id.et_input_name);
inputName.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_GO) {
InputMethodManager imm = (InputMethodManager)mContext
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive()) {
imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0);
}
String strInput = inputName.getText().toString();
contactList.add(strInput);
addContact.setVisibility(View.VISIBLE);
inputName.getText().clear();
inputName.setVisibility(View.GONE);
}
return false;
}
});
}
private void initListData() {
// temp data
contactList.add("Jacob");
contactList.add("Nicolas");
contactList.add("David");
contactList.add("Jacob");
contactList.add("Nicolas");
contactList.add("David");
}
}
and Adapter Class was..
public class MainListAdapter extends BaseAdapter {
private static final String TAG = "MainListAdapter";
private Context mContext;
private LayoutInflater layoutInflater;
private MyViewPager itemViewPager;
private View viewMain;
private View viewSlide;
private TextView cancel;
private TextView delete;
private ArrayList<View> views;
private PagerAdapter pagerAdapter;
private List<String> mList;
public MainListAdapter(Context context, List<String> list) {
mContext = context;
layoutInflater = LayoutInflater.from(mContext);
mList = list;
}
#Override
public int getCount() {
return mList != null ? mList.size() : 0;
}
#Override
public Object getItem(int position) {
return mList != null ? mList.get(position) : null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.listview_item, null);
}
viewMain = layoutInflater.inflate(R.layout.listview_item_main, null);
viewSlide = layoutInflater.inflate(R.layout.listview_item_slide, null);
cancel = (TextView)viewSlide.findViewById(R.id.tv_menu_cancel);
delete = (TextView)viewSlide.findViewById(R.id.tv_menu_delete);
cancel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v(TAG, "on click cancel");
MyViewPager currPagerView = (MyViewPager)v.getParent().getParent();
currPagerView.setCurrentItem(0, true);
notifyDataSetChanged();
}
});
delete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v(TAG, "on click cancel");
itemViewPager.setCurrentItem(0, true);
notifyDataSetChanged();
MyViewPager currPagerView = (MyViewPager)v.getParent().getParent();
deleteContact(currPagerView.getSelfIndex());
}
});
views = new ArrayList<View>();
views.add(viewMain);
views.add(viewSlide);
itemViewPager = (MyViewPager)convertView.findViewById(R.id.vp_list_item);
itemViewPager.setSelfIndex(position);
pagerAdapter = new PagerAdapter() {
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((MyViewPager)container).removeView(views.get(position));
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
((MyViewPager)container).addView(views.get(position));
// Log.v("PagerAdapter", "curr item positon is" + position);
return views.get(position);
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
#Override
public int getCount() {
return views.size();
}
};
fillItemData(convertView, position, viewMain);
itemViewPager.setAdapter(pagerAdapter);
itemViewPager.setCurrentItem(0);
itemViewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
Log.v(TAG, "onPageSelected");
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
Log.v(TAG, "onPageScrolled, " + "arg0=" + arg0 + ", arg1=" + arg1 + ", arg2="
+ arg2);
}
#Override
public void onPageScrollStateChanged(int arg0) {
Log.v(TAG, "onPageScrollStateChanged");
}
});
// notifyDataSetChanged();
// pagerAdapter.notifyDataSetChanged();
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// your code here for list item click listener...
}
})
return convertView;
}
private void fillItemData(View convertView, int position, View viewMain) {
int[] colorCollection = {
R.color.green, R.color.royalblue, R.color.violet
};
for (int i = 0; i < colorCollection.length; i++) {
colorCollection[i] = mContext.getResources().getColor(colorCollection[i]);
}
int currColor = colorCollection[position % colorCollection.length];
convertView.setBackgroundColor(currColor);
TextView itemName = (TextView)viewMain.findViewById(R.id.tv_item_name);
itemName.setText(mList.get(position));
// Log.v(TAG, "item name is " + itemName.getText());
}
private void deleteContact(int postion) {
mList.remove(postion);
}
}
add this below line in your listview_item parent layout only.
android:descendantFocusability="blocksDescendants"
actually when the list item contains a element which can get focus then list item click listener not work.
Add this to the parent of your Listview and parent of your listview_item and try again:
android:descendantFocusability="blocksDescendants"
Like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:descendantFocusability="blocksDescendants"
android:layout_height="match_parent"
android:background="#color/background"
tools:context="${packageName}.${activityClass}" >
<ListView
android:id="#+id/lv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#android:color/transparent"
android:listSelector="#android:color/transparent" />
and this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:descendantFocusability="blocksDescendants"
android:minHeight="100dp" >
<com.example.yo.view.MyViewPager
android:id="#+id/vp_list_item"
android:layout_width="fill_parent"
android:layout_height="100dp" />
</RelativeLayout>
If this does not work, call isFocusable() on your EditText and TextView
addContact.isFocusable(false);
inputName.isFocusable(false);
I am guessing you made a common error. Please check/try both changes.
1) add android:descendantFocusability="blocksDescendants" into the ListView UI ("#+id/lv_main").
Note: If this and 2nd suggestion does not work, then the Listview layout may need rework.
2) mainListView.setItemsCanFocus(false);
Note: The Listview may be confused with focusing on an item in the UI.
I think the suggested code by "Nirmal Shethwala" looks good. It has the if/else block for if (convertView == null).
EDIT: I noticed you inflated 3 xml layout files in getView(). You can only have one, and that is listview_item in your code. I know this is not well documented. I have tried this in the past. The reason is getView() method has to return only one view, and your code return convertView; like me.
Sorry I know this will take some modifications in your layout.

Categories

Resources