how to modify this imageCheckBoxAdapter code in order to maintain status of checkBox when scrolled(that is all the checkboxes which are checked should remain checked even after scrolling. Also the checked variables need to be stored in an array)?
class imageCheckBoxAdapter extends ArrayAdapter<String>
{
private final Context context;
private final ArrayList<String> values;
private final Map< String, SmbFile> obj;
static ArrayList<Boolean> checks=new ArrayList<Boolean>();
public imageCheckBoxAdapter(Context context,ArrayList<String> values,Map< String, SmbFile>obj)
{
super(context, R.layout.row_checkbox, values);
this.context = context;
this.values = values;
this.obj=obj;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row_checkbox, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.text1_check);
textView.setText(values.get(position));
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon_image_check);
try
{
if((obj.get(values.get(position)).isFile()))
{
imageView.setImageResource(R.drawable.view_file_icon);
}
else
{
imageView.setImageResource(R.drawable.view_folder_icon);
}
}
catch (SmbException e)
{
Toast.makeText(context,"Network error",Toast.LENGTH_SHORT).show();
Log.d("id1", "error1");
e.printStackTrace();
}
return rowView;
}
}
row_checkbox.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp" >
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false" />
<ImageView
android:id="#+id/icon_image_check"
android:layout_width="50px"
android:layout_height="50px"
android:layout_marginLeft="5px"
android:layout_marginRight="20px"
android:layout_marginTop="5px"
android:src="#drawable/view_file_icon" >
</ImageView>
<TextView
android:id="#+id/text1_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="30px"
android:typeface="sans">
</TextView>
</LinearLayout>
class imageCheckBoxAdapter extends ArrayAdapter<String> implements View.onClickListener
{
private final Context context;
private final ArrayList<String> values;
private final Map< String, SmbFile> obj;
private ArrayList<Boolean> checks=new ArrayList<Boolean>();
public imageCheckBoxAdapter(Context context,ArrayList<String> values,Map< String, SmbFile>obj)
{
super(context, R.layout.row_checkbox, values);
this.context = context;
this.values = values;
this.obj=obj;
for (int i = 0; i < values.size(); i++) {
checks.add(i, false);
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row_checkbox, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.text1_check);
CheckBox chk = (CheckBox) rowView.findViewById(R.id.checkBox1);
textView.setText(values.get(position));
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon_image_check);
try
{
if((obj.get(values.get(position)).isFile()))
{
imageView.setImageResource(R.drawable.view_file_icon);
}
else
{
imageView.setImageResource(R.drawable.view_folder_icon);
}
}
catch (SmbException e)
{
Toast.makeText(context,"Network error",Toast.LENGTH_SHORT).show();
Log.d("id1", "error1");
e.printStackTrace();
}
chk.setTag(Integer.valueOf(position));
// Set a listener for the checkbox
chk.setOnClickListener(this);
//Sets the state of CB, since we have the list of checked CB
chk.setChecked(checks.get(position));
return rowView;
}
#Override
public void onClick(View view) {
Integer index = (Integer)view.getTag();
boolean state = checks.get(index.intValue());
checks.set(index.intValue(), !state);
}
}
I think your need to store value in an array. For each checkBox, you set a changeListener to store the checkBox associated.
I recently read, not sure where already, a similar case someone asked about.
If I understand correctly, this may be because the CheckBox control is not databound in the DataRepeaterItem, and when scrolling the checkboxes lose their state.
You can try using Viewstate to maintain checked value. I'll try finding that post, it seemed informative.
I think you can save the position of the checkbox in the list by using the View.setTag method
make a reference of your checkbox in the getView like this:
CheckBox chk = (CheckBox) rowView.findViewById(R.id.checkBox1);
Since CheckBoxes are indirect subclasses of View, it also has an attribute View.setTag like this:
chk.setTag(Integer.valueOf(position));
Then set an OnCheckedChangeListener to your chk like:
chk.setOnCheckedChangeListener(new OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton buttonView, boolean state) {
Integer int = (Integer)buttonView.getTag();
checks.set(int.intValue(), !boolean)
}
});
Since the boolean arraylist size is same to the values size, the specified position corresponds the exact location of the checkbox
Then add this snippet to your getView method:
if (checks.get(position)) {
chk.setChecked(checks.get(position));
// do some stuff if wanted..
} else {
chk.setChecked(checks.get(position));
// do some stuff if wanted..
}
We did the snippet because when listview is scrolled upward or downward getView is called for the unseen row item. And to update the row item if already checked or not.
Related
I'm trying to implement a selection activity for a given list of items. Each item is checkable, so I have an item with a TextView and a CheckBox. I implemented a ListView for displaying all the options and a Spinner for showing only the "Top Ten" choices, as a subset of the same list. For now I'm showing all the items in both ListView and Spinner.
I want for the items in the ListView to update when the user selects an item in the Spinner (Note: The reverse path works fine, as the Spinner grabs the updated ArrayList each time it dropsdown).
I tried to implement setOnItemSelectedListener for my Spinner, and to call notifyOnDataSetChanged() for my ListViewAdapter inside the Listener. But the Listener is only called on collapse and I get a weird (maybe unrelated) warning message.
The onItemSelectedListener for the Spinner only runs when the Spinner gets collapsed. But notifyOnDataSetChanged() seems to ignore the checked status of the items as a change. How can I make the first option run everytime I check an item and have the change get properly received by the ListAdapter?
Here's the Activity.java code:
public class TriageReasonActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_triage_reason);
final String[] select_qualification = {
"Select Qualification", "10th / Below", "12th", "Diploma", "UG",
"PG", "Phd"};
Spinner spinner = (Spinner) findViewById(R.id.top_reasons_spinner);
ListView symptoms_list = (ListView) findViewById(R.id.view_list_symptoms);
ArrayList<Symptoms> listVOs = new ArrayList<>();
for (int i = 0; i < select_qualification.length; i++) {
Symptoms reason = new Symptoms();
reason.setTitle(select_qualification[i]);
reason.setSelected(false);
listVOs.add(reason);
}
SymptomsListAdapter mListAdapter = new SymptomsListAdapter(this, 0,
listVOs);
SymptomsSpinnerAdapter mSpinnerAdapter = new SymptomsSpinnerAdapter(this, 0,
listVOs);
symptoms_list.setAdapter(mListAdapter);
spinner.setAdapter(mSpinnerAdapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
Log.i("Item selected", "but not cahnged");
symptoms_list.invalidateViews();
mListAdapter.notifyDataSetInvalidated();
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
Log.i("Not item selected", "but actually it did");
}
});
}
The SpinnerCustom Adapter code:
public class SymptomsSpinnerAdapter extends ArrayAdapter<Symptoms>{
private Context mContext;
private ArrayList<Symptoms> listState;
private SymptomsSpinnerAdapter myAdapter;
private boolean isFromView = false;
/*#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
//mNotifyOnChange = true;
}*/
public SymptomsSpinnerAdapter(Context context, int resource, List<Symptoms> objects) {
super(context, resource, objects);
this.mContext = context;
this.listState = (ArrayList<Symptoms>) objects;
this.myAdapter = this;
}
#Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView,
ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflator = LayoutInflater.from(mContext);
convertView = layoutInflator.inflate(R.layout.item_reasons, null);
holder = new ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.text);
holder.mCheckBox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText(listState.get(position).getTitle());
// To check weather checked event fire from getview() or user input
isFromView = true;
holder.mCheckBox.setChecked(listState.get(position).isSelected());
isFromView = false;
if ((position == 0)) {
holder.mCheckBox.setVisibility(View.INVISIBLE);
} else {
holder.mCheckBox.setVisibility(View.VISIBLE);
}
holder.mCheckBox.setTag(position);
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
if (!isFromView) {
listState.get(position).setSelected(isChecked);
}
}
});
return convertView;
}
#Override
public int getCount() {
return listState.size();
}
#Override
public Symptoms getItem(int position) {
if( position < 1 ) {
return null;
}
else {
return listState.get(position-1);
}
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder {
private TextView mTextView;
private CheckBox mCheckBox;
}
}
Here's the (almost identical) ListAdapter:
public class SymptomsListAdapter extends BaseAdapter implements ListAdapter {
private Context mContext;
private ArrayList<Symptoms> listState;
private boolean isFromView = false;
public SymptomsListAdapter(Context context, int resource, List<Symptoms> objects) {
this.mContext = context;
this.listState = (ArrayList<Symptoms>) objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflator = LayoutInflater.from(mContext);
convertView = layoutInflator.inflate(R.layout.item_reasons, null);
holder = new SymptomsListAdapter.ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.text);
holder.mCheckBox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (SymptomsListAdapter.ViewHolder) convertView.getTag();
}
holder.mTextView.setText(listState.get(position).getTitle());
// To check weather checked event fire from getview() or user input
isFromView = true;
holder.mCheckBox.setChecked(listState.get(position).isSelected());
isFromView = false;
if ((position == 0)) {
holder.mCheckBox.setVisibility(View.INVISIBLE);
} else {
holder.mCheckBox.setVisibility(View.VISIBLE);
}
holder.mCheckBox.setTag(position);
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
if (!isFromView) {
listState.get(position).setSelected(isChecked);
}
}
});
return convertView;
}
#Override
public int getCount() {
return listState.size();
}
#Override
public Symptoms getItem(int position) {
if( position < 1 ) {
return null;
}
else {
return listState.get(position-1);
}
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder {
public TextView mTextView;
public CheckBox mCheckBox;
}
}
And here's the warning I'm getting:
W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
EDIT: Adding the layouts and the model class in case they may cause an issue:
Activity Layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="demo.hb.activity.visit.TriageReasonActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textFontWeight="6dp"
android:textSize="30sp"
android:layout_margin="20dp"
android:textAlignment="center"
android:textColor="#000000"
android:text="What is the reason for your visit?" />
<Spinner
android:id="#+id/top_reasons_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:drawable/btn_dropdown"
android:spinnerMode="dropdown"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="end">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/view_list_symptoms"
android:layout_above="#+id/next_btn"
android:layout_alignParentTop="true"/>
</RelativeLayout>
</LinearLayout>
</FrameLayout>
Item layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="text"
android:textAlignment="gravity" />
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true" />
</RelativeLayout>
Model Class:
public class Symptoms {
private String title;
private boolean selected;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
The reason that nothing is changing is because you haven't implemented the method to handle the data set changes. You need to handle how the data is reloaded in your adapter:
public class SymptomsListAdapter extends BaseAdapter implements ListAdapter {
...
public void refreshData(ArrayList<Symptoms> objects){
this.listState = (ArrayList<Symptoms>) objects;
notifyDataSetChanged();
}
...
}
This link does a great job of explaining how the notifyDataSetInvalidated() works (or in your case, why it's not working).
I'm very new to android and I was given a prewritten app that I must improve. One thing I have to do is add a delete button to each item in a ListView.
Here is the XML for my ListView element:
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:descendantFocusability="blocksDescendants"
android:orientation="horizontal" >
<ImageView
android:id="#+id/li_map_image"
android:layout_width="50dp"
android:layout_height="match_parent"
android:contentDescription="thumbnail" />
<TextView
android:id="#+id/li_map_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:paddingLeft="8dp"
android:textSize="16sp" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/delete"
android:focusableInTouchMode="true"
android:background="#drawable/red_x"
android:layout_gravity="center|left"
android:onClick="deleteMap"></ImageButton>
Basically, I want the user to click the delete icon if they want to delete a row in the ListView. Also, this should delete the item's data from the database. I'm very confused about how to implement this because I don't know how I will know which delete button they are clicking. Also, when I added the ImageButton to the ListView code, it tells me to make the onClick method in main (should it be in main?); but how will I be able to delete data from the database? Also, Main Activity has a Fragment which obtains the ListView code. This is the Fragment class:
public class MapListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
private static final int LOADER_ID = 1;
private static final String[] FROM = { Database.Maps.DATA,
Database.Maps.NAME };
private static final String[] CURSOR_COLUMNS = { Database.Maps.ID,
Database.Maps.DATA, Database.Maps.NAME };
private static final int[] TO = { R.id.li_map_image, R.id.li_map_name };
private SimpleCursorAdapter mAdapter;
// FIXME isn't this unnecessary?
public MapListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// FIXME reverse the order so the newest sessions are at the top
mAdapter = new SimpleCursorAdapter(getActivity(),
R.layout.map_list_item, null, FROM, TO, 0);
mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Cursor cursor,
int columnIndex) {
if (view.getId() == R.id.li_map_image) {
((ImageView) view).setImageURI(Uri.parse(cursor
.getString(columnIndex)));
return true;
}
return false;
}
});
setListAdapter(mAdapter);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public void onListItemClick(ListView list, View v, int position, long id) {
final Intent nextIntent = new Intent(getActivity(),
ViewMapActivity.class);
nextIntent.putExtra(Utils.Constants.MAP_ID_EXTRA, id);
startActivity(nextIntent);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), DataProvider.MAPS_URI,
CURSOR_COLUMNS, null, null, null);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (loader.getId() == LOADER_ID)
mAdapter.swapCursor(cursor);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
I'm very lost as how to implement this delete feature. Any help will be much appreciated :)
here is a very good tutorial on how to put a clicklistener on a button inside listview.
follow this link
inside your adapter getView method, you need to put click listener on button like this
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.child_listview, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView
.findViewById(R.id.childTextView);
viewHolder.button = (Button) convertView
.findViewById(R.id.childButton);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final String temp = getItem(position);
viewHolder.text.setText(temp);
viewHolder.button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (customListner != null) {
customListner.onButtonClickListner(position,temp);
}
}
});
return convertView;
}
Add Longclicklistner in Your Listview
try this , it may help you
Link
I have a row which is represented by an image, some text and a CheckBoxes. Whenever I'm trying to use the OnItemClickListener for the rows, the event won't fire up when clicking the CheckBoxes.
I also tried checkbox.onCheckedChangedListener but it gives me Null Pointer at findViewByID. I checked, the ID I am looking for is alright, no typos in there.
I'd like to make usage of this OnItemClickListener so later on I can play with the checkboxes. Any ideas?
Code:
ADAPTER:
public class FilterAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> mFilters;
private ArrayList<Integer> mPictures;
private Typeface Bebas, DroidSans;
public FilterAdapter(Context context, ArrayList<String> filters, ArrayList<Integer> pictures) {
this.mContext = context;
this.mFilters = filters;
this.mPictures = pictures;
}
#Override
public int getCount() {
return mFilters.size();
}
#Override
public Object getItem(int position) {
return mFilters.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.category_filter_item, null);
}
DroidSans = Typeface.createFromAsset(mContext.getAssets(), "fonts/DroidSans.ttf");
ImageView filter_img = (ImageView) convertView.findViewById(R.id.category_picture);
TextView filter_category = (TextView) convertView.findViewById(R.id.filter_category);
CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.check_box);
filter_category.setTypeface(DroidSans);
filter_category.setText(mFilters.get(position));
filter_img.setBackgroundResource(mPictures.get(position));
return convertView;
}
}
Class where using the Adapter:
public class CheckinFilters extends Fragment {
private ListView mListView;
private FilterAdapter filterAdapter;
private ArrayList<String> l = new ArrayList<String>();
private ArrayList<Integer> drawables = new ArrayList<Integer>();
private Typeface Bebas;
private ArrayList<Integer> checkboxes = new ArrayList<Integer>();
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
public CheckinFilters() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_checkin_filters, container, false);
l.add("Chill");
l.add("Eat");
l.add("Explore");
l.add("Move");
l.add("Party");
l.add("Whatever");
drawables.add(R.drawable.category_chill);
drawables.add(R.drawable.category_eat);
drawables.add(R.drawable.category_explore);
drawables.add(R.drawable.category_move);
drawables.add(R.drawable.category_party);
drawables.add(R.drawable.category_whatever);
mListView = (ListView) view.findViewById(R.id.filter_list);
filterAdapter = new FilterAdapter(view.getContext(), l, drawables);
mListView.setAdapter(filterAdapter);
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
Bebas = Typeface.createFromAsset(view.getContext().getAssets(), "fonts/BebasNeue.otf");
TextView mainHeader = (TextView) view.findViewById(R.id.filters_text);
mainHeader.setTypeface(Bebas);
SearchView filter_categories = (SearchView) view.findViewById(R.id.filter_categories);
int searchImgID = getResources().getIdentifier("android:id/search_button", null, null);
ImageView searchViewHint = (ImageView) filter_categories.findViewById(searchImgID);
searchViewHint.setImageResource(R.drawable.ab_icon_search);
int searchPlateID = filter_categories.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
View searchPlateView = filter_categories.findViewById(searchPlateID);
if (searchPlateView != null) {
searchPlateView.setBackgroundResource(R.drawable.search_location_shape);
}
int searchViewID = filter_categories.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
TextView textView = (TextView) filter_categories.findViewById(searchViewID);
textView.setTextColor(Color.GRAY);
CheckBox checkBox = (CheckBox) view.findViewById(R.id.check_box);
return view;
}
private void save() {
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
editor.putInt("first", checkboxes.size());
for (int i = 0; i < checkboxes.size(); i++) {
editor.remove("Status_" + i);
editor.putInt("Status_" + i, checkboxes.get(i));
}
editor.commit();
}
private void load() {
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
int size = sharedPreferences.getInt("first", 0);
for (int i = 0; i < size; i++) {
checkboxes.add(sharedPreferences.getInt("Status_" + i, 0));
}
}
#Override
public void onPause() {
super.onPause();
save();
}
#Override
public void onResume() {
super.onResume();
load();
}
}
Layout I'm inflating for Adapter:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ECF0F1">
<ImageView
android:id="#+id/category_picture"
android:layout_width="70dp"
android:layout_height="60dp"
android:background="#drawable/sm_profile"/>
<TextView
android:id="#+id/filter_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/category_picture"
android:padding="10dp"
android:text="Party"
android:textColor="#color/enloop_dark_gray"
android:textSize="18dp"/>
<CheckBox
android:id="#+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:padding="10dp"/>
</RelativeLayout>
</RelativeLayout>
Instead of using OnItemClickListener in CheckinFilters.java, you should add that code in getView() method of FilterAdapter. You are actually adding checkbox for every row but the id for all checkbox is same, so you can't apply customized code for every checkbox.
To be able to make use of all checkboxes you can put checkbox code in getView() method because it also contains an argument called position. So you can just get the position and apply OnItemClickListener to every single checkbox. That way it will work.
public class FilterAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> mFilters;
private ArrayList<Integer> mPictures;
private Typeface Bebas, DroidSans;
public FilterAdapter(Context context, ArrayList<String> filters, ArrayList<Integer> pictures) {
this.mContext = context;
this.mFilters = filters;
this.mPictures = pictures;
}
#Override
public int getCount() {
return mFilters.size();
}
#Override
public Object getItem(int position) {
return mFilters.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.category_filter_item, null);
}
DroidSans = Typeface.createFromAsset(mContext.getAssets(), "fonts/DroidSans.ttf");
ImageView filter_img = (ImageView) convertView.findViewById(R.id.category_picture);
TextView filter_category = (TextView) convertView.findViewById(R.id.filter_category);
CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.check_box);
filter_category.setTypeface(DroidSans);
filter_category.setText(mFilters.get(position));
filter_img.setBackgroundResource(mPictures.get(position));
if(position == 0) {
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
else {
}
}
});
}
//Similarly add OnClickListener to other checkboxes.
return convertView;
}
}
I've searched a lot this but I really did not find what I need exactly.
What I want is :
I have a listview and load it on my main class. I load it like this:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(Main.this,
R.layout.myrow,R.id.text );
if (friends != null) {
for (ParseObject friend : friends) {
adapter.add((String) friend.get("name"));
}
}
setListAdapter(adapter);
and myrow layout xml is here:
< RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<ProgressBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/my_prog"
></ProgressBar>
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp" >
</TextView>
</RelativeLayout >
You can see I have progress bar on textview so I need to reach it and set it's visible. I mean sometimes I set it invisible sometimes visible
What I did is:
On my MainActivity on create method the code is here :
ProgressBar my_prog;
my_prog=(ProgressBar)findViewById(R.id.my_prog);
my_prog.setVisibility(View.INVISIBLE);
The error is:
07-16 13:35:39.219: E/AndroidRuntime(29096): java.lang.RuntimeException: Unable to start activity ComponentInfo{....MainActivity}: java.lang.NullPointerException
I think I cant reach my_prog on my main activity but I need it.
How can I do that.
thanks in adnvace...
You need to implement a custom Adapter to do this. I have written this ExampleAdapter to show you how it works, I commented all the important parts:
public class ExampleAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private final List<ParseObject> objects;
private final boolean[] activated;
public ExampleAdapter(Context context, List<ParseObject> objects) {
this.inflater = LayoutInflater.from(context);
this.objects = objects;
this.activated = new boolean[objects.size()];
}
public void showProgressBar(int position, boolean visible) {
this.activated[position] = visible;
notifyDataSetChanged();
}
#Override
public int getCount() {
return this.objects.size();
}
#Override
public ParseObject getItem(int position) {
return this.objects.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// If the convertView is null, we need to inflate a new one
if(convertView == null) {
// We inflate the view with your layout
convertView = inflater.inflate(R.layout.myrow, parent, false);
// Here we create a view holder object which keeps a
// reference to the Views in this row so we have to
// perform the expensive findViewById() only once
ViewHolder holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.my_prog = (ProgressBar) convertView.findViewById(R.id.my_prog);
// The view holder is set as tag to the view so we can access it later
convertView.setTag(holder);
}
// We retrieve the ParseObject for the current position
ParseObject parseObject = getItem(position);
// And get the view holder from the View
ViewHolder holder = (ViewHolder) convertView.getTag();
// We read the data we need from the ParseObject
String name = parseObject.get("name");
// And here is the visibility logic
int progressBarVisibility = this.activated[position] ? View.VISIBLE : View.GONE;
int textViewVisibility = this.activated[position] ? View.GONE : View.VISIBLE;
// Now we set the data to the Views through the view holder
holder.text.setText(name);
holder.text.setVisibility(textViewVisibility);
holder.my_prog.setVisibility(progressBarVisibility);
return convertView;
}
// This is our view holder class. It keeps a reference to the Views
// inside each row so we have to perform the expensive
// findViewById() only once
private class ViewHolder {
public TextView text;
public ProgressBar my_prog;
}
}
You can use the ExampleAdapter like this:
if(friends != null) {
ExampleAdapter adapter = new ExampleAdapter(Main.this, friends);
setListAdapter(adapter);
}
If you want to show a ProgressBar at a specific position you just do this:
// Shows the ProgressBar in the first row
adapter.showProgressBar(0, true)
I'm trying to make a task manager, and I only have one problem. I have a listview that gets inflated. All the elements in the listview are correct. The problem is that when I select an item, the listview will select another item away. I've heard listviews repopulate the list as it scrolls down to save memory. I think this may be some sort of problem. Here is a picture of the problem.
If i had more apps loaded, then it would continue to select multiple at once.
Here is the code of my adapter and activity and XML associated
public class TaskAdapter extends BaseAdapter{
private Context mContext;
private List<TaskInfo> mListAppInfo;
private PackageManager mPack;
public TaskAdapter(Context c, List<TaskInfo> list, PackageManager pack) {
mContext = c;
mListAppInfo = list;
mPack = pack;
}
#Override
public int getCount() {
return mListAppInfo.size();
}
#Override
public Object getItem(int position) {
return mListAppInfo.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
TaskInfo entry = mListAppInfo.get(position);
if (convertView == null)
{
LayoutInflater inflater = LayoutInflater.from(mContext);
//System.out.println("Setting LayoutInflater in TaskAdapter " +mContext +" " +R.layout.taskinfo +" " +R.id.tmbox);
convertView = inflater.inflate(R.layout.taskinfo,null);
}
ImageView ivIcon = (ImageView)convertView.findViewById(R.id.tmImage);
ivIcon.setImageDrawable(entry.getIcon());
TextView tvName = (TextView)convertView.findViewById(R.id.tmbox);
tvName.setText(entry.getName());
convertView.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
final CheckBox checkBox = (CheckBox)v.findViewById(R.id.tmbox);
if(v.isSelected())
{
System.out.println("Listview not selected ");
//CK.get(arg2).setChecked(false);
checkBox.setChecked(false);
v.setSelected(false);
}
else
{
System.out.println("Listview selected ");
//CK.get(arg2).setChecked(true);
checkBox.setChecked(true);
v.setSelected(true);
}
}
});
return convertView;
public class TaskManager extends Activity implements Runnable
{
private ProgressDialog pd;
private TextView ram;
private String s;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.taskpage);
setTitleColor(Color.YELLOW);
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run()
{
//System.out.println("In Taskmanager Run() Thread");
final PackageManager pm = getPackageManager();
final ListView box = (ListView) findViewById(R.id.cBoxSpace);
final List<TaskInfo> CK = populate(box, pm);
runOnUiThread(new Runnable()
{
#Override
public void run()
{
ram.setText(s);
box.setAdapter(new TaskAdapter(TaskManager.this, CK, pm));
//System.out.println("In Taskmanager runnable Run()");
endChecked(CK);
}
});
handler.sendEmptyMessage(0);
}
Taskinfo.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal">
<ImageView
android:id="#+id/tmImage"
android:layout_width="48dp"
android:layout_height="48dp"
android:scaleType="centerCrop"
android:adjustViewBounds="false"
android:focusable="false" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tmbox"
android:lines="2"/>
</LinearLayout>
Taskpage.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#+id/cBoxSpace"
android:layout_width="wrap_content"
android:layout_height="400dp"
android:orientation="vertical"/>
<TextView
android:id="#+id/RAM"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp" />
<Button
android:id="#+id/endButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="End Selected Tasks" />
</LinearLayout>
Any ideas for what reason mutliple items are selected with a single click would be GREATLY appreciated. I've been messing around with different implementations and listeners and listadapters but to no avail.
I think the point is you only save checking state in the view(v.setSelected).
And you reuse these view, so its checkbox is always not change its state.
You can create a state array to save every checking state of every TaskInfo, and check this array when you create a view.
for example
// default is false
ArrayList<Boolean> checkingStates = new ArrayList<Boolean>(mListAppInfo.size());
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
TaskInfo entry = mListAppInfo.get(position);
if (convertView == null)
{
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(R.layout.taskinfo,null);
}
ImageView ivIcon = (ImageView)convertView.findViewById(R.id.tmImage);
ivIcon.setImageDrawable(entry.getIcon());
TextView tvName = (TextView)convertView.findViewById(R.id.tmbox);
tvName.setText(entry.getName());
final CheckBox checkBox = (CheckBox)v.findViewById(R.id.tmbox);
checkBox.setChecked(checkingStates.get(position));
convertView.setSelected(checkingStates.get(position));
convertView.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
if(v.isSelected())
{
System.out.println("Listview not selected ");
//CK.get(arg2).setChecked(false);
checkBox.setChecked(false);
v.setSelected(false);
checkingStates.get(position) = false;
}
else
{
System.out.println("Listview selected ");
//CK.get(arg2).setChecked(true);
checkBox.setChecked(true);
v.setSelected(true);
checkingStates.get(position) = true;
}
}
});
return convertView;
}
I'm not 100% sure what you are trying to do, but part of your problem might be related to the condition in your onClick method:
if(v.isSelected())
I think you want that to read
if(v.isChecked())
isSelected is inherited from View, and it means something different from isChecked
Also, the whether the CheckBox is checked or not is independent from your data model since it is a recycled view. Your CheckBox should be checked based on entry (I'm assuming your TextInfo class has an isChecked() method that returns a boolean:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
TaskInfo entry = mListAppInfo.get(position);
if (convertView == null)
{
LayoutInflater inflater = LayoutInflater.from(mContext);
//System.out.println("Setting LayoutInflater in TaskAdapter " +mContext +" " +R.layout.taskinfo +" " +R.id.tmbox);
convertView = inflater.inflate(R.layout.taskinfo,null);
}
ImageView ivIcon = (ImageView)convertView.findViewById(R.id.tmImage);
ivIcon.setImageDrawable(entry.getIcon());
TextView tvName = (TextView)convertView.findViewById(R.id.tmbox);
tvName.setText(entry.getName());
CheckBox checkBox = (CheckBox)v.findViewById(R.id.tmbox);
checkBox.setChecked(entry.isChecked());
}
I don't think you need the View.OnClickListener you are attaching to convertView. You should handle that in the OnItemClickListener attached to the ListView. Assuming your ListView is called listView and TaskInfo instances have setChecked and isChecked methods:
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
entry = mListAppInfo.get(position);
entry.setChecked(!entry.isChecked());
}
});
First of all don't set the list checked or unchecked on view position.
because view position means only visible items position in your listview but you would like to set checked or uncheked status on a particular list item.
That's why this problem arises in your code.
You have the need to set the items checked and unchecked on your custom arraylist getter setter like the code i have attached below:
package com.app.adapter;
public class CategoryDynamicAdapter {
public static ArrayList<CategoryBean> categoryList = new ArrayList<CategoryBean>();
Context context;
Typeface typeface;
public static String videoUrl = "" ;
Handler handler;
Runnable runnable;
// constructor
public CategoryDynamicAdapter(Activity a, Context context, Bitmap [] imagelist,ArrayList<CategoryBean> list) {
this.context = context;
this.categoryList = list;
this.a = a;
}
// Baseadapter to the set the data response from web service into listview.
public BaseAdapter mEventAdapter = new BaseAdapter() {
#Override
public int getCount() {
return categoryList.size();
}
#Override
public Object getItem(int position) {
return categoryList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
class ViewHolder {
TextView title,category,uploadedBy;
ImageView image;
RatingBar video_rating;
Button report_video ,Flag_video;
}
public View getView(final int position, View convertView, final ViewGroup parent) {
ViewHolder vh = null ;
if(convertView == null) {
vh = new ViewHolder();
convertView = LayoutInflater.from(context).inflate (R .layout.custom_category_list_layout,null,false);
vh.title = (TextView) convertView .findViewById (R.id.title);
vh.image = (ImageView) convertView.findViewById(R.id.Imagefield);
convertView.setTag(vh);
}
else
{
vh=(ViewHolder) convertView.getTag();
}
try
{
final CategoryBean Cb = categoryList.get(position);
//pay attention to code below this line i have shown here how to select a listview using arraylist getter setter objects
String checkedStatus = Cb.getCheckedStringStaus();
if(checkdStatus.equal("0")
{
System.out.println("Listview not selected ");
//CK.get(arg2).setChecked(false);
checkBox.setChecked(false);
v.setSelected(false);
}
else ////checkdStatus.equal("1")
{
System.out.println("Listview selected ");
//CK.get(arg2).setChecked(true);
checkBox.setChecked(true);
v.setSelected(true);
}
catch (Exception e)
{
e.printStackTrace();
}