This is my code:
clientGridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
gridClientChooseMode = !gridClientChooseMode;
clientAdapter.notifyDataSetChanged();
return false;
}
};)
and this is the adapter for the gridview:
class ClientListAdapter extends ArrayAdapter<ClientData> {
public ClientListAdapter(Context context, List<ClientData> list) {
super(context, R.layout.view_item, list);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (gridClientChooseMode) {
checkBox.setVisibility(View.VISIBLE);
}else{
checkBox.setVisibility(View.GONE);
}
}
}
checkBox will change its visibility to VISIBLE when gridClientChooseMode=true (when long click on item of the gridview).But after that I cannot turn off the check box because the OnItemLongClickListener didn't work anymore, I mean it works only at first time. Any help is highly appreaciate. Thanks in adavance.
#Elltz is right about the CheckBoxes stealing focus. In the layout root view for you grid items, you need the following to prevent the CheckBoxes from getting focus:
android:descendantFocusability="blocksDescendants"
whiles checkbox is visible it takes away the focus, so either you do put your onlongitemclick listener functions in your checkbox widget onlongclicklistener in your adapter, so it responds to itself and set itself to gone or invisible or you intercept touch events for the grid or listview, and handle all focus/touch events
I have a RecyclerView with an TextView text box and a cross button ImageView. I have a button outside of the recyclerview that makes the cross button ImageView visible / gone.
I'm looking to remove an item from the recylerview, when that items cross button ImageView is pressed.
My adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener {
private ArrayList<String> mDataset;
private static Context sContext;
public MyAdapter(Context context, ArrayList<String> myDataset) {
mDataset = myDataset;
sContext = context;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view, parent, false);
ViewHolder holder = new ViewHolder(v);
holder.mNameTextView.setOnClickListener(MyAdapter.this);
holder.mNameTextView.setOnLongClickListener(MyAdapter.this);
holder.mNameTextView.setTag(holder);
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mNameTextView.setText(mDataset.get(position));
}
#Override
public int getItemCount() {
return mDataset.size();
}
#Override
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
if (view.getId() == holder.mNameTextView.getId()) {
Toast.makeText(sContext, holder.mNameTextView.getText(), Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onLongClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
if (view.getId() == holder.mNameTextView.getId()) {
mDataset.remove(holder.getPosition());
notifyDataSetChanged();
Toast.makeText(sContext, "Item " + holder.mNameTextView.getText() + " has been removed from list",
Toast.LENGTH_SHORT).show();
}
return false;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mNumberRowTextView;
public TextView mNameTextView;
public ViewHolder(View v) {
super(v);
mNameTextView = (TextView) v.findViewById(R.id.nameTextView);
}
}
}
My layout is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:id="#+id/layout">
<TextView
android:id="#+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:padding="5dp"
android:background="#drawable/greyline"/>
<ImageView
android:id="#+id/crossButton"
android:layout_width="16dp"
android:layout_height="16dp"
android:visibility="gone"
android:layout_marginLeft="50dp"
android:src="#drawable/cross" />
</LinearLayout>
How can I get something like an onClick working for my crossButton ImageView? Is there a better way? Maybe changing the whole item onclick into a remove the item? The recyclerview shows a list of locations that need to be edited. Any technical advice or comments / suggestions on best implementation would be hugely appreciated.
I have done something similar.
In your MyAdapter:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public CardView mCardView;
public TextView mTextViewTitle;
public TextView mTextViewContent;
public ImageView mImageViewContentPic;
public ImageView imgViewRemoveIcon;
public ViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextViewTitle = (TextView) v.findViewById(R.id.item_title);
mTextViewContent = (TextView) v.findViewById(R.id.item_content);
mImageViewContentPic = (ImageView) v.findViewById(R.id.item_content_pic);
//......
imgViewRemoveIcon = (ImageView) v.findViewById(R.id.remove_icon);
mTextViewContent.setOnClickListener(this);
imgViewRemoveIcon.setOnClickListener(this);
v.setOnClickListener(this);
mTextViewContent.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(view, getPosition());
}
return false;
}
});
}
#Override
public void onClick(View v) {
//Log.d("View: ", v.toString());
//Toast.makeText(v.getContext(), mTextViewTitle.getText() + " position = " + getPosition(), Toast.LENGTH_SHORT).show();
if(v.equals(imgViewRemoveIcon)){
removeAt(getPosition());
}else if (mItemClickListener != null) {
mItemClickListener.onItemClick(v, getPosition());
}
}
}
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public void removeAt(int position) {
mDataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
}
Edit:
getPosition() is deprecated now, use getAdapterPosition() instead.
first of all, item should be removed from the list!
mDataSet.remove(getAdapterPosition());
then:
notifyItemRemoved(getAdapterPosition());
notifyItemRangeChanged(getAdapterPosition(), mDataSet.size()-getAdapterPosition());
if still item not removed use this magic method :)
private void deleteItem(int position) {
mDataSet.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
holder.itemView.setVisibility(View.GONE);
}
Kotlin version
private fun deleteItem(position: Int) {
mDataSet.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, mDataSet.size)
holder.itemView.visibility = View.GONE
}
The Problem
RecyclerView was built to display data in an efficient and responsive manner.
Usually you have a dataset which is passed to your adapter and is looped through to display your data.
Here your dataset is:
private ArrayList<String> mDataset;
The point is that RecyclerView is not connected to your dataset, and therefore is unaware of your dataset changes.
It just reads data once and displays it through your ViewHolder, but a change to your dataset will not propagate to your UI.
This means that whenever you make a deletion/addition on your data list, those changes won't be reflected to your RecyclerView directly. (i.e. you remove the item at index 5, but the 6th element remains in your recycler view).
A (old school) solution
RecyclerView exposes some methods for you to communicate your dataset changes, reflecting those changes directly on your list items.
The standard Android APIs allow you to bind the process of data removal (for the purpose of the question) with the process of View removal.
The methods we are talking about are:
notifyItemChanged(index: Int)
notifyItemInserted(index: Int)
notifyItemRemoved(index: Int)
notifyItemRangeChanged(startPosition: Int, itemCount: Int)
notifyItemRangeInserted(startPosition: Int, itemCount: Int)
notifyItemRangeRemoved(startPosition: Int, itemCount: Int)
A Complete (old school) Solution
If you don't properly specify what happens on each addition, change or removal of items, RecyclerView list items are animated unresponsively because of a lack of information about how to move the different views around the list.
The following code will allow RecyclerView to precisely play the animation with regards to the view that is being removed (And as a side note, it fixes any IndexOutOfBoundExceptions, marked by the stacktrace as "data inconsistency").
void remove(position: Int) {
dataset.removeAt(position)
notifyItemChanged(position)
notifyItemRangeRemoved(position, 1)
}
Under the hood, if we look into RecyclerView we can find documentation explaining that the second parameter we pass to notifyItemRangeRemoved is the number of items that are removed from the dataset, not the total number of items (As wrongly reported in some others information sources).
/**
* Notify any registered observers that the <code>itemCount</code> items previously
* located at <code>positionStart</code> have been removed from the data set. The items
* previously located at and after <code>positionStart + itemCount</code> may now be found
* at <code>oldPosition - itemCount</code>.
*
* <p>This is a structural change event. Representations of other existing items in the data
* set are still considered up to date and will not be rebound, though their positions
* may be altered.</p>
*
* #param positionStart Previous position of the first item that was removed
* #param itemCount Number of items removed from the data set
*/
public final void notifyItemRangeRemoved(int positionStart, int itemCount) {
mObservable.notifyItemRangeRemoved(positionStart, itemCount);
}
Open source solutions
You can let a library like FastAdapter, Epoxy or Groupie take care of the business, and even use an observable recycler view with data binding.
New ListAdapter
Google recently introduced a new way of writing the recycler view adapter, which works really well and supports reactive data.
It is a new approach and requires a bit of refactoring, but it is 100% worth switching to it, as it makes everything smoother.
here is the documentation, and here a medium article explaining it
Here are some visual supplemental examples. See my fuller answer for examples of adding and removing a range.
Add single item
Add "Pig" at index 2.
String item = "Pig";
int insertIndex = 2;
data.add(insertIndex, item);
adapter.notifyItemInserted(insertIndex);
Remove single item
Remove "Pig" from the list.
int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);
Possibly a duplicate answer but quite useful for me. You can implement the method given below in RecyclerView.Adapter<RecyclerView.ViewHolder>
and can use this method as per your requirements, I hope it will work for you
public void removeItem(#NonNull Object object) {
mDataSetList.remove(object);
notifyDataSetChanged();
}
I tried all the above answers, but inserting or removing items to recyclerview causes problem with the position in the dataSet. Ended up using delete(getAdapterPosition()); inside the viewHolder which worked great at finding the position of items.
The problem I had was I was removing an item from the list that was no longer associated with the adapter to make sure you are modifying the correct adapter you can implement a method like this in your adapter:
public void removeItemAtPosition(int position) {
items.remove(position);
}
And call it in your fragment or activity like this:
adapter.removeItemAtPosition(position);
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private List<cardview_widgets> list;
public MyAdapter(Context context, List<cardview_widgets> list) {
this.context = context;
this.list = list;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(this.context).inflate(R.layout.fragment1_one_item,
viewGroup, false);
return new MyViewHolder(view);
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtValue;
TextView txtCategory;
ImageView imgInorEx;
ImageView imgCategory;
TextView txtDate;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
txtValue= itemView.findViewById(R.id.id_values);
txtCategory= itemView.findViewById(R.id.id_category);
imgInorEx= itemView.findViewById(R.id.id_inorex);
imgCategory= itemView.findViewById(R.id.id_imgcategory);
txtDate= itemView.findViewById(R.id.id_date);
}
}
#NonNull
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, int i) {
myViewHolder.txtValue.setText(String.valueOf(list.get(i).getValuee()));
myViewHolder.txtCategory.setText(list.get(i).getCategory());
myViewHolder.imgInorEx.setBackgroundColor(list.get(i).getImg_inorex());
myViewHolder.imgCategory.setImageResource(list.get(i).getImg_category());
myViewHolder.txtDate.setText(list.get(i).getDate());
myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
list.remove(myViewHolder.getAdapterPosition());
notifyDataSetChanged();
return false;
}
});
}
#Override
public int getItemCount() {
return list.size();
}}
i hope this help you.
if you want to remove item you should do this:
first remove item:
phones.remove(position);
in next step you should notify your recycler adapter that you remove an item by this code:
notifyItemRemoved(position);
notifyItemRangeChanged(position, phones.size());
but if you change an item do this:
first change a parameter of your object like this:
Service s = services.get(position);
s.done = "Cancel service";
services.set(position,s);
or new it like this :
Service s = new Service();
services.set(position,s);
then notify your recycler adapter that you modify an item by this code:
notifyItemChanged(position);
notifyItemRangeChanged(position, services.size());
hope helps you.
String str = arrayList.get(position);
arrayList.remove(str);
MyAdapter.this.notifyDataSetChanged();
To Method onBindViewHolder Write This Code
holder.remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Cursor del=dbAdapter.ExecuteQ("delete from TblItem where Id="+values.get(position).getId());
values.remove(position);
notifyDataSetChanged();
}
});
Incase Anyone wants to implement something like this in Main class instead of Adapter class, you can use:
public void removeAt(int position) {
peopleListUser.remove(position);
friendsListRecycler.getAdapter().notifyItemRemoved(position);
friendsListRecycler.getAdapter().notifyItemRangeChanged(position, peopleListUser.size());
}
where friendsListRecycler is the Adapter name
you must to remove this item from arrayList of data
myDataset.remove(holder.getAdapterPosition());
notifyItemRemoved(holder.getAdapterPosition());
notifyItemRangeChanged(holder.getAdapterPosition(), getItemCount());
//////// set the position
holder.cancel.setTag(position);
///// click to remove an item from recycler view and an array list
holder.cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int positionToRemove = (int)view.getTag(); //get the position of the view to delete stored in the tag
mDataset.remove(positionToRemove);
notifyDataSetChanged();
}
});
make interface into custom adapter class and handling click event on recycler view..
onItemClickListner onItemClickListner;
public void setOnItemClickListner(CommentsAdapter.onItemClickListner onItemClickListner) {
this.onItemClickListner = onItemClickListner;
}
public interface onItemClickListner {
void onClick(Contact contact);//pass your object types.
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
// below code handle click event on recycler view item.
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onItemClickListner.onClick(mContectList.get(position));
}
});
}
after define adapter and bind into recycler view called below code..
adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() {
#Override
public void onClick(Contact contact) {
contectList.remove(contectList.get(contectList.indexOf(contact)));
adapter.notifyDataSetChanged();
}
});
}
In case you are wondering like I did where can we get the adapter position in the method getadapterposition(); its in viewholder object.so you have to put your code like this
mdataset.remove(holder.getadapterposition());
In the activity:
mAdapter.updateAt(pos, text, completed);
mAdapter.removeAt(pos);
In the your adapter:
void removeAt(int position) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, list.size());
}
void updateAt(int position, String text, Boolean completed) {
TodoEntity todoEntity = list.get(position);
todoEntity.setText(text);
todoEntity.setCompleted(completed);
notifyItemChanged(position);
}
in 2022, after trying everything the whole internet given below is the answer
In MyViewHolder class
private myAdapter adapter;
inside MyViewHolder function initalise adapter
adapter = myAdapter.this
inside onclick
int position = getAdapterPosition()
list.remove(position);
adapter.notifyItemRemoved(position);
I am using Yuri Kanivets' WheelView in my project.
For translation purposes, I have made a custom TextView with custom Font. The WheelView uses TextView to display text. I would like to use the custom Textview in Wheelview so that it displays the text in custom font. How do I do that?
I don't want to change the original source of wheelview, in case I have to use it for other apps.
Code of the wheelview adapter:
/**
* Adapter for string based wheel. Highlights the current value.
*/
private class DateArrayAdapter extends ArrayWheelAdapter<String> {
// Index of current item
int currentItem;
// Index of item to be highlighted
int currentValue;
/**
* Constructor
*/
public DateArrayAdapter(Context context, String[] items, int current) {
super(context, items);
this.currentValue = current;
setTextSize(16);
}
#Override
protected void configureTextView(TextView view) {
super.configureTextView(view);
if (currentItem == currentValue) {
view.setTextColor(getResources().getColor(R.color.holo_blue));
}
view.setTypeface(Typeface.SANS_SERIF);
view.setTextSize(18);
}
#Override
public View getItem(int index, View cachedView, ViewGroup parent) {
currentItem = index;
return super.getItem(index, cachedView, parent);
}
}
Create a layout xml with your own view. Let us say it is layout_item.xml. Set the id of your view (the custom textview) to text using android:id="#+id/text"
Use this on your adapter:
adapter.setItemResource(R.layout.layout_item);
adapter.setItemTextResource(R.id.text);
I guess now it should work
How can I get a grid-view's item tag by its position and have to get from another grid-view's item click listener function.
gridview2.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v,
int position, long id)
{
int i=(Integer)gridview1.getChildAt(gridview1s_position).getTag();---> it is returning Null
}
});
MY gridview1.setOnitemClicklistener and gridview2.setonitemclicklistener are in the same file (MainActivity.java)
But the gridview1 adapter is a ImageAdapter.java(this is for setting the images in the gridview1) and gridview2 adapter is imageadapter2.java(this is for setting black images so that the gridview2 looks like a box with rows and columns, otherwise it is showing like a Bold line because we didn't put anything in the gridview)
gridview1.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v,int position, long id)
{
int tag=(Integer)gridview1.getChildAt(position).getTag();//this returning the tag
}
});
ImageAdapter1.java
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
if(arg1!=null)
{
imv=(ImageView)arg1;
}
else
{
imv=new ImageView(cont);
imv.setLayoutParams(new GridView.LayoutParams(40,40));
imv.setScaleType(ScaleType.CENTER_CROP);
imv.setPadding(0,0,0,0);
}
imv.setImageResource(imageid[arg0]);//imageid aray is having drawable images
imv.setTag(imageid[arg0]);
return imv;
}
gridview2
gridview2.setOnItemClickListener(new OnItemClickListener()
{
ImageAdapter ia=new ImageAdapter(getApplicationContext());
public void onItemClick(AdapterView<?> parent, View v,int position, long id)
{
ImageView imv;
if(v!=null)
{
imv=(ImageView)v;
}
else
{
imv=new ImageView(getApplicationContext());
imv.setLayoutParams(new GridView.LayoutParams(40,40));
imv.setScaleType(ScaleType.CENTER_CROP);
imv.setPadding(0,0,0,0);
imv.setBackgroundColor(5555);
}
imv.setImageResource(ia.imageid[tt]);
}
});
using getChildAt might be too cumbersome for something like this because it only useful for making references to views that are in view and re-orders its indexes to match this. I don't know enough about where your other GridView is positioned to pursue this avenue further.
But regardless, the way i'd do something like this is to make an intermediary collection between the two adapters. as in one adapter holds all the tags in an indexed collection and then you could make some sort of reader get method. at the very least, this way of doing it would put my mind at ease.
gridview2.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
int i = gridview1.getTagFromPosition(position);
}
});
then in the gridView1 adapter something like:
private int[] tagCollection;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// .....
convertView.setTag(tagCollection[position]);
return convertView;
}
public int getTagFromPosition(int position) {
return tagCollection[position];
}
i at least hope the idea comes across so that you can modify it for however is practical for how your objects are getting modified and accessed.
Finally myself i got the solution for my question.Thank you for all who gave their valuable suggestions.
i saved the tag of a particullar cell of grid-view1 in a variable and used that variable in the grid-view2.
I have a ListView which uses a custom adapter as shown:
private class CBAdapter extends BaseAdapter implements OnCheckedChangeListener{
Context context;
public String[] englishNames;
LayoutInflater inflater;
CheckBox[] checkBoxArray;
LinearLayout[] viewArray;
private boolean[] checked;
public CBAdapter(Context con, String[] engNames){
context=con;
englishNames=engNames;
inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
checked= new boolean[englishNames.length];
for(int i=0; i<checked.length; i++){
checked[i]=false;
//Toast.makeText(con, checked.toString(),Toast.LENGTH_SHORT).show();
}
checkBoxArray = new CheckBox[checked.length];
viewArray = new LinearLayout[checked.length];
}
public int getCount() {
return englishNames.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
if(viewArray[position] == null){
viewArray[position]=(LinearLayout)inflater.inflate(R.layout.record_view_start,null);
TextView tv=(TextView)viewArray[position].findViewById(R.id.engName);
tv.setText(englishNames[position]);
checkBoxArray[position]=(CheckBox)viewArray[position].findViewById(R.id.checkBox1);
}
checkBoxArray[position].setChecked(checked[position]);
checkBoxArray[position].setOnCheckedChangeListener(this);
return viewArray[position];
}
public void checkAll(boolean areChecked){
for(int i=0; i<checked.length; i++){
checked[i]=areChecked;
if(checkBoxArray[i] != null)
checkBoxArray[i].setChecked(areChecked);
}
notifyDataSetChanged();
}
public void onCheckedChanged(CompoundButton cb, boolean isChecked) {
for(int i=0; i<checked.length; i++){
if(cb == checkBoxArray[i])
checked[i]=isChecked;
}
}
public boolean itemIsChecked(int i){
return checked[i];
}
}
The layouts are fairly simple so I won't post them unless anyone thinks they are relevant.
The problem is that some of the CheckBoxes are not responding. It seems to be the ones that are visible when the layout is first displayed. Any that you have to scroll down to work as expected.
Any pointers appreciated.
Your code from the answer works but is inefficient(you can actually see this, just scroll the ListView and check the Logcat to see the garbage collector doing it's work). An improved getView method which will recycle views is the one below:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout view = (LinearLayout) convertView;
if (view == null) {
view = (LinearLayout) inflater.inflate(R.layout.record_view_start, parent, false);
}
TextView tv = (TextView) view.findViewById(R.id.engName);
tv.setText(getItem(position));
CheckBox cBox = (CheckBox) view.findViewById(R.id.checkBox1);
cBox.setTag(Integer.valueOf(position)); // set the tag so we can identify the correct row in the listener
cBox.setChecked(mChecked[position]); // set the status as we stored it
cBox.setOnCheckedChangeListener(mListener); // set the listener
return view;
}
OnCheckedChangeListener mListener = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mChecked[(Integer)buttonView.getTag()] = isChecked; // get the tag so we know the row and store the status
}
};
Regarding your code from your question, at first I thought it was wrong because of the way you setup the rows but I don't see why the adapter will have that behavior as you detached the row view from the list. Also, I even tested the code and it works quite well regarding CheckBoxes(but with very poor memory handling). Maybe you're doing something else that makes the adapter to not work?
Let me first say that you have thrown away one of the main benefits of using an adapter: Reusable views. Holding a hard reference to each created View holds a high risk of hitting the memory ceiling. You should be reusing convertView when it is non-null, and creating your view when convertView is null. There are many tutorials around which show you how to do this.
Views used in an adapter typically have an OnClickListener attached to them by the parent View so that you can set a OnItemClickListener on the ListView. This will supersede any touch listeners on the individual views. Try setting android:clickable="true" on the CheckBox in XML.
This may not be the most elegant or efficient solution but it works for my situation. For some reason attempting to reuse the views either from an array of views or using convertView makes every thing go wobbley and the CheckBoxes fail to respond.
The only thing that worked was creating a new View everytime getView() is called.
public View getView(final int position, View convertView, ViewGroup parent) {
LinearLayout view;
view=(LinearLayout)inflater.inflate(R.layout.record_view_start,null);
TextView tv=(TextView)view.findViewById(R.id.engName);
tv.setText(englishNames[position]);
CheckBox cBox=(CheckBox)view.findViewById(R.id.checkBox1);
cBox.setChecked(checked[position]);
cBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checked[position]=isChecked;
}
});
return view;
}
Finding this solution was also hampered by the fact that I was calling a separately defined onCheckedChangedListener, that then identified which CheckBox by id, rather than having a new listener for each CheckBox.
As yet I haven't marked this as the correct answer as I'm hoping that others may have some input regarding the rather wasteful rebuilding the view every time.