I am developing a simple Android app which creates a ListView with a checkbox as follows
listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice,results);
this.setListAdapter(listAdapter);
ListView lv = getListView();
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lv.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
CheckedTextView check = (CheckedTextView)view;
//The below code needed for running on AVD version 4.2
if(check.isChecked()) {
// Checkbox checked do something
}
else {
// Not checked. Do something
}
/* Exact opposite need on Samsung phone running 2.3.6
if(!check.isChecked()) {
// Checkbox checked do something
}
else {
// Not checked. DO something
} */
This is truly weird. How will the app ever be compatible with both version when they require completely opposite checks?
Please let me know how I can handle this. Any help will be appreciated.
i know the problem, on newer frameworks the onItemClick call before the checkd attribute of the checkbox changed!
i check the checked state of my checkboxes in after item clicking (e.g. on activity close or save button click).
look at list.getCheckedItemPositions()... it will return a SparseBooleanArray you can use!
EDIT: example
public class MyMultiChoiceActivity extends Activity implements View.OnClickListener {
private ListView list = null;
private boolean savedSelectionInvalid = true;
private List<Integer> selectedIds = new ArrayList<Integer>();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.entry_data_multi_choice_filter);
//initialize the list
list = (ListView) findViewById(R.id.list);
listAdapter = new MyListAdapterClass(this, R.layout.list_item_multiple_choice);
list.setAdapter(listAdapter);
//onclick on a item, set the selectaion as invalid
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
savedSelectionInvalid = true;
}
});
list.setAdapter(listAdapter);
//...
}
//...
private void validateChecked() {
if(savedSelectionInvalid == true) {
SparseBooleanArray checkedItemlist = list.getCheckedItemPositions();
selectedIds.clear();
for (int i=0; i < checkedItemlist.size(); i++){
if (checkedItemlist.valueAt(i)) {
selectedIds.add(a.keyAt(i));
}
}
this.savedSelectionInvalid = false;
}
}
//...
//this method se
private void saveAndClose() {
validateChecked();
//now you have the selectedIds filled with every checked item key!
this.finish();
}
}
The issue can be solved by checking the version of the device.
The documentation recommends you check Build.VERSION.SDK_INT against the values in Build.VERSION_CODES.
Sample usage
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
// only for android older than gingerbread
}
http://developer.android.com/reference/android/os/Build.VERSION.html
(More like a hack than a solution though)
You can also try to use something like this:
mFilterListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
...
SparseBooleanArray checkedItemlist = mFilterListView.getCheckedItemPositions();
boolean checked = false;
for (int i = 0; i < checkedItemlist.size(); i++) {
if (checkedItemlist.keyAt(i) == position) {
checked = checkedItemlist.valueAt(i);
}
...
}
}
As a result you have a flag checked, which indicates what is the state of item after the click.
Related
I am working on the custom Listview using BaseAdapter. I am facing one small issue after tap on listview item that particular row gets highlighted but after that if i'll tap one another list item it's highlighted but still the older one it remains same it's not going to it's previous state.
I want to see one item should select at one time.
MainActivity.java
if (musicRealmResults.get(currentIndex).isSelected() == false) {
musicRealmResults.get(currentIndex).setIsSelected(true);
playSong(currentIndex, true);
adapter.notifyDataSetChanged();
} else {
musicRealmResults.get(currentIndex).setIsSelected(false);
adapter.notifyDataSetChanged();
}
MusicAdapter.java
if (musicRealmResults.get(position).isSelected()) {
Typeface tf = Typeface.createFromAsset(mContext.getAssets(), "fonts/fonts_bold.otf");
holder1.albumsTextView.setTypeface(tf);
holder1.equalizerView.setVisibility(View.VISIBLE);
holder1.albumsImageView.setVisibility(View.INVISIBLE);
holder1.equalizerView.animateBars();
} else {
Typeface tf = Typeface.createFromAsset(mContext.getAssets(), "fonts/fonts_regular.otf");
holder1.albumsTextView.setTypeface(tf);
holder1.equalizerView.setVisibility(View.GONE);
holder1.albumsImageView.setVisibility(View.VISIBLE);
holder1.equalizerView.stopBars();
}
Please kindly go through my post and suggest me how to do select and deselect in a listview row.
Loop through all your array elements and set check state to false, then set currentIndex to true.
MainActivity
for(int i =0 ; i < musicRealmResults.size() ; ++i){
musicRealmResults.get(i).setIsSelected(false);
}
musicRealmResults.get(currentIndex).setIsSelected(true);
playSong(currentIndex, true);
adapter.notifyDataSetChanged();
Seems that you weren't able to setSelected(false) your previous item.
Please check setChoiceMode() of ListView or you may just reset your previous item to setSelected(false).
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
musicRealmResults.get(currentSelected).setIsSelected(false); //Reset previous
currentSelected = position; //Save currentPosition to for reset later
.....todos
}
This is a good alternative too, if u dont want to loop through the rest of positions to deselect them.
int prevSelection =-1; //nothing selected
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (prevSelection==-1) //nothing selected
{
musicRealmResults.get(position).setIsSelected(true);
adapter.notifyDataSetChanged();
prevSelection = position;
}else if (prevSelection == position) //deselect previously selected
{
musicRealmResults.get(position).setIsSelected(false);
adapter.notifyDataSetChanged();
prevSelection = -1;
}else // Some other selection
{
musicRealmResults.get(prevSelection).setIsSelected(false);
musicRealmResults.get(position).setIsSelected(true);
adapter.notifyDataSetChanged();
prevSelection = position;
}
You can manage this in your model class. Just make a toggle Boolean isSelected with its getter and setter, When user tap on list item check whether its already selected or not, if not then mark it as selected and update the Boolean value in your model class.
mListLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(list.get(position).getisSelected()){
// list item is already selected.
mListLayout.setBackgroundColor(Color.WHITE); // normal color
list.get(position).setisSelected(false);
}
else{
// list item is not selected, make it selected
mListLayout.setBackgroundColor(Color.GRAY); // selected color
list.get(position).setisSelected(true);
}
notifyDataSetChanged();
}
});
Try Below Code:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
if (musicRealmResults.get(position).isSelected() == false)
{
musicRealmResults.get(position).setIsSelected(true);
playSong(position, true);
adapter.notifyDataSetChanged();
}
else
{
musicRealmResults.get(position).setIsSelected(false);
adapter.notifyDataSetChanged();
}
}
});
I have my code:
AdapterView.OnItemClickListener listener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String elementoSeleccionado = parent.getItemAtPosition(position).toString();
Boolean realizado = getRealizadoPorElemento(elementoSeleccionado);
if (realizado == true){
actualizaRealizado(elementoSeleccionado,"N");
elementosList.getChildAt(position).setBackgroundColor(Color.TRANSPARENT);
} else if (realizado == false){
actualizaRealizado(elementoSeleccionado,"S");
elementosList.getChildAt(position).setBackgroundColor(Color.parseColor("#3DF400"));
}
}
};
And this still working, but the problem is here.
I have a Method run the list view and update some with other color:
ArrayList<String> elementos = LeerElementosLista();
if (elementos.isEmpty() == false) {
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, LeerElementosLista());
elementosList.setAdapter(arrayAdapter);
Boolean realizadoelem = false;
int count = elementosList.getCount();
for (int i = 0; i < count; i++){
String elem = elementosList.getItemAtPosition(i).toString();
realizadoelem = getRealizadoPorElemento(elem);
if (realizadoelem == true){
elementosList.getChildAt(i).setBackgroundColor(Color.parseColor("#3DF400"));
}
}
} else {
//Toast.makeText(this, "No hay Listas para mostrar!!!", Toast.LENGTH_SHORT);
}
And just this line in the second method
elementosList.getChildAt(i).setBackgroundColor(Color.parseColor("#3DF400"));
is not working, the app closes but I don't have an error in the console.
Thats not the way of doing it.
You need to create a custom adapter, from BaseAdapter class.
There you can set the background color of the cell on the getView() method.
Hope this helps.
Maybe you need to set drawable/selector instead of color.If you override default background it aloso deletes default selector.So your list is created with one selector and you are trying change it.Maybe here is the conflict.
But better provide logcat output.It would be easier;
I'm trying to implement multiple list item selection and user can perform actions based on menu item appears on actionbar.
I have tried a way ListView.CHOICE_MODE_MULTIPLE_MODAL but this option works only for API 11 or above.
Is there a way we can make use of the same technique for API 11 below i.e below code works only API 11 onwards.
list.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
// Capture total checked items
final int checkedCount = list.getCheckedItemCount();
// Set the CAB title according to total checked items
mode.setTitle(checkedCount + " Selected");
// Calls toggleSelection method from ListViewAdapter Class
listviewadapter.toggleSelection(position);
}
Using ActionBarSherlock the MultiChoiceModeListener if you want to support API level < 11.
A workaround is to use the onItemClickListener.
List setup:
listView = (ListView) timeline.findViewById(android.R.id.list);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setItemsCanFocus(false);
listView.setAdapter(new ListAdapter(getActivity(), R.layout.cleaning_list_item, items));
Listener of ListFragment or ListActivity:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
SparseBooleanArray checked = listView.getCheckedItemPositions();
boolean hasCheckedElement = false;
for (int i = 0; i < checked.size() && !hasCheckedElement; i++) {
hasCheckedElement = checked.valueAt(i);
}
if (hasCheckedElement) {
if (mMode == null) {
mMode = ((SherlockFragmentActivity) getActivity()).startActionMode(new MyActionMode());
mMode.invalidate();
} else {
mMode.invalidate();
}
} else {
if (mMode != null) {
mMode.finish();
}
}
}
Where MyActionMode is an implementation of ActionMode.Callback:
private final class MyActionMode implements ActionMode.Callback { /* ... */ }
Couples of example I have had referred for my Android application. In ListActivity,before the OnCreate method, the items array was predefined as
String[] items = new String[]{"Text for Item1", "text for item2", ....};
Inside the OnCreate method, I use the simplest way to set the adapter and display the list view below:
setListAdapter( new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_checked, items));
And I have had override the method:
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
CheckedTextView textview = (CheckedTextView)v;
textview.setChecked(!textview.isChecked());
}
All above code is worked fine. The checkmark for each litem in the ListView can be displayed and set checked/unchecked manually.
MY PROBLEM IS:
I want to set some items by program,not by hand clicking, to be checked/unchecked and the checkmark be changed along too. Can it be done and how to do it ?
Thanks for the help in Advance
I think Romain Guy who is Android Engineer at Google said in this can resolve your prolbem:
Actually you want to use CheckedTextView with choiceMode. That's what
CheckedTextView is for. However, you should not be calling setChecked
from bindView(), but let ListView handle it. The problem was that you
were doing ListView's job a second time. You don't need listeners
(click on onlistitem), calls to setChecked, etc.
Here is my solution for this:
class MyActivity extends ListActivity { // or ListFragment
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// some initialize
new UpdateCheckedTask().execute(); // call after setListAdapter
}
// some implementation
class UpdateChecked extends AsyncTask<Void, Void, List<Integer>> {
#Override
protected List<Integer> doInBackground(Void... params) {
ListAdapter listAdapter = getListAdapter();
if (listAdapter == null) {
return null;
}
List<Integer> positionList = new ArrayList<Integer>();
for (int position = 0; position < listAdapter.getCount(); position++) {
Item item = (Cursor) listAdapter.getItem(position); // or cursor, depends on your ListAdapter implementaiton
boolean checked = item.isChecked() // your model
positionList.add(position, checked);
}
return positionList;
}
#Override
protected void onPostExecute(List<Integer> result) { // setItemChecked in UI thread
if (result == null) {
return;
}
ListView listView = getListView();
for (Iterator<Integer> iterator = result.iterator(); iterator.hasNext();) {
Integer position = iterator.next();
listView.setItemChecked(position, true);
}
}
}
}
I am currently implementing a multi-select ListView for my android app. My aim is to retrieve the selected items from the ArrayAdapter associated with the ListView when clicking the search button.
I am currently stumped on how to do this, I have found stuff online such as trying to set a MultiChoiceModeListener, but this does not seem to come up as an option in Eclipse. I am using Google APIs(level 10), Android 2.3.3 equivalent. Here is the code I have so far:
public class FindPlace extends Activity {
public FindPlace() {}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_places);
Button search = (Button) findViewById(R.id.search);
String[] categories = getResources().getStringArray(R.array.Categories);
ArrayAdapter ad = new ArrayAdapter(this,android.R.layout.simple_list_item_multiple_choice,categories);
final ListView list=(ListView)findViewById(R.id.List);
list.setAdapter(ad);
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { }
});
}
}
Slightly more efficiently / correctly:
SparseBooleanArray checked = listView.getCheckedItemPositions();
for (int i = 0; i < checked.size(); ++i)
{
if (checked.valueAt(i))
{
int pos = checked.keyAt(i);
doSomethingWith(adapter.getItem(pos));
}
}
Use the method getCheckedItemPosition().
take the count of the selected item in the int and make for loop like below.
int len = listView.getCount();
SparseBooleanArray checked = listView.getCheckedItemPositions();
for (int i = 0; i < len; i++){
if (checked.get(i)) {
String item = cont_list.get(i);
/* do whatever you want with the checked item */
}
}