I have a custom list view with base adapter.In the listview each item contain button and a textview,I want to visible the textview when clicking on the corresponding button.It is working bt my problem is that when i click on the button the textview is visible in more than one item.Please suggest any solution.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
// convertView = new View(context);
convertView = inflater.inflate(R.layout.secondadapter, null);
}
holder.ans=(Button)convertView.findViewById(R.id.btn_ans);
holder.textview=(TextView)convertView.findViewById(R.id.txt_ans);
holder.ans.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
holder.textview.setText("Answer is correct");
}
});
}
public class Holder
{
TextView textview;
Button ans;
}
Try this code.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
// convertView = new View(context);
convertView = inflater.inflate(R.layout.secondadapter, null);
holder.ans=(Button)convertView.findViewById(R.id.btn_ans);
holder.textview=(TextView)convertView.findViewById(R.id.txt_ans);
convertView.setTag(holder);
}else{
holder=(holder)convertView.getTag();
}
if(!isTextViewVisible[position]) { holder.textview.setVisibility(View.Invisible); }
else {
holder.textview.setVisibility(View.visible);
}
holder.ans.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
holder.textview.setText("Answer is correct"); isTextViewVisible[position] = true;
} });
}
public class Holder
{
TextView textview;
Button ans;
}
You are didn't follow ViewHolder Pattern.You have to use convertView.setTag(holder) and holder=(holder)convertView.getTag()
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
// convertView = new View(context);
convertView = inflater.inflate(R.layout.secondadapter, null);
holder.ans=(Button)convertView.findViewById(R.id.btn_ans);
holder.textview=(TextView)convertView.findViewById(R.id.txt_ans);
convertView.setTag(holder);
}else{
holder=(holder)convertView.getTag();
}
holder.ans.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
holder.textview.setText("Answer is correct");
}
});
}
public class Holder
{
TextView textview;
Button ans;
}
Please have a read to understand , how listview works.
public class SampleAdapter extends BaseAdapter {
public SampleAdapter (Activity callingActivity,
ArrayList datas, Resources imagesEtc) {
this.callingActivity = callingActivity;
this.datas = datas;
this.imagesEtc = imagesEtc;
}
#Override
public void notifyDataSetChanged() {
// Refresh List rows
super.notifyDataSetChanged();
}
#Override
public int getCount() {
if (datas.size() <= 0)
return 1;
return datas.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
public static class ItemsInEachRow {
TextView sample1, sample2, sample3;
}
#Override
public View getView(final int position, View eachRowsView,
ViewGroup parentView) {
// To Inflate Single Item of ListView
View eachRow = eachRowsView;
ItemsInEachRow itemsInEachRow;
if (eachRowsView == null) {
itemsInEachRow = new ItemsInEachRow();
eachRow = callingActivity.getLayoutInflater().inflate(
R.layout.your_layout, null);
itemsInEachRow.sample1= (TextView) eachRow
.findViewById(R.id.sample1);
eachRow.setTag(itemsInEachRow);
} else {
itemsInEachRow = (ItemsInEachRow) eachRow.getTag();
}
itemsInEachRow.sample1
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
}
});
return eachRow;
}
}
Please see below code hope it will work for you
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
{
convertView = inflater.inflate(R.layout.secondadapter, null);
holder.ans=(Button)convertView.findViewById(R.id.btn_ans);
holder.textview=(TextView)convertView.findViewById(R.id.txt_ans);
convertView.setTag(holder);
}
else
{
m_viewHolder = (ViewHolder) convertView.getTag();
}
holder.ans.setTag(position);
holder.ans.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
int m_position = Integer.parseInt(p_view.getTag().toString());
holder.textview.setText("Answer is correct");
}
});
}
public class Holder
{
TextView textview;
Button ans;
}
If textview is sibling of button. Using its parent get the corresponding textview. here is the code.
holder.ans.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
View vi = (View) v.getParent();
TextView texview = (TextView) vi.findViewById(R.id.txt_ans);
textview.setText("Answer is correct");
textview.setVisiblity(View.VISIBLE);
}
});
There are more than one view getting visible is because ListView reuse your view if it is no longer visible on the screen. To tell ListView to don't do this for a view: itemView.setHasTransientState(true)
When you are done with that view (e.g the item has been removed) you can call the method again and set it to false.
To Learn more. https://www.youtube.com/watch?v=8MIfSxgsHIs
P/s: It seems like you do not follow the viewHolder Pattern as #kishore-jethava said.
Related
I have a problem with "remembering" states of Checkboxes in CheckTextView.
Now when I click, it changes the state but on different CheckBox.
class CustomAdapterSmartwatch extends ArrayAdapter<String> {
static class ViewHolder {
protected CheckedTextView cTextView;
}
ViewHolder holder;
public CustomAdapterSmartwatch(Context context, ArrayList<String> variables) {
super(context,R.layout.row_smartwatch_resources,variables);
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
holder.cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.cTextView.setText(getItem(position));
holder.cTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.cTextView.isChecked()) {
holder.cTextView.setChecked(false);
} else {
holder.cTextView.setChecked(true);
}
}
});
return convertView;
}
}
Now i'm trying to figure out with using Holder but i heard that it's possible to use SparseBooleanArray. Can someone explain how to make it works?
EDIT 1
Ok, I have ListView which is controlled by CustomAdapter. That adapter contains only 1 item (CheckedTextView).
The problem is that after scrolling these checkedboxes don't remember their state.
I saw your answer with explanation but now after clicking any "CheckedTextView", the state of their checkbox doesn't change.
EDIT 2
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
holder.cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.cTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("MainActivity","Position = " + position);
CheckedTextView checkedText = (CheckedTextView) v;
checkedState.put(position, !checkedText.isChecked());
Log.d("MainActivity","State = " + checkedState.get(position));
}
});
holder.cTextView.setText(getItem(position));
holder.cTextView.setChecked(checkedState.get(position));
return convertView;
}
EDIT 3
class CustomAdapterSmartwatch extends ArrayAdapter<String> {
public SparseBooleanArray checkedState = new SparseBooleanArray();
private CheckedTextView cTextView;
public CustomAdapterSmartwatch(Context context, ArrayList<String> variables) {
super(context,R.layout.row_smartwatch_resources,variables);
}
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);
cTextView.setText(getItem(position));
cTextView.setChecked(checkedState.get(position));
cTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("MainActivity","Position = " + position);
CheckedTextView checkedText = (CheckedTextView) v;
checkedText.toggle();
if (checkedText.isChecked())
checkedState.put(position,true);
else
checkedState.delete(position);
Log.d("MainActivity","State = " + checkedState.get(position));
}
});
return convertView;
}
}
You have to keep a boolean flag for each CheckTextView. This can be an array, List, or SparseBooleanArray. The data structure you choose should be a field of your adapter:
class CustomAdapterSmartwatch extends ArrayAdapter<String> {
private SparseBooleanArray checkedState = new SparseBooleanArray();
// ...
}
You do not want to put it in the holder because the holder is retired only fr visible rows. On the other hand, you want to maintain the checked state for every row, visible or not.
Now, you set the stored checked state when the user clicks on a CheckedTextView:
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// ...
holder.cTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckedTextView checkedText = (CheckedTextView)v;
checkedState.put(position, checkedText.isChecked());
}
});
}
And you restore the checked state whenever you inflate a view or reuse one from a holder:
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// ...
holder.cTextView.setText(getItem(position));
holder.cTextView.setChecked(checkedState.get(position));
// ...
}
You can simply use the view in onClick() method itself.
holder.cTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(v instanceOf CheckedTextView) {
CheckedTextView c = (CheckedTextView) v;
c.setChecked(!c.isChecked());
}
}
});
Replace your code with following update:
class CustomAdapterSmartwatch extends ArrayAdapter<CustomAdapterSmartwatch.MyPojo> {
class MyPojo {
boolean checked;
String data;
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
static class ViewHolder {
protected CheckedTextView cTextView;
}
ViewHolder holder;
public CustomAdapterSmartwatch(Context context, ArrayList<MyPojo> variables) {
super(context, R.layout.row_smartwatch_resources, variables);
}
#Nullable
#Override
public MyPojo getItem(int position) {
return super.getItem(position);
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
holder.cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final MyPojo item = getItem(position);
holder.cTextView.setText(item.getData());
holder.cTextView.setChecked(item.isChecked());
holder.cTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean nextStatus = !item.isChecked();
item.setChecked(nextStatus);
holder.cTextView.setChecked(nextStatus);
}
});
return convertView;
}
}
I am using a custom Listview with Custom views as list elements, each list item is a separate Custom view. The problem which I am facing is , click event on button in 1st item of ListView is not getting fired when we click on it. After clicking on it if we click somewhere else in the screen the click event get fires. I am not able to find the solutions for it and I am struggling with it. Any help will be highly appreciated.
Updated with code: Here is the getview method
public override View GetView(int position, View convertView, ViewGroup parent)
{
if (position == 0)
{
convertView = this.context.LayoutInflater.Inflate(Resource.Layout.home_hero_container, null);
this.heroSection = convertView.FindViewById<FrameLayout>(Resource.Id.heroContainer);
this.setHeroCard();
}
else
{
convertView = (View)GetItem(position - 1);
}
return convertView;
}
GetItem returns CustomView. 1st item will be the hero layout, after that all the Customviews will be added to Convertview. Click event is not working on the 1st item after hero.
Update with my answer:
Instead of assigning Customview directly on to Convertview I inflated a FrameLayout and add Customview to FrameLayout. Now I don't have click issue.
try this it will work
public class ContactsAdapter extends BaseAdapter {
ArrayList<ContactInfo> mlist;
Context mcontext;
public BluetoothChatadpter(Context context,ArrayList<ChatInfo> mchtlist) {
mlist = mchtlist;
mcontext = context;
}
#Override
public int getCount() {
return mlist.size();
}
#Override
public Object getItem(int postion) {
return mlist.get(postion);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertview, ViewGroup viewgroup){
View view = null;
if(convertview == null){
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(R.layout.contactrow, null);
ContactHolder holder = new ContactHolder();
holder.txtviewfirstname = (TextView)view.findViewById(R.id.firstname);
holder.txtviewphone = (TextView)view.findViewById(R.id.phone);
holder.chkselected = (CheckBox)view.findViewById(R.id.check);
setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// to open the selected file in resp
// do your work here
}});
chkselected .setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Toast.makeText(context,// "checked is clicke="+pos, 12).show();
if (chkselected.isChecked())
{
// do your work here
} else {
// do your work here
}
}
});
view.setTag(holder);
}
else{
view = convertview;
}
ContactHolder holder2 = (ContactHolder) view.getTag();
holder2.txtviewfirstname.setText(list.get(position).firstname);
holder2.txtviewphone.setText(list.get(position).phonenumber);
holder2.chkselected.setChecked(list.get(position).selected);
return view;
}
}
public class ContactsAdapter extends BaseAdapter {
ArrayList<ContactInfo> mlist;
Context mcontext;
public BluetoothChatadpter(Context context,ArrayList<ChatInfo> mchtlist) {
mlist = mchtlist;
mcontext = context;
}
#Override
public int getCount() {
return mlist.size();
}
#Override
public Object getItem(int postion) {
return mlist.get(postion);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertview, ViewGroup viewgroup){
View view = null;
if(convertview == null){
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(R.layout.contactrow, null);
ContactHolder holder = new ContactHolder();
holder.txtviewfirstname = (TextView)view.findViewById(R.id.firstname);
holder.txtviewphone = (TextView)view.findViewById(R.id.phone);
holder.chkselected = (CheckBox)view.findViewById(R.id.check);
holder.chkselected.setOnCheckChangeListener(new CheckchangeListener() );
view.setTag(holder);
}
else{
view = convertview;
}
ContactHolder holder2 = (ContactHolder) view.getTag();
holder2.txtviewfirstname.setText(list.get(position).firstname);
holder2.txtviewphone.setText(list.get(position).phonenumber);
holder2.chkselected.setChecked(list.get(position).selected);
return view;
}
class CheckchangeListener implements OnCheckedChangeListener {
public CheckchangeListener() {
// TODO Auto-generated constructor stub
}
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
// do your work here
} else {
// do your work here
}
}
}
}
You can try to set onClick event in your Custom adapter and if you have time then check this tutorial for reference - http://androidforbeginners.blogspot.it/2010/03/clicking-buttons-in-listview-row.html
My gridview custom item is a image button.I want to change image button image when the image button is clicked.You can see below my custom adapter class getView method.But image button image does not change.
ImageButton btn1;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.myItem, null);
btn1 = (ImageButton) view.findViewById(R.id.btn1);
}
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
btn1.setImageResource(R.id.image1);
}
});
return view;
}
Try this way,hope this will help you to solve your problem.
public class CustomGridAdapter extends BaseAdapter {
private Context context;
private ArrayList<HashMap<String,Integer>> imagesList;
public CustomGridAdapter(Context context,ArrayList<HashMap<String,Integer>> imagesLis) {
this.context =context;
this.imagesList =imagesLis;
}
#Override
public int getCount() {
return imagesList.size();
}
#Override
public Object getItem(int position) {
return imagesList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.myItem, null);
holder.btn1 = (TextView) convertView.findViewById(R.id.btn1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btn1.setImageResource(imagesList.get(position).get("normalImage"));
holder.btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((ImageButton)v).setImageResource(imagesList.get(position).get("selectedImage"));
}
});
return convertView;
}
static class ViewHolder {
ImageButton btn1;
}
}
I have a activity in which there are some buttons and a listview.each rows of the listview has a delete button which i'm intend to delete the row whenever the user click the delete button.
i'm using a custom adapter so here is my getview method:
public override View GetView(int position, View convertView, ViewGroup parent)
{
convertView = menuActivity.LayoutInflater.Inflate(Resource.Layout.OrderItemLayout, null);
ImageButton btn = convertView.FindViewById<ImageButton>(Resource.Id.btn_del);
btn.Tag = position;
btn.Click += btn_Click;
return convertView;
}
void btn_Click(object sender, EventArgs e)
{
_lstOrder.RemoveAt((int)((sender as ImageButton)).Tag);
NotifyDataSetChanged();
}
but the problem is that when i click the delete button the listview doesn't refresh so the row that was deleted is still there but it will gone if i go back and then come to the activity again.
how can I solve this problem so after i delete a row the listview refresh?
thank you
Creating a common arraylist
ArrayList<GeterSetterClass> comn_arylist = new ArrayList<GeterSetterClass>();
Customized addapter setting
custdet_adapter adapter = new custdet_adapter(this,comn_arylist);
listview.setAdapter(adapter);
listview.invalidateViews();
Customized Adapter class
public static class custdet_adapter extends BaseAdapter {
private ArrayList<GeterSetterClass> cust_arrayList;
private LayoutInflater l_Inflater;
public custdet_adapter(Context context,
ArrayList<GeterSetterClass> list_details) {
cust_arrayList = list_details;
l_Inflater = LayoutInflater.from(context);
}
public int getCount() {
return cust_arrayList.size();
}
public Object getItem(int position) {
return cust_arrayList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = l_Inflater.inflate(R.layout.layoutname_struct,null);
holder = new ViewHolder();
holder.txt_custname = (TextView) convertView
.findViewById(R.id.textView1);
holder.txt_mobno = (TextView) convertView
.findViewById(R.id.textView2);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.txt_custname.setText(cust_arrayList.get(position).getName());
holder.txt_mobno.setText(cust_arrayList.get(position).getunitcd());
holder.txt_custname.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
comn_arylist.remove(position);
listview.invalidateViews();
}
});
return convertView;
}
class ViewHolder {
TextView txt_custname;
TextView txt_mobno;
}
}
I've that in my Adapter :
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if(convertView==null)
{
convertView = myInflater.inflate(R.layout.list, null);
holder = new ViewHolder();
holder.text01 = (TextView) convertView.findViewById(R.id.Text01);
((Button)convertView.findViewById(R.id.ListButonPlus)).setOnClickListener(this);
convertView.setTag(holder);
}else
{
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
And that :
public void onClick(View v)
{
Toast.makeText(v.getContext(), "pouette",1000).show();
}
And I try t get the position of the item who contains my button.
How Can I pass the position variable present in the getView method to my onClick Method?
I will have several button In my View (Item view)
Thank you
Ok I found, I pass my position to the ViewHolder
and I get the ViewHolder from the tag of the view or parrent view by a recursive function.
Is there any different method?
public static class ViewHolder
{
private TextView text01;
public int position;
}
public ViewHolder getViewHolder(View v)
{
if(v.getTag() == null)
{
return getViewHolder((View)v.getParent());
}
return (ViewHolder)v.getTag();
}
public void onClick(View v) {
ViewHolder vh = getViewHolder(v);
vh.position // Here I get position
}
I know this post is old, but this could help some others:
In the getView of my adapeter:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
ContactHolder holder = null;
final ContactRow ContactRow = ContactRowList.get(position);
if(row == null)
{
...
holder.delete = (ImageButton)row.findViewById(R.id.btn_contact_delete); // my button inside the item
holder.delete.setTag(position);
...
}
This is my listener for this button
holder.delete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
int position=(Integer)v.getTag();
((MainActivity)context).deleteContact(position,true); // call the delete function form the main activity
}
});
My holder
static class ContactHolder
{
...
ImageButton delete;
}