I am developing an application which uses list view with check-boxes,consider there are 10 items on list-view items,And by default in that check boxes are checked,Until now every thing is working fine for me here is my problem,When I uncheck any check-box in list-view whole list-view need to be refresh.
Nikhil just keep in mind that defining a custom adapter is one time practice, once you define and understand it properly then you can customize any views like ListView, GridView, Gallery, Spinner. So go through the below answer properly.
For defining ListView with CheckBox (or any View), you have to define your own custom adapter. For defining custom adapter, follow below steps:
Define a custom row file (which represents every items of your listview)
Define a adapter class and extends BaseAdapter.
Inflate the above row xml file inside the getView() method of this adapter class.
In your case,
1st step: (Define row xml file)
<RelativeLayout>
<TextView>
<CheckBox>
</RelativeLayout>
2nd & 3rd step: (Define custom adapter class)
public class MyListViewAdapter extends BaseAdapter
{
....
....
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
.......
.......
}
checkbox of a particular item have no info. about listView so to get its positiion , set id as position dthen get id in click listener .
second way is check/uncheck on listItemClick by set a ListItemClickListener instead of checkListener on checkBox , this is useful only when list item have just one clickable item , which is your checkbox .
Related
I have created a ListView and its custom Adapter. But due to some reason I am not allowed to get items from ViewHolder.
In my case ViewHolder has only one variable and that is of LinearLayout. LinearLayout contains the other child views(which is decided and created at run time). When I use ViewHolder and set the tag of holder object, on scroll I am getting the same views again.
Is there any other way to stop adapter to create views while scrolling ?
Or, while scrolling how can we clear the references of views ?
I have find this but I don't think this will work.
setRecyclerListener(new RecyclerListener() {
#Override
public void onMovedToScrapHeap(View view) {
//from here can we use this to clean the memory
}
});
ViewHolder is meant as a holder to contain ids of listitem layout.
It is optimization to avoid calling findViewById everytime new listitem is created for display by going through data container e.g. arrayList.
You cannot stop adapter in between creating item views.
Only items on display are created.
convertView acts as object being recycled for creating subsequent view while scrolling up/down.
You will not be able to use view holder for the purpose you are trying to achieve.
Sample usage as below.
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
ViewHolder viewHolder = null;
if(convertView == null)
{
v = LayoutInflater.from(StockDetailsActivity.this).inflate(R.layout.stock_details_list_item, null);
viewHolder = new ViewHolder();
viewHolder.model_name_tv = (TextView) v.findViewById(R.id.model_name);
viewHolder.model_type_iv = (ImageView) v.findViewById(R.id.model_type_icon);
viewHolder.model_type_tv = (TextView) v.findViewById(R.id.model_type_desc);
viewHolder.model_stock_tv = (TextView) v.findViewById(R.id.model_stock_value);
v.setTag(viewHolder);
}
else
viewHolder = (ViewHolder) v.getTag();
stockCursor.moveToPosition(position);
// logic to update data to views as appropriate goes here
return v;
}
public class ViewHolder{
public TextView model_name_tv;
public ImageView model_type_iv;
public TextView model_type_tv;
public TextView model_stock_tv;
}
I have a ListView where each row item has EditText and CheckBox elements. You can see the sample image below.
What I intend to do is
I want to implement both OnItemClickListener (for ListView) and OnClickListener (for EditText and CheckBox) i.e. I want Task A to be done on clicking the ListView items (outside EditText and CheckBox) and I also want to do individual tasks on clicking EditText and CheckBox respectively.
My Problem
If no attribute is set on ListView, EditText or CheckBox to control the focus, then the default behaviour is that ListView row items won't listen to item click, but EditText and CheckBox are getting the focus
On playing around with these attributes and there values (eg - )
// to ListView
android:descendantFocusability="blocksDescendants"
// to EditText and CheckBox
android:focusable="false"
android:focusableInTouchMode="true"
Listeners are working either for ListView or for the EditText. CheckBox click listener seems to work in all cases (strange). I am new to this and any kind of help would be appreciated. I cannot post the source right now, for that please bear with me. Any solution, suggestion or explanation would do a great help.
I am glad that I happen to solve this problem. What I wanted to do was (let me clear it out again) I wanted the EditText to be focusable and additionally I should be able to click on each row of the ListView to perform some specific task. Well we won't be needing these attributes:
android:focusable=""
android:focusableInTouchMode=""
android:descendantFocusability=""
What simple needed to be done is
In you custom ListAdapter class implement OnClickListener for each items (say EditText, CheckBox, etc.) and implement OnClickListener of rootView (i.e. for ListView row item) too.
For Example:
public class CustomListAdapter extends ArrayAdapter<YOUR_OBJECT> {
Context context;
ArrayList<YOUR_OBJECT> itemlist = new ArrayList<YOUR_OBJECT>();
Integer resourceID;
ViewHolder holder;
public ServicesListAdapter(Context context, int resourceId, ArrayList<YOUR_OBJECT> itemlist) {
super(context, resourceId, itemlist);
this.itemlist.addAll(itemlist);
this.context = context;
this.resourceID = resourceId;
}
public class ViewHolder {
TextView name;
EditText editText;
CheckBox checkBox;
}
public View getView(final int position, View rootView, ViewGroup parent) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (rootView == null) {
rootView = mInflater.inflate(resourceID, null);
holder = new ViewHolder();
holder.name = (TextView) rootView.findViewById(R.id.name);
holder.editText = (EditText) rootView.findViewById(R.id.port);
holder.checkBox = (CheckBox) rootView.findViewById(R.id.check_box);
// Add Listeners for EditText and CheckBox here
rootView.setTag(holder);
} else {
holder = (ViewHolder) rootView.getTag();
}
// Click Listener for the ListView row item
rootView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "Clicked" + position, Toast.LENGTH_SHORT).show();
}
});
// Do what rest you need to do with your ViewHolder
}
}
I have a ListView whose rows comprise of some TextViews and a button. Upon a user pressing the button, I want to remove that parent that houses the button from the ListView. How do I access my custom ArrayAdapter's fields from within a nested method (onClickListener) though? All I have to work with is the View v. Am I suppose to call v.getParent() multiple times, or is there a better way to do it?
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Action item = this.getItem(position);
if (convertView == null) {
convertView = inflater.inflate(R.layout.action_holder_layout,
parent, false);
holder = new ViewHolder();
holder.title = (TextView) convertView
.findViewById(R.id.action_holder_title);
holder.finishBtn = (Button) convertView
.findViewById(R.id.finish_action_button);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
holder.title.setText(item.getActionName());
holder.finishBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//REMOVE THE ACTION FROM THE ADAPTER'S ARRAYLIST
}
});
return convertView;
}
static class ViewHolder {
private TextView title;
private Button finishBtn;
}
Make item final:
final Action item = this.getItem(position);
and you can access it from onClick. Not a beautiful solution IMO, but will work:
remove(item);
If you need access to your ListView (and consequently its Adapter), a better way than using getParent().getParent()... would be to use the setTag() method on your View. Since you are already using it to insert a ViewHolder as a Tag of your view, why not add another field
ListView parentListView;
to your ViewHolder and retrieve it later in the onClick?
You could also set the ListView directly as a tag on your button.
You could also just access the adapter or other methods and fields directly from your onClick code since you're using an anonymous class.
I have a custom listview with item layout having a checkbox at the left and 4 textviews much like astrid task manager.
What I intend to do is that on clicking the checkbox, the textviews have to update their values. At first, my problem was that on checking a checkbox at position 1 would check the checkbox at the end or somewhere else while scrolling. While searching for a solution, I came to know about recycling of view in listview. I applied those concepts like viewholder and right now I am able to maintain the state of checkbox. But, on checkbox click, I change the textviews and the change is not persisting, meaning any random tv also shows the same change.
I have applied a checkbox onclicklistener in my adapter. Any ideas how to achieve it?
You will want to persist the state of the item in your item data rather than in the view holder. The view holder is just a convenience to the view, which at various times will display many different items, assuming you recycle the views. During the data binding, you will want to bind all state necessary for displaying your item to avoid having random data appearing in another list item's view.
public class MyListAdapter extends BaseAdapter {
// ....
#Override
View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = inflate(R.layout.my_list_item_layout, parent, false);
// View holder just prevents having to look up these values
// every time the view is reused.
MyViewHolder holder = new MyViewHolder();
holder.checkbox = (CheckBox) view.findViewById(R.id.check_box);
holder.textview = (TextView) view.findViewById(R.id.text_view);
view.setTag(holder);
}
final MyViewHolder holder = (MyViewHolder) view.getTag();
final MyData data = (MyData) getItem(position);
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
data.savedCheckboxState = isChecked;
// now tell the view to rebind the data
notifyDataSetChanged();
}
});
holder.checkbox.setChecked(data.savedCheckboxState);
holder.textview.setText(String.valueOf(data.savedCheckboxState));
return view;
}
private static class MyViewHolder {
CheckBox checkbox;
TextView textview;
}
}
You can refer to my full code here, what you can do is,store check box state in a boolean array then you wont face this issue.....
Android checkbox multiselected issue
Good time!
My Android app has so feature that I use ListView in the one of the page of TabHost without layout for ListView. Like that:
ListView lv = new ListView(this);
lv.setAdapter(myAdapter);
So I'd like to change some row's properties like text size in the row. So, how can I get access to the properties of the explicit row of ListView to change text size, for example?
Use BaseAdapter and modify font size in getView call.
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.custom_layout, null);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Change text size
holder.text.setTextAppearance(context,R.style.customStyle);
return convertView;
}
static class ViewHolder {
TextView text;
}
And you can use position variable in getView call to change specific row. Hope this help!!!