Custom ListView with checkbox changes position while scrolling in android - android

I am new to android and working on web view demo, I have implemented it. But the problem with me is when I check any check box and scrolling the list view , The checked position changes.
I have tried some links from stack over flow with no luck, SO I request someone can help me to resolve this issue, please
My adapter is as below,
adapter
public class FilterAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<String> mData = new ArrayList<String>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public FilterAdapter(Context context) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
public int getCount() {
return mData.size();
}
public String getItem(int position) {
return mData.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.raw_filter, null);
holder.textView = (TextView) convertView.findViewById(R.id.tv_filter);
holder.chk_filter = (CheckBox) convertView.findViewById(R.id.chk_filter);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.raw_headr, null);
holder.textView = (TextView) convertView.findViewById(R.id.tv_hdr);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
class ViewHolder {
public TextView textView;
public CheckBox chk_filter;
}

add clickListener in your getView() method, it will fix your set checked box in the entire listView like this:
checkBoxSelected.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
instrumentClickListener.onCheckBoxClick(instrumentDTO, checkBoxSelected.isChecked(), position);
Log.d(TAG, "checked instruments is check: " + checkBoxSelected.isChecked() + " \ninstrument: " + position);
}
});

Related

ListView Header implementation

I have an Adapter class that implements ListView with headers.
//Adapter Class
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private static final int TYPE_GRAY_SEPARATOR = 2;
private TreeSet<Integer> mGraySeparatorsSet = new TreeSet<Integer>();
private ArrayList<ContentWrapper> mData = new ArrayList<ContentWrapper>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter(Context context)
{
mInflater = LayoutInflater.from(context);
}
public void addItem(ContentWrapper value) {
mData.add(value);
notifyDataSetChanged();
}
public void addSeparatorItem(ContentWrapper value) {
mData.add(value);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
public ContentWrapper getItem(int position) {
return mData.get(position);
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
public int getCount() {
return mData.size();
}
public long getItemId(int position) {
Log.v("getItemId Position", ""+position);
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.white, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.black, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
} holder.textView.setText(mData.get(position).getItem());
if (type == TYPE_ITEM) {
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder x = new AlertDialog.Builder(getActivity());
x.setIcon(R.drawable.ic_launcher)
.setTitle(mData.get(position).getItem())
.setMessage(mData.get(position).getItemDescription())
.setCancelable(true)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg,
int arg1) {
}
});
AlertDialog a = x.create();
a.show();
}
return null;
}
});
} else {
holder.textView.setOnClickListener(null);
}
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
In this I truly understand the implementation of getView method (ViewHolder,convertView,etc).
The above code runs smoothy but I do not understand that why we are using the methods
addItem
addSeparatorItem
getItemViewType
getViewTypeCount
getCount
getItemId
Can Anyone explain me the scenario clearly !
Thanks in advance..
These all are the call back methods. You can have the clear definition of these methods in below mentioned link.
http://developer.android.com/reference/android/widget/BaseAdapter.html
Let me give you an example of getItem()
Whenever new listview row is created, adapte willl get item details from this call back method.
Similarly whenever list is created, getCount() is called.
Suppose you have 12 items in listview. But you pass 10 in getCount(). it will show only ten items in list view.

Slider menu View issue

I have implemented a ListView with headers from sqlite in a separate project which is like this:
When I implemented onClick() in a position of Slider Menu, It is displayed in Slider Menu rather than in the background View
onCreate() code snippet
if(position == 3)
{
mAdapter = new MyCustomAdapter();
mAdapter.addSeparatorItem(q.get(0).getA_name());
mAdapter.addItem(q.get(0).getAS_name());
for (int i = 1; i < 460; i++) {
if (!(q.get(i).getA_name().trim().equals(q.get(i-1).getA_name().trim()))) {
mAdapter.addSeparatorItem(q.get(i).getA_name());
c++;
}
mAdapter.addItem(q.get(i).getAS_name());
}
setListAdapter(mAdapter);
toggleMenu(arg1);
}
Adapter class
//Adapter Class
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<String> mData = new ArrayList<String>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
public int getCount() {
return mData.size();
}
public String getItem(int position) {
return mData.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.activity_main1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder nointernetconnection = new AlertDialog.Builder(
temp);
nointernetconnection
.setIcon(R.drawable.ic_launcher)
.setTitle(q.get(position-1).getAS_name())
.setMessage(q.get(position-1).getDesc_art())
.setCancelable(true)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg,
int arg1) {
}
});
AlertDialog a = nointernetconnection.create();
a.show();
}
});
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.activity_main2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
So, MyCustomAdapter class is dispalying the list in slider menu. But this list should not be displayed in slider menu rather it should be displayed behind slider menu. I hope the problem is clear. Please tell my mistake.
The setlistadapter method you are calling is being called for the slider rather than your list view on the activity/fragment in the background.
do a ListView list = (ListView) getactivity().findViewById(R.id.yourListViewName) or something like this, and then set the list adapter.

Android listview with checkbox make selected based on input from edittext

I am trying to implement my own custom listview with two separate items, a header for the section and then checkable items under each header.
What I want to be able to do is type text into the edittext and then loop over the list of checkable elements and find which one matches the input and set the checkbox of that row.
I am using a fragmentpageradapter also to manage the two sliding fragments.
So basically I need to know what the best way would be to be able to change the checked state of the list item, but not only from the onitemcheckedlistener, but also from just me typing something into a text box.
public class RetrieveListAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<ScanInfo> list = new ArrayList<ScanInfo>();
private static LayoutInflater inflater = null;
private TreeSet mSeparatorsSet = new TreeSet();
public RetrieveListAdapter(Activity a) {
activity = a;
//list = si;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return list.size();
}
public void addItem(final ScanInfo item) {
list.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final ScanInfo item) {
list.add(item);
mSeparatorsSet.add(list.size() - 1);
// save separator position
//mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
public ScanInfo getItem(int position) {
return list.get(position);
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? 0 : 1;
}
#Override
public int getViewTypeCount() {
return 2;
}
public long getItemId(int position) {
return position;
}
public void checkItem(String tracking) {
for (int i = 0; i < list.size(); i++) {
if (getItemViewType(i) == 1) {
if (tracking.equals(getItem(i).getTracking())) {
RetrievePackage.checkedItems[i] = true;
}
}
}
}
public View getView(final int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case 0:
convertView = inflater.inflate(R.layout.single_list_item, null);
holder.textView = (TextView) convertView.findViewById(R.id.text1);
holder.textView.setText(list.get(position).getLocation());
break;
case 1:
convertView = inflater.inflate(R.layout.retrieve_package_item, null);
holder.textView = (TextView) convertView.findViewById(R.id.trackingListItem);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.checkBox1);
if (list.get(position).getShortDisplayTracking().equals("")) {
holder.textView.setText(list.get(position).getTracking() + " [" + list.get(position).getCarrier() + "]");
} else {
holder.textView.setText(list.get(position).getShortDisplayTracking() + " [" + list.get(position).getCarrier() + "]");
}
holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
RetrievePackage.checkedItems[position] = isChecked;
}
});
holder.checkBox.setChecked(RetrievePackage.checkedItems[position]);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
switch (type) {
case 0:
holder.textView.setText(list.get(position).getLocation());
break;
case 1:
if (list.get(position).getShortDisplayTracking().equals("")) {
holder.textView.setText(list.get(position).getTracking() + " [" + list.get(position).getCarrier() + "]");
} else {
holder.textView.setText(list.get(position).getShortDisplayTracking() + " [" + list.get(position).getCarrier() + "]");
}
break;
}
return convertView;
}
public static class ViewHolder {
public TextView textView;
public CheckBox checkBox;
}
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View V = inflater.inflate(R.layout.retrieve_packages, null);
submitRetrieve = (Button) V.findViewById(R.id.retrievePackages);
tracking = (EditText) V.findViewById(R.id.scanTrackingRet);
lv = (ListView) V.findViewById(R.id.retrieveList);
submitRetrieve.setEnabled(false);
activity = getActivity();
context = getActivity().getApplicationContext();
adapter = new RetrieveListAdapter(activity);
return V;
}
private static void initializePackageScan() {
checkedItems = new boolean[adapter.getCount()];
tracking.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_NEXT || actionId == EditorInfo.IME_ACTION_DONE) {
String number = tracking.getText().toString();
adapter.checkItem(number);
}
return true;
}
});
}
It looks like you have the right idea; set the item to "checked" and then call notifyDataSetChanged(), just like if you had added an item.

CheckBox Issue in List View With Different Layout For Rows

I tried make list view has TextView and CheckBox. It is worked fine but when select CheckBox in row another CheckBox in another row selected too.
Example: if I checked first row and scroll down I found another row selected too.
This my Adapter Code
public class ReadersrListAdapter extends BaseAdapter{
private static final int TYPE_SEPARATOR = 0;
private static final int TYPE_ITEM = 1;
private static final int TYPE_MAX_COUNT = 2;
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private LayoutInflater mInflater=null;
public ReadersrListAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
mInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
return !data.get(position).get(UtiliShare.KEY_TITLE).startsWith("-");
}
#Override
public int getItemViewType(int position) {
return data.get(position).get(UtiliShare.KEY_TITLE).startsWith("-") ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
ViewHolder2 holder2 = null;
int type = getItemViewType(position);
if (convertView == null) {
//holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.reader_list_item, null);
holder.textView = (TextView)convertView.findViewById(R.id.readerTitle);
holder.textView.setTypeface(UtiliShare.getTf());
convertView.setTag(holder);
break;
case TYPE_SEPARATOR:
holder2 = new ViewHolder2();
convertView = mInflater.inflate(R.layout.reader_list_devider, null);
holder2.textView = (TextView)convertView.findViewById(R.id.readerTitle);
holder2.textView.setTypeface(UtiliShare.getTf());
convertView.setTag(holder2);
break;
}
//convertView.setTag(holder);
} else {
if(type==TYPE_ITEM) holder = (ViewHolder)convertView.getTag();
else holder2 = (ViewHolder2)convertView.getTag();
}
HashMap<String, String> curdata = new HashMap<String, String>();
curdata = data.get(position);
String txt = curdata.get(UtiliShare.KEY_TITLE);
if(type == TYPE_SEPARATOR){
txt = txt.replace("-", "");
holder2.textView.setText(txt);
}else{
//if(position <= 100) System.out.println("getView " + position + " " + convertView + " type = " + type);
holder.star = (CheckBox) convertView.findViewById(R.id.btn_Fav);
holder.star.setOnCheckedChangeListener(((ReadersListActivity) this.activity).mStarCheckedChanceChangeListener);
holder.textView.setText(txt);
}
//holder.textView.setText(txt);
return convertView;
}
private static class ViewHolder {
public CheckBox star;
public TextView textView;
}
private static class ViewHolder2 {
public TextView textView;
}
}
And this OnCheckedChangeListener in activity
public OnCheckedChangeListener mStarCheckedChanceChangeListener = new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Cyril: Not implemented yet!
final int position = list.getPositionForView(buttonView);
Toast.makeText(ReadersListActivity.this, ""+position, Toast.LENGTH_SHORT).show();
}
};
How Can I fix this???
Thanks.
As you may know the layouts are reused as you scroll, so you need to track whether each row should be checked yourself. Let's add a new member to your Adapter:
private SparseBooleanArray checked = new SparseBooleanArray();
And a new method:
public void toggleCheck(int position) {
boolean state = expanded.get(position, false);
expanded.put(!state);
}
Now call our new method in onCheckedChanged():
final int position = list.getPositionForView(buttonView);
adapter.toggleCheck(position);
Lastly let's tweak getView() to change the checked state (and a few other things):
// Don't create a new HashMap that you'll never use
//HashMap<String, String> curdata = new HashMap<String, String>();
HashMap<String, String> curdata = data.get(position);
String txt = curdata.get(UtiliShare.KEY_TITLE);
if(type == TYPE_SEPARATOR){
txt = txt.replace("-", "");
holder2.textView.setText(txt);
}else{
//if(position <= 100) System.out.println("getView " + position + " " + convertView + " type = " + type);
// These two lines should be in `if(convertView == null)` with the others
holder.star = (CheckBox) convertView.findViewById(R.id.btn_Fav);
holder.star.setOnCheckedChangeListener(((ReadersListActivity) this.activity).mStarCheckedChanceChangeListener);
// Set the appropriate values
holder.textView.setText(txt);
holder.star.setChecked(expanded.get(position, false));
}

Android Image not loaded in Custom Adapter

I am having list of my Facebook friends and i created a list View that's having separator as months from Jan to Dec.
I am able list my friends details, My problem is that i am able to show their Name and birthday date if i try load their "PICTURES" i can't do it..
It showing me the icon set as Background in XML.
Even the URL for the image to be load is get printed in Log, but i cant get the image..
Here is my code
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mData = new ArrayList<Category>();
}
public void addItem(final Category item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final Category item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Category getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
Category category = mData.get(position);
holder = new ViewHolder();
if (convertView == null) {
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
holder.textView1 = (TextView)convertView.findViewById(R.id.text1);
holder.icon = (ImageView) convertView.findViewById(R.id.friend_photo);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
if(type==TYPE_ITEM){
holder.textView = (TextView)convertView.findViewById(R.id.text);
holder.textView1 = (TextView)convertView.findViewById(R.id.text1);
holder.icon = (ImageView) convertView.findViewById(R.id.friend_photo);
holder = (ViewHolder)convertView.getTag();
}else{
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
holder = (ViewHolder)convertView.getTag();
}
}
if(type==TYPE_SEPARATOR){
holder.textView.setText(mData.get(position).dealTitle);
}else{
holder.textView.setText(mData.get(position).dealTitle);
holder.textView1.setText(mData.get(position).dealDesc);
holder.icon.setTag(mData.get(position).picture);
}
return convertView;
}
}
You need to set your ImageView's bitmap using one of the setImageFoo() calls.
setImageResource()
setImageBitmap()
setImageDrawable()
I'm not sure what type of object mData.get(position).picture is but
holder.icon.setTag(mData.get(position).picture);
isn't loading the picture. That's just setting some data on the View.
You need to use one of the setImage() methods of ImageView.
Your code looks fine, there might be a problem with the xml/layout file.
As you are loading two textViews and a ImageView from the xml for each item, it is important to know how the layout is organised to show all the added views in it.
Please post the layout files so that, one can suggest if there is any problem.

Categories

Resources