dynamically built checkboxes are being reset on scroll - java

I have a list view with adaptor where I create some checkboxes, in the adaptor I add an on change listener to change the value in my realm database. Just above this I am getting the current values stored in the database to persist the previous values.
This seems to work rather well, but when you scroll the items that you have checked will become unchecked when past the screen.
As seen here:
The code that generates this:
Adaptor.java
if(check != null){
viewHolder.checkbox.setText(check.title);
if (check.completed == 1) {
viewHolder.checkbox.setChecked(true);
} else {
viewHolder.checkbox.setChecked(false);
}
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
check.setCompleted();
} else {
check.setNotCompleted();
}
}
});
}
Fragment.java
final ChecksAdaptor checksAdaptor = new ChecksAdaptor(device.checks(), getContext());
listView.setAdapter(checksAdaptor);
Full Adaptor
public class ChecksAdaptor extends ArrayAdapter<DeviceCheck> {
public RealmResults<DeviceCheck> checks;
Context mContext;
// View lookup cache
private static class ViewHolder {
CheckBox checkbox;
}
public ChecksAdaptor(RealmResults<DeviceCheck> checks, Context context) {
super(context, R.layout.check_row_item, checks);
this.checks = checks;
this.mContext=context;
}
private int lastPosition = -1;
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// Get the data item for this position
final DeviceCheck check = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.check_row_item, parent, false);
viewHolder.checkbox = convertView.findViewById(R.id.checkbox);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
lastPosition = position;
if(check != null){
viewHolder.checkbox.setText(check.title);
if (check.completed == 1) {
viewHolder.checkbox.setChecked(true);
} else {
viewHolder.checkbox.setChecked(false);
}
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
check.setCompleted();
} else {
check.setNotCompleted();
}
}
});
}
// Return the completed view to render on screen
return convertView;
}
}

As suggested by mTak
viewHolder.checkbox.setOnCheckedChangeListener(null)

Related

listview toggle switch works only last row

i'm facing a problem which is, when i toggle switch it's works for only last item of listview. It doesn't matter which switch i toggle. I research other asked questions but i couldn't figure it out.
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.row, parent, false);
String allData = getItem(position);
final Switch status = (Switch) customView.findViewById(R.id.switchStatus);
status.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
Toast.makeText(getContext(),"selectid",Toast.LENGTH_LONG).show();
}
});
return customView;
}
You can see my adapter activiy in here.
public class adapter_test extends ArrayAdapter<String> {
public adapter_allservicerecords(Context context, String[] data){
super(context, R.layout.row, data);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.row, parent, false);
String allData = getItem(position);
try {
if(!all_data.isEmpty()) {
JSONObject jsonRowData = new JSONObject(all_data);
try {
text.setText(jsonRowData.getString("TITLE"));
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
Log.e("FAILED", "Json parsing error: " + e.getMessage());
}
return customView;
}
}
The solution to the problem is you have to instead of making your data as a String, you should instead change it into something that would represent each row.
For example you can set this class to represent your row:
class Item {
String data;
boolean toggled;
public Item(String data) {
this.data = data;
}
public void setToggled(boolean toggle) {
toggled = toggle;
}
}
Your data source now must not be Strings, so you should instead have your List as List and you can easily add your strings to the list by passing on new Item("THE STRING DATA HERE"); when adding data to the list.
So instead of
String allData = getItem(position);
you would use
Item item = getItem(position);
then on the getView would look something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.row, parent, false);
Item item = getItem(position);
final Switch status = (Switch) customView.findViewById(R.id.switchStatus);
status.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
// here we change the value of the item which is referring to the specific index in the array returned by getItems()
item.setToggled(isChecked);
Toast.makeText(getContext(),"selectid",Toast.LENGTH_LONG).show();
}
});
// here we get what the latest value of the switch is
status.setChecked(item.toggled);
return customView;
}
Make sure you also change your data source into a data structure/list that represents somewhat like List or anything similar on which you decide to use.
BONUS TIP:
It is recommended to use a ViewHolder to hold your View and for efficient recycling of instances.
class ViewHolder {
Switch statusSwitch;
View customView;
}
Then to use that in the getView() part you can easily.
You actually don't have to create a new instance of the view since convertView or the second parameter of the method represents the view that could be reused or instantiated if null.
Heterogeneous lists can specify their number of view types, so that this View is always of the right type, so you are recommended to use that.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
ViewHolder holder = null;
Item item = getItem(position);
if (convertView == null) { // instantiate if not yet instantiated
convertView = inflater.inflate(R.layout.supplies_list_item, null);
holder.statusSwitch = (Switch) convertView.findViewById(R.id.switchStatus);
}
else {
holder = (ViewHolder) convertView.getTag();
}
// you could set the values/ listeners here
holder.statusSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
item.setToggled(isChecked);
Toast.makeText(getContext(),"selectid",Toast.LENGTH_LONG).show();
}
});
holder.statusSwitch.setChecked(item.toggled);
return convertView;
}

All values in RecycleView and ListView are changing while I'm using dialog

I have a dialog and I want to add a recyclerView or listView and I know that I have to use a List to control items in each row. Now when I want to change a value of a checkbox or a radioButton all the data in List are changing. I used Log and I got that all the booleans data changed at the same time. I moved all items to an activity but the problem still remains. It seems there is a link between the arrayList data.
Also I changed my codes and used SwitchCompat but all Boolean data in mDataSet are changing when I want to change just one of them.
public class AdapterSetOnOffTime extends RecyclerView.Adapter<AdapterSetOnOffTime.ViewHolder> {
private Context mContext;
private ArrayList<StructSetOnOffTime> mDataSet;
private View mView;
public AdapterSetOnOffTime(Context context, ArrayList<StructSetOnOffTime> dataSet) {
mContext = context;
mDataSet = dataSet;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int id = R.layout.layout_list_settime_items;
mView = LayoutInflater.from(mContext).inflate(id, parent, false);
return new ViewHolder(mView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.mSwitch.setChecked(mDataSet.get(position).setOnOffValue);
holder.mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if(isChecked){
mDataSet.get(position).setOnOffValue = true;
}else{
mDataSet.get(position).setOnOffValue = false;
}
}
});
}
#Override
public int getItemCount() {
return mDataSet.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextTitle;
public TextView mTextValue;
public ImageButton mBtn;
public SwitchCompat mSwitch;
public ViewHolder(View itemView) {
super(itemView);
mTextTitle = (TextView) itemView.findViewById(R.id.txtSetTime);
mTextValue = (TextView) itemView.findViewById(R.id.txtOnOffStatus);
mBtn = (ImageButton) itemView.findViewById(R.id.btnSetTime);
mSwitch = (SwitchCompat) itemView.findViewById(R.id.swPrefSwitch);
}
}
}
Update answer
After wasting a day I recognized that I made a little mistake to fill ArrayList and I'm going to share it.
Previous method of fill adapter:
StructSetOnOffTime item = new StructSetOnOffTime();
ArrayList<StructSetOnOffTime> arrayList = new ArrayList<>();
for(int i = 0; i < 9; i++){
item.setTimeValue = null;
item.setOnOffValue = false;
arrayList.add(item);
}
As #Anatoli said, I had a problem in this section and I solved it by changing the upper method to this one:
ArrayList<StructSetOnOffTime> arrayList = new ArrayList<>();
for(int i = 0; i < 9; i++){
StructSetOnOffTime item = new StructSetOnOffTime();
item.setTimeValue = null;
item.setOnOffValue = false;
arrayList.add(item);
}
You set to radOn and radOff same OnCheckedChangeListener and checks in listener if it was set to true. Why you don't make 2 listeners?
CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDataSet.get(position).onOffStatus = true;
// update adapter
notifyDataSetChanged();
}
}
};
holder.radOn.setOnCheckedChangeListener(listener);
CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDataSet.get(position).onOffStatus = false;
// update adapter
notifyDataSetChanged();
}
}
};
holder.radOff.setOnCheckedChangeListener(listener);
looks much simpler
calling of
holder.radOn.setChecked(holder.radOn == buttonView);
holder.radOff.setChecked(holder.radOff == buttonView);
triggers the listeners. To update values in list, just call adapter.notifyDataSetChanged();
UPDATE
For each new item in list you must initialize new Holder
RecyclerView
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
// Inflate the custom layout
View itemView = LayoutInflater.from(parent.getContext())
.inflate(layoutId, parent, false);
return new Holder(itemView, viewType);
}
ArayList
#NonNull
#Override
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
Holder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
viewHolder = new Holder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (Holder) convertView.getTag();
}
Item item = getItem(position);
fill(item, position);
return convertView;
}
When ever you set the check state of your view(from your code also if view didn't get destroyed) your check listener will get called so you need to manually maintain the state. It will work for all radiobutton, checkbox etc.
holder.mSwitch.setOnCheckedChangeListener(null);
holder.mSwitch.setChecked(mDataSet.get(position).setOnOffValue);
holder.mSwitch.setOnClickListener(new OnClickListener(){
//holder.mSwitch.setCheck(!mDataSet.get(position).setOnOffValue);
mDataSet.get(position).setOnOffValue = !mDataSet.get(position).setOnOffValue;
});

How to get checkbox value from list view ... which is connected to Sqlite data base?

Help to get mobile number and get it in a edittext... i am gone...
help me to get the check box value and take the mobile number to some where. to send sms using Sms manager
Class name adapter... which contains row of the list view.
List list=new ArrayList();
Context context;
public Adapter(Context context, int resource)
{
super(context, resource);
this.context=context;
}
public void add(Product object) {
list.add(object);
super.add(object);
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row=convertView;
final Holder holder;
if (row==null){
LayoutInflater layoutInflater= (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row=layoutInflater.inflate(R.layout.rowlist,parent,false);
holder =new Holder();
holder.id=(TextView)row.findViewById(R.id.tsnoo);
holder.name=(TextView)row.findViewById(R.id.tname);
holder.birth=(TextView)row.findViewById(R.id.tbirth);
holder.email=(TextView)row.findViewById(R.id.temail);
holder.req=(TextView)row.findViewById(R.id.treq);
holder.mobile=(TextView)row.findViewById(R.id.tmobile);
holder.check=(CheckBox)row.findViewById(R.id.tcheck);
row.setTag(holder);
}else {
holder= (Holder) row.getTag();
}
Product product= (Product) getItem(position);
holder.id.setText(Integer.toString(product.getId()));
holder.name.setText(product.getName().toString());
holder.birth.setText(product.getBirth().toString());
holder.email.setText(product.getEmail().toString());
holder.req.setText(product.getReq().toString());
holder.mobile.setText(product.getMobile().toString());
holder.check.setChecked(false);
holder .check.setChecked(itemChecked[position]);
holder.check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
itemChecked[position]=isChecked;
}
});
return row;
}
private boolean[] itemChecked;
private void createCheckedHolder() {
itemChecked = new boolean[getCount()];
}
static class Holder{
TextView name,birth,email,req,mobile,id;
CheckBox check;
}
}
I have used AsyncTask to to Synchronize it...
Here i made my answer my self... with a simple meathod...
holder.check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(holder.check.isChecked()){
View get=null;
for (int i=0;i<getCount();i++) {
if (position == i) {
get = getView(i, get, listView1);
holder.mobile = (TextView) get.findViewById(R.id.tmobile);
String last = holder.mobile.getText().toString();
String[] data;
Toast.makeText(getContext(), last, Toast.LENGTH_SHORT).show();
}
}
}
else
{
}
}
});

All checkbox in listview is not getting visible from invisible state when button is clicked from Mainactivity

I am new to android. I am struggling with the checkbox in listview. By default I made my checkbox in listview to be in INVISIBLE mode when the button is clicked from MainActivity. I want to all checkbox in listview to be in VISIBLE mode but when I am clicking the button check box is VISIBLE in only one list row in all other rows. Still the check box is in INVISIBLE mode.
FavouriteListAdapter
public class FavouriteListAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
ArrayList<FavouritesArray> mArrFavourites;
ViewHolder viewHolder;
String favId;
//Make checkbox to visible in all rows in listview
public void setcheckbox() {
viewHolder.favCheckbox.setVisibility(View.VISIBLE);
}
public static class ViewHolder {
public TextView favName;
public TextView favUrl;
public TextView favAddress;
public CheckBox favCheckbox;
}
public FavouriteListAdapter(Context context, ArrayList<FavouritesArray> lArrFavourites) {
mContext = context;
mArrFavourites = lArrFavourites;
}
#Override
public int getCount() {
if (mArrFavourites == null) {
return 0;
}
return mArrFavourites.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.favouritelistadapter, parent, false);
viewHolder.favName = (TextView) convertView.findViewById(R.id.fav_name);
viewHolder.favUrl = (TextView) convertView.findViewById(R.id.fav_url);
viewHolder.favAddress = (TextView) convertView.findViewById(R.id.fav_address);
viewHolder.favCheckbox = (CheckBox) convertView.findViewById(R.id.fav_checkbox);
viewHolder.favCheckbox .setVisibility(View.INVISIBLE);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final FavouritesArray chooseService = mArrFavourites.get(position);
viewHolder.favName.setText(chooseService.getFavouritename());
viewHolder.favAddress.setText(chooseService.getFavouritelocation());
viewHolder.favCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
favId = chooseService.getFavouritename();
((MainActivity) mContext).check(favId);
}
}
});
return convertView;
}}
I think you need boolean varibale showCheckBox and check it state in method getView.
Look at this sample:
private boolean showCheckBox = false;
public void showChecBox(boolean show) {
showCheckBox = show;
}
public View getView(final int position, View convertView, ViewGroup parent) {
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.favouritelistadapter, parent, false);
viewHolder.favName = (TextView) convertView.findViewById(R.id.fav_name);
viewHolder.favUrl = (TextView) convertView.findViewById(R.id.fav_url);
viewHolder.favAddress = (TextView) convertView.findViewById(R.id.fav_address);
viewHolder.favCheckbox = (CheckBox) convertView.findViewById(R.id.fav_checkbox);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final FavouritesArray chooseService = mArrFavourites.get(position);
viewHolder.favName.setText(chooseService.getFavouritename());
viewHolder.favAddress.setText(chooseService.getFavouritelocation());
int checkBoxVisibility = showCheckBox : View.VISIBLE ? View.INVISIBLE;
viewHolder.favCheckbox.setVisibility(checkBoxVisibility);
viewHolder.favCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
favId = chooseService.getFavouritename();
((MainActivity) mContext).check(favId);
}
}
});
return convertView;
}}
when a button is clicked in activity you need to call adapter.showCheckBoxes(true) of your adapter. then set a field to showCheckBoxes=true; in that function and also refresh the list using notifyDataSetChanged() which will cause the getView method to be called for all the rows.
In getView check if showCheckBoxes is true or not and show check boxes accordingly.
public class FavouriteListAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
ArrayList<FavouritesArray> mArrFavourites;
ViewHolder viewHolder;
String favId;
boolean showCheckBoxes = false;
//Make checkbox to visible in all rows in listview
public void setcheckbox() {
viewHolder.favCheckbox.setVisibility(View.VISIBLE);
}
public static class ViewHolder {
public TextView favName;
public TextView favUrl;
public TextView favAddress;
public CheckBox favCheckbox;
}
public FavouriteListAdapter(Context context, ArrayList<FavouritesArray> lArrFavourites) {
mContext = context;
mArrFavourites = lArrFavourites;
}
#Override
public int getCount() {
if (mArrFavourites == null) {
return 0;
}
return mArrFavourites.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.favouritelistadapter, parent, false);
viewHolder.favName = (TextView) convertView.findViewById(R.id.fav_name);
viewHolder.favUrl = (TextView) convertView.findViewById(R.id.fav_url);
viewHolder.favAddress = (TextView) convertView.findViewById(R.id.fav_address);
viewHolder.favCheckbox = (CheckBox) convertView.findViewById(R.id.fav_checkbox);
viewHolder.favCheckbox .setVisibility(View.INVISIBLE);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final FavouritesArray chooseService = mArrFavourites.get(position);
viewHolder.favName.setText(chooseService.getFavouritename());
viewHolder.favAddress.setText(chooseService.getFavouritelocation());
if(showCheckBoxes){
viewHolder.favCheckbox .setVisibility(VISIBLE);
}else{
viewHolder.favCheckbox .setVisibility(INVISIBLE);
}
viewHolder.favCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
favId = chooseService.getFavouritename();
((MainActivity) mContext).check(favId);
}
}
});
return convertView;
}}
public void showCheckBoxes(boolean showCheckBoxes){
this.showCheckBoxes=showCheckBoxes;
notifyDataSetChanged();
}
in your button click function:
void onClick(View v){
mAdapter.showCheckBoxes(true);
}

GridView inside ExpandableListView with multiple choice on Android

In my app I need to show images inside a expandableListView and it has to be a gridview of images, and these images can be selectable so I have an expandableListAdapter and inside of it I'm implementing a gridview adapter,
the images are showing fine as you can see in the picture 1, now what I'm trying to achieve is the picture 2, how can I pass the groupPosition and the childPosition to the gridAdapter and whe I click on the image make it highlight? :
Picture 2:
public class ExpandListAdapter extends BaseExpandableListAdapter {
public static final int CHOICE_MODE_MULTIPLE = AbsListView.CHOICE_MODE_MULTIPLE;
public static final int CHOICE_MODE_MULTIPLE_MODAL = AbsListView.CHOICE_MODE_MULTIPLE_MODAL;
/**
* No child could be selected
*/
public static final int CHOICE_MODE_NONE = AbsListView.CHOICE_MODE_NONE;
/**
* One single choice per group
*/
public static final int CHOICE_MODE_SINGLE_PER_GROUP = AbsListView.CHOICE_MODE_SINGLE;
/**
* One single choice for all the groups
*/
public static final int CHOICE_MODE_SINGLE_ABSOLUTE = 10001;
private Context context;
private ArrayList<Group> groups;
private ArrayList<ArrayList<Child>> child = new ArrayList();
private ArrayList<Child> listchild;
private GridAdapter adapter;
private CustomGridView gridView;
private SparseArray<SparseBooleanArray> checkedPositions;
private static final String LOG_TAG = ExpandListAdapter.class.getSimpleName();
private int choiceMode = CHOICE_MODE_MULTIPLE;
public ExpandListAdapter(Context context, ArrayList<Group> groups) {
this.context = context;
this.groups = groups;
checkedPositions = new SparseArray<SparseBooleanArray>();
child = new ArrayList();
for (int i = 0; i < groups.size(); i++) {
child.add(i, groups.get(i).getItems());
}
}
public ExpandListAdapter(Context context, ArrayList<Group> children, int choiceMode) {
this(context, children);
// For now the choice mode CHOICE_MODE_MULTIPLE_MODAL
// is not implemented
if (choiceMode == CHOICE_MODE_MULTIPLE_MODAL) {
throw new RuntimeException("The choice mode CHOICE_MODE_MULTIPLE_MODAL " +
"has not implemented yet");
}
this.choiceMode = choiceMode;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return child.get(childPosition);
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.gridview, null);
}
listchild = new ArrayList<Child>();
for (int j = 0; j < groups.get(groupPosition).getItems().size(); j++) {
listchild.add(child.get(groupPosition).get(j));
}
gridView = (CustomGridView) convertView.findViewById(R.id.GridView_toolbar);
gridView.setExpanded(true);
adapter = new GridAdapter(context, listchild, checkedPositions, groupPosition, childPosition);
gridView.setAdapter(adapter);// Adapter
gridView.setChoiceMode(CustomGridView.CHOICE_MODE_MULTIPLE);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setClicked(groupPosition, childPosition);
System.out.println("position" + checkedPositions.get(groupPosition));
if (checkedPositions.get(groupPosition) != null) {
boolean isChecked = checkedPositions.get(groupPosition).get(childPosition);
if(!isChecked){
}
} else {
System.out.println("false");
}
}
});
return convertView;
}
public void setClicked(int groupPosition, int childPosition) {
switch (choiceMode) {
case CHOICE_MODE_MULTIPLE:
SparseBooleanArray checkedChildPositionsMultiple = checkedPositions.get(groupPosition);
// if in the group there was not any child checked
if (checkedChildPositionsMultiple == null) {
checkedChildPositionsMultiple = new SparseBooleanArray();
// By default, the status of a child is not checked
// So a click will enable it
checkedChildPositionsMultiple.put(childPosition, true);
checkedPositions.put(groupPosition, checkedChildPositionsMultiple);
} else {
boolean oldState = checkedChildPositionsMultiple.get(childPosition);
checkedChildPositionsMultiple.put(childPosition, !oldState);
}
break;
// TODO: Implement it
case CHOICE_MODE_MULTIPLE_MODAL:
throw new RuntimeException("The choice mode CHOICE_MODE_MULTIPLE_MODAL " +
"has not implemented yet");
case CHOICE_MODE_NONE:
checkedPositions.clear();
break;
case CHOICE_MODE_SINGLE_PER_GROUP:
SparseBooleanArray checkedChildPositionsSingle = checkedPositions.get(groupPosition);
// If in the group there was not any child checked
if (checkedChildPositionsSingle == null) {
checkedChildPositionsSingle = new SparseBooleanArray();
// By default, the status of a child is not checked
checkedChildPositionsSingle.put(childPosition, true);
checkedPositions.put(groupPosition, checkedChildPositionsSingle);
} else {
boolean oldState = checkedChildPositionsSingle.get(childPosition);
// If the old state was false, set it as the unique one which is true
if (!oldState) {
checkedChildPositionsSingle.clear();
checkedChildPositionsSingle.put(childPosition, !oldState);
} // Else does not allow the user to uncheck it
}
break;
// This mode will remove all the checked positions from other groups
// and enable just one from the selected group
case CHOICE_MODE_SINGLE_ABSOLUTE:
checkedPositions.clear();
SparseBooleanArray checkedChildPositionsSingleAbsolute = new SparseBooleanArray();
checkedChildPositionsSingleAbsolute.put(childPosition, true);
checkedPositions.put(groupPosition, checkedChildPositionsSingleAbsolute);
break;
}
// Notify that some data has been changed
notifyDataSetChanged();
Log.v(LOG_TAG, "List position updated");
Log.v(LOG_TAG, PrintSparseArrays.sparseArrayToString(checkedPositions));
}
public void setChoiceMode(int choiceMode) {
this.choiceMode = choiceMode;
// For now the choice mode CHOICE_MODEL_MULTIPLE_MODAL
// is not implemented
if (choiceMode == CHOICE_MODE_MULTIPLE_MODAL) {
throw new RuntimeException("The choice mode CHOICE_MODE_MULTIPLE_MODAL " +
"has not implemented yet");
}
checkedPositions.clear();
Log.v(LOG_TAG, "The choice mode has been changed. Now it is " + this.choiceMode);
}
#Override
public int getChildrenCount(int nGroup) {
return 1;
}
#Override
public Object getGroup(int groupPosition) {
return groups.get(groupPosition);
}
#Override
public int getGroupCount() {
return groups.size();
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
Group group = (Group) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater inf = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = inf.inflate(R.layout.group_item, null);
}
ExpandableListView mExpandableListView = (ExpandableListView) parent;
mExpandableListView.expandGroup(groupPosition);
TextView tv = (TextView) convertView.findViewById(R.id.group_name);
tv.setText(group.getName());
return convertView;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
GridAdapter:
public class GridAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Child> child;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
private SparseArray<SparseBooleanArray> checkedPositions;
int groupPosition, childPosition;
public GridAdapter(Context context, ArrayList<Child> childValues, SparseArray<SparseBooleanArray> checkedPositions, int groupPosition, int childPosition) {
mContext = context;
child = childValues;
this.checkedPositions = checkedPositions;
this.childPosition = childPosition;
this.groupPosition = groupPosition;
}
#Override
public int getCount() {
return child.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
NetworkImageView i;
childPosition = position;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_item, null);
holder = new ViewHolder();
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
i = (NetworkImageView) convertView
.findViewById(R.id.flag);
i.setImageUrl(String.valueOf(child.get(childPosition).getImage()), imageLoader);
convertView.setTag(holder);
System.out.println("position" + checkedPositions.get(groupPosition));
if (checkedPositions.get(groupPosition) != null) {
boolean isChecked = checkedPositions.get(groupPosition).get(childPosition);
i.setBackgroundResource(R.color.bg);
if(!isChecked){
}
} else {
System.out.println("false");
}
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text = (TextView) convertView.findViewById(R.id.label);
holder.text.setText(child.get(position).getName());
return convertView;
}
static class ViewHolder {
TextView text;
}
}
In My Assumption
ExpandListAdapter Class
In getChildView() method childPosition does not depends on what country flag is being clicked , Because childPosition here returns the position of the Grid view, not the flags under it
So, no need to pass childPosition in constructor of GridView ,since childPosition will always return 1
To get actual flag clicked position Use onClickListener inside your GridAdapter like:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
NetworkImageView i;
childPosition = position;
if (convertView == null) {
} else {
holder = (ViewHolder) convertView.getTag();
}
convertView.setOnclickListener(new OnClickListener{
#Override
onClick(View v){
isChecked=child.get(childPosition).isChecked();
if(!isChecked){
child.get(childPosition).setChecked(true);
}
else {
child.get(childPosition).setChecked(false);
}
});
No need to handle checked positions separately create two methods in your child class isChecked() and setChecked() to maintain check-uncheck state of flags.
Change color of selected or checked flag here
holder.text = (TextView) convertView.findViewById(R.id.label);
holder.text.setText(child.get(position).getName());
return convertView;
}
and remove your Check logic from ExpandListAdapter Class :
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setClicked(groupPosition, childPosition);
System.out.println("position" + checkedPositions.get(groupPosition));
if (checkedPositions.get(groupPosition) != null) {
boolean isChecked = checkedPositions.get(groupPosition).get(childPosition);
if(!isChecked){
}
} else {
System.out.println("false");
}
}
});
You need to set an 'OnItemClickListener' to your gridAdapter, and overide the onItemClick method as following.
Note :- This will highlight the ImageView you click and if you happened to click another ImageView in the same GridView, that ImageView also will be highlighted! Like in a 'multiple selection'.
gridAdapter.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ImageView selectedFlagImageView = (ImageView) view;
selectedFlagImageView.setBackgroundColor(Color.parseColor("#37a93400"));
}
});
This will color the background of the selected ImageView. Color code I've used in here is simply, more alpha and less RGBs.(I used Android Studio color chooser)
Following images will give you an idea about how it will look when giving a background color like this.
Without background color :
With background color :

Categories