This is the first grid where I selected
the problem is:
when I scroll down, here random images are getting selected
I used glide library for grid view. Here's the Java Code for Multiple selection:
mgridview.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode actionMode, int i, long l, boolean b) {
if (sel_tab2_images.contains(tab2_images.get(i))) {
sel_count = sel_count - 1;
actionMode.setTitle(sel_count + " images selected");
sel_tab2_images.remove(tab2_images.get(i));
viewprev = mgridview.getChildAt(i - mgridview.getFirstVisiblePosition());
viewprev.setBackgroundColor(Color.WHITE);
viewprev.setAlpha(1f);
if(Build.VERSION.SDK_INT>=23) {
viewprev.setForeground(null);
}
} else {
sel_count = sel_count + 1;
actionMode.setTitle(sel_count + " images selected");
sel_tab2_images.add(tab2_images.get(i));
viewprev = mgridview.getChildAt(i - mgridview.getFirstVisiblePosition());
if (viewprev != null) {
viewprev.setAlpha(0.5f);
//ImageView imageView=viewprev.findViewById(R.id.tick);
//Resource(R.drawable.ic_save_black_24dp);
if(Build.VERSION.SDK_INT>=23) {
viewprev.setForeground(getResources().getDrawable(R.drawable.ic_check_white_24dp));
}
}
else
Toast.makeText(getContext(), "Error Occured", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = actionMode.getMenuInflater();
inflater.inflate(R.menu.context_action_bar, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
int del_count = 0;
switch (menuItem.getItemId()) {
case R.id.delete_action_bar:
for (String sel : sel_tab2_images) {
file = new File(sel);
if (file.exists()) {
file.delete();
tab2_images.remove(sel);
if (tab1_fragment.tab1_images.contains(sel)) {
tab1_fragment.tab1_images.remove(sel);
}
if (tab3_fragment.spam_list.contains(sel)) {
tab3_fragment.spam_list.remove(sel);
}
UpdateGallery(sel);
/*
int pos_1=tab2_images.indexOf(sel);
tab2_images.remove(sel);
adapter.notifyDataSetChanged();
viewprev=mgridview.getChildAt(pos_1);
viewprev.setBackgroundColor(Color.WHITE);
*/
del_count++;
}
}
adapter = new ImageAdapterGridView(getContext());
mgridview.setAdapter(adapter);
Toast.makeText(getContext(), del_count + " images deleted", Toast.LENGTH_SHORT).show();
sel_count = 0;
sel_tab2_images.clear();
actionMode.finish();
break;
}
return true;
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
}
});
return view;
}
Below is the java code for Grid View. I also tried #overriding getItem and getItemId methods but it's not working. This is my first app and I'm still learning. Please help me to fix this!
public class ImageAdapterGridView extends BaseAdapter {
private Context mcontext;
public ImageAdapterGridView(Context c) {
mcontext = c;
}
public int getCount() {
return tab2_images.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertview, ViewGroup parent) {
ImageView imageView;
if(convertview==null){
imageView= new ImageView(mcontext);
imageView.setLayoutParams(new GridView.LayoutParams(280,320));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(16,16,16,16);
}
else{
imageView=(ImageView)convertview;
}
Glide.with(tab2_fragment.this).load("file://" + tab2_images.get(position))
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.skipMemoryCache(true)
.into(imageView);
return imageView;
}
}
#Override
public void onResume() {
super.onResume();
adapter = new ImageAdapterGridView(getContext());
mgridview.setAdapter(adapter);
}
}
You're relying on view in a list. In list views are being reused as they get off screen. So to get this done you have to declare a boolean isSelected per each item (so the best place to do this is in your item model which holds all each grid properties) and make it true as the user select your grid item and always update your view based on that boolean not the view.
Currently your model is holding just the url of your images. If you need to save the isSelected boolean there you should build your model object like:
public class ImageModel {
public String url;
public boolean isSelected;
}
And then use the field objects in your grid list:
public void onItemCheckedStateChanged(ActionMode actionMode, int i, long l, boolean b) {
ImageModel image = tab2_images.get(i);
if (image.isSelected) {
// Image is selected you need to deselect it
} else {
// Image is not selected you need to select it
}
}
In your adapter:
public View getView(int position, View convertview, ViewGroup parent) {
// Your view construction code
ImageModel image = tab2_images.get(i);
if (image.isSelected) {
// Show your check image view
} else {
// Image is not selected yet, hide your check image view
}
}
I hope this helps but grid view is considered deprecated, try to consider using RecyclerView which is more efficient and fast.
Related
I'm having an issue with a long press on a row to get highlighted.
I looked over how to handle the single click to lead to another activity and a long press to get the contextual action bar comes up. I decided to switch the listview choice by ListView.CHOICE_MODE_MULTIPLE_MODAL and ListView.CHOICE_MODE_NONE to let the built in android methods to do their work on selected rows. The single click is working as it is intended.
The multiple modal is working and the contextual action bar is showing the number of the notes selected yet the rows aren't highlighted. I have checked the theme and it doesn't work either for Theme.AppCompat and Theme.AppCompat.Light.
Here are the code -
Classes
MainActivity extends AppCompatActivity {}
ObjectListFragment extends ListFragment implements
AdapterView.OnItemLongClickListener, AbsListView.MultiChoiceModeListener {}
NoteListAdapter extends ArrayAdapter<NoteTO> {}
initialization of listeners and other objects in ListFragment
//get the data
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LogUtils.LOGD(getClass().getSimpleName(), "onViewCreated");
ListView listView = getListView();
listView.setOnItemLongClickListener(this);
listView.setMultiChoiceModeListener(this);
int choiceMode = (savedInstanceState == null ? ListView.CHOICE_MODE_NONE : savedInstanceState.getInt(STATE_CHOICE_MODE));
listView.setChoiceMode(choiceMode);
}
Action mode methods, long press method and private methods
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
l.setItemChecked(position, true);
NoteTO note = (NoteTO) l.getItemAtPosition(position);
Intent i = new Intent(getActivity(), NoteActivity.class);
NotePreferences.setNote(getActivity(), note);
AppPreferences.setActionFlag(getActivity(), AppConstants.ACTION_UPDATE);
startActivityForResult(i, 1);
}
#Override
public void onItemCheckedStateChanged(ActionMode actionMode, int i, long l, boolean b) {
if (mActiveMode != null) {
updateSubtitle(actionMode);
}
}
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.contextual_menu, menu);
this.mActiveMode = actionMode;
updateSubtitle(mActiveMode);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
boolean result = performActions(menuItem);
updateSubtitle(mActiveMode);
return(result);
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
if (mActiveMode != null) {
mActiveMode = null;
getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
getListView().setAdapter(getListView().getAdapter());
}
}
public boolean performActions(MenuItem item) {
List<NoteTO> list = listAdapter.getList();
Set<Integer> positionSet = listAdapter.getCurrentCheckedPosition();
Integer[] positions = listAdapter.getCurrentCheckedPosition().toArray(new Integer[positionSet.size()]);
if(item.getItemId() == R.id.item_delete) {
List<NoteTO> notesToBeDeleted = new ArrayList<NoteTO>();
String text = "";
for(int i = 0; i < positions.length; i++) {
NoteTO note = (NoteTO) list.get(positions[i]);
notesToBeDeleted.add(note);
}
task = new ObjectListFragment.deleteNotesTask().execute(notesToBeDeleted);
return true;
}
else if(item.getItemId() == R.id.item_share) {
String text = "";
for(int i = 0; i < positions.length; i++) {
NoteTO note = (NoteTO) list.get(positions[i]);
text = text + note.getBody() + "\r\n"+ "\r\n";
}
shareNotes(text);
return true;
}
return false;
}
private void updateSubtitle(ActionMode mode) {
mode.setSubtitle("(" + getListView().getCheckedItemCount() + ")");
}
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setItemChecked(position, true);
return(true);
}
Adapter - there isn't any code that overwrite up the selectors of the rows.
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View row = super.getView(position, convertView, parent);
NoteHolder holder = (NoteHolder) row.getTag();
if(holder == null) {
holder = new NoteHolder(row);
row.setTag(holder);
}
NoteTO note = getItem(position);
if(mSettings.getListSingleLine() == 0) {
holder.textviewNote.setEllipsize(null);
holder.textviewNote.setSingleLine(false);
}
else {
holder.textviewNote.setEllipsize(TextUtils.TruncateAt.END);
holder.textviewNote.setSingleLine();
}
holder.textviewNote.setText(note.getBody());
holder.textviewNote.setTextSize(getmSettings().getListViewTextSize());
holder.textviewNote.setTypeface(getmSettings().getGeneralFontStyleTypeFace());
//holder.textviewNote.setBackgroundColor(ContextCompat.getColor(context, android.R.color.background_dark));
//holder.textviewNote.setBackground(selector);
//arraylist has containers to get the boolean of the position
if (mSelection.get(position) != null) {
//holder.textviewNote.setSelected(true);
//holder.textviewNote.setBackgroundColor(ContextCompat.getColor(context, android.R.color.holo_blue_light));
//holder.textviewNote.setTextColor(mSettings.getListViewTextColor());
//holder.textviewNote.setBackground(selector);
}
return row;
}
I found the solution, I overlooked the styles where will get the highlighted rows -
<item name="android:background">?android:attr/activatedBackgroundIndicator</item>
Thanks to
Highlight custom listview item when long click
and
Commonsware - The Busy Coder's Guide to Android Development
I am developing a gallery-like Activity. Everything runs fine but there is a key functionality which is missing and I couldn't find a decent answer or explanation. What I need is to give the user the ability to select multiple items by long clicking on them.
Here is the desired result:
You can clearly see the selected pics and the options in the ActionBar.
My setup is this:
1.I have a GridView in my XML:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp"
android:stretchMode="columnWidth"
android:gravity="center"/>
2.It is attached to a class, which extends BaseAdapter and loads images using Picasso:
public class GalleryAdapter extends BaseAdapter {
Context mContext;
List<String> mDataset;
public GalleryAdapter(Context context, List<String> dataset) {
mContext = context;
mDataset = dataset;
}
#Override
public int getCount() {
return mDataset.size();
}
#Override
public Object getItem(int position) {
return mDataset.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if(convertView == null){
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(200,200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8,8,8,8);
} else {
imageView = (ImageView) convertView;
}
//TODO: REMOVE INTEGER.VALUEOFF. IT'S MADE FOR MOCK
Picasso.with(mContext).load(Integer.valueOf(mDataset.get(position))).fit().into(imageView);
return imageView;
}
}
3.It is attached to the Activity:
//Get images paths
List<String> data = getImagesPath(this);
List<String> sortedData = new ArrayList<>();
for(String file : data){
sortedData.add(0, file);
}
GalleryAdapter adapter = new GalleryAdapter(this, sortedData);
mGallery.setAdapter(adapter);
From now on the struggle begins:
I tried making my item in the GridView to implement Checkable:
public class CheckableItem extends LinearLayout implements Checkable{
private boolean mIsChecked = false;
private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
public CheckableItem(Context context) {
super(context);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked())
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
return drawableState;
}
#Override
public void setChecked(boolean checked) {
mIsChecked = checked;
refreshDrawableState();
}
#Override
public boolean isChecked() {
return mIsChecked;
}
#Override
public void toggle() {
setChecked(!isChecked());
refreshDrawableState();
}
Then I load it in my XML and added .setChoiceMode(GridView.CHOICE_MODE_MULTIPLE) to my GridView in the Activity. Nothing Happened.
Added MultiChoiceModeListener:
class MultiChoiceListener implements GridView.MultiChoiceModeListener{
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
int selectCount = mGallery.getCheckedItemCount();
switch (selectCount) {
case 1:
mode.setSubtitle("One item selected");
break;
default:
mode.setSubtitle("" + selectCount + " items selected");
break;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.setTitle("Select Items");
mode.setSubtitle("One item selected");
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
}
Then added it to my gridView .setMultiChoiceModeListener(newMultiChoiceListener()); but still no results.
Can someone propose a way to achieve this item selecting behavior in GridView? I'd like to use the native Android API, no 3rd party libraries.
I think Checkable and the rest that I see in your code is a bit of an overkill...When I want to implement something like that I just add another field in the class of the object that is shown in the GridView/ListView which stores the checked state of the object. example:
class Image {
Bitmap bm;
boolean isChecked=false;
public Image(Bitmap bm){
this.bm=bm;
}
public boolean isChecked(){
return isChecked;
}
public void toggleChecked(){
isChecked = !isChecked;
}
}
and feed an ArrayList to the adapter. an in the getView method of the adapter I do something like this;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(images.get(position).isChecked()){
//show the overlay view that suggests the item is selected
}
else{
//hide the overlay view
}
}
finally in the onItemClickListener of the ListView
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
images.get(position).toggleChecked();
listView.getAdapter().notifyDataSetChanged();
}
});
I have a listview in fragment and my problem is when I select items on listview then it's fine, but when I scroll my listview then item's background is checked for another items, but I don't want that. You can see my image, first I select 3 items (Browser, Calendar, Contact), when I scroll listview then 2 items (Dev tool, Camera) have a changed background, if I continue scroll then listview has more items like that.
Here is my code:
#SuppressLint("NewApi") public class Tab2 extends Fragment{
private PackageManager packageManager = null;
private List<ApplicationInfo> applist = null;
public static ApplicationAdapter listadaptor = null;
public static ListView list;
private ActionMode acMode;
private int counterChecked = 0;
private SparseBooleanArray sp;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab2test,container,false);
list = (ListView)v.findViewById(R.id.list_view2);
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
list.setItemsCanFocus(false);
packageManager = getActivity().getPackageManager();
applist = checkForLaunchIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listadaptor = new ApplicationAdapter(getActivity().getApplicationContext(),R.layout.snippet_list_row, applist);
list.setAdapter(listadaptor);
sp = list.getCheckedItemPositions();
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//Here i set item's color and unselected color
view.setBackgroundColor(sp.get(position)? 0x9934B5E4: Color.WHITE);
if(counterChecked<1){
acMode = ((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback);
}
String str="";
int i=0;
for(i=0;i<sp.size();i++)
{
if(sp.valueAt(i)){
str+=sp.keyAt(i)+",";
}
}
if(list.isItemChecked(position)){
Log.d("list1", String.valueOf(position));
list.setItemChecked(position, true);
counterChecked++;
}else{
list.setItemChecked(position, false);
counterChecked--;
}
if(counterChecked<1){
mActionModeCallback.onDestroyActionMode(acMode);
}
}
});
return v;
}
private List<ApplicationInfo> checkForLaunchIntent(List<ApplicationInfo> list) {
ArrayList<ApplicationInfo> applist = new ArrayList<ApplicationInfo>();
for (ApplicationInfo info : list) {
try {
if(isSystemPackage(info)){
if (null != packageManager.getLaunchIntentForPackage(info.packageName)) {
applist.add(info);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return applist;
}
private boolean isSystemPackage(ApplicationInfo AInfo) {
return ((AInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true
: false;
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback(){
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.cab_menu, menu);
MainActivity.toolbar.setVisibility(View.GONE);
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
mode.finish();
MainActivity.toolbar.setVisibility(View.VISIBLE);
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
// TODO Auto-generated method stub
return false;
}
};
}
You actually trigger OnItemClickListener when scrolling which causes a multiple select for items that you didn't want to include.
A better approach would be using a checkBox inside your listView Item and mark the item as selected when the check box is checked: check out this link on how to Get Selected Item Using Checkbox in Listview.
If you incest on using onClick then you can implement longClickListener on your listView Items which may prevent get item selected when scrolling but my advice to you is to go with checkBoxes.
OnLongClickListener Implementation:
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View v,
int index, long arg3) {
// TODO Auto-generated method stub
String str=listView.getItemAtPosition(index).toString();
return true;
}
});
I'm trying to create ListView with installed apps. User selects apps inside wizard (basically viewpager).
My plan is to create a list of custom views (icon, name, package) that will allow to select more than one item. Unfortunatelly checkboxes won't work, because I need this place for another functionality. So, I'll change the background of the element.
So, I found a solution on stackoverflow and changed it a bit.
Firstly - main activity with this list.
public class MainActivity extends ListActivity {
private static final String TAG = MainActivity.class.getName();
private ApplicationsAdapter applicationsAdapter;
private void getAppList(){
//get apps asynch
createList(list);
}
private void createList(ArrayList<ApplicationItem> list){
applicationsAdapter = new ApplicationsAdapter(this, R.layout.application_list_item, list);
setListAdapter(applicationsAdapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
private int nr = 0;
#Override
public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.cabselection_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(android.view.ActionMode mode) {
nr = 0;
applicationsAdapter.clearSelection();
}
#Override
public void onItemCheckedStateChanged(android.view.ActionMode mode, int position, long id, boolean checked) {
if (checked) {
nr++;
applicationsAdapter.setNewSelection(position, checked);
L.d(TAG, applicationsAdapter.getItem(position).getAppName());
} else {
nr--;
applicationsAdapter.removeSelection(position);
}
mode.setTitle(nr + " rows selected!");
}
});
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getAppList();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
ApplicationItem item = (ApplicationItem)l.getAdapter().getItem(position);
L.d(TAG + "onListItemClick", applicationsAdapter.getItem(position).getAppName());
l.setItemChecked(position, !applicationsAdapter.isPositionChecked(position));
}
}
In my case, normally this whole thing is inside a fragment, inside the viewpager. For the sake of clarity I changed this into typical activity.
Now, the adapter:
public class ApplicationsAdapter extends ArrayAdapter<ApplicationItem> {
// private HashMap<ApplicationItem, Boolean> objects;
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
public ApplicationsAdapter(Context context, int textViewResourceId, ArrayList<ApplicationItem> objects) {
super(context, textViewResourceId, objects);
//this.objects = objects;
}
public void setNewSelection(int position, boolean value) {
mSelection.put(position, value);
notifyDataSetChanged();
}
public boolean isPositionChecked(int position) {
Boolean result = mSelection.get(position);
return result == null ? false : result;
}
public Set<Integer> getCurrentCheckedPosition() {
return mSelection.keySet();
}
public void removeSelection(int position) {
mSelection.remove(position);
notifyDataSetChanged();
}
public void clearSelection() {
mSelection = new HashMap<Integer, Boolean>();
notifyDataSetChanged();
}
public ApplicationItem getItem(int position){
return super.getItem(position);
}
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.application_list_item, null);
}
ApplicationItem item = super.getItem(position);
if(item != null){
TextView appName = (TextView) v.findViewById(R.id.appName);
TextView appPackage = (TextView) v.findViewById(R.id.appPackage);
ImageView appIcon = (ImageView) v.findViewById(R.id.appIcon);
if (appName != null){
appName.setText(item.getAppName());
}
if (appPackage != null){
appPackage.setText(item.getPackageName());
}
if (appIcon != null){
appIcon.setImageDrawable(item.getIcon());
}
}
v.setBackgroundColor(Color.parseColor("#00FFFFFF")); //default color
if (mSelection.get(position) != null) {
v.setBackgroundColor(Color.BLUE);// this is a selected position so make it red
}
return v;
}
}
THE PROBLEM:
ActionMode is nice, however I'm not sure how to keep selected elements after it's destroy.
Normally inside onDestroyActionMode I'm clearing the selection. Great, so I'll just delete that. Now after clicking the "tick" symbol all apps are still selected. However, getting back to them is now problematic, because ActionMode will only "fire up" when clicking on unselected element.
So - how should I handle that?
Ha, the answer was quite simple. I should have thought about it yesterday, but apparently I was a bit too exhausted.
First of all, I changed the mode of listview into
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
And deleted setMultiChoiceModeListener() and I'm only using
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
ApplicationItem item = (ApplicationItem)l.getAdapter().getItem(position);
L.d(TAG + "onListItemClick", applicationsAdapter.getItem(position).getAppName());
boolean checked = item.isSelected();
if (!checked) {
item.setSelected(true);
applicationsAdapter.setNewSelection(position, checked);
L.d(TAG, applicationsAdapter.getItem(position).getAppName());
} else {
item.setSelected(false);
applicationsAdapter.removeSelection(position);
}
}
That simple.
Apparently, ActionMode may be fun, but it wasn't the right tool for this job.
And also - adapter from first post can be used as a example of multiselect listView that changes backgrounds instead of checkboxes. Apparently I couldn't find anything simple enough like that.
I have spinner and my custom spinner adapter.
In some reasons spinner (when user change item selection) dont fire OnItemSelected in my adapter and does not call getView so i cannt render currently selected item ( spinner firing internal item click and set current item correctly)
If User open "software keyboard" spinner works perfectly! It always refreshing spinner content.
I can provide more info if necessary
Any suggestion ?
public class DictionarySpinnerAdapter implements SpinnerAdapter, OnItemSelectedListener{
public DictionarySpinnerAdapter(BaseActivity ctx, Spinner owner)
{
this.ctx = ctx;
li = (LayoutInflater) ctx.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
Owner = owner;
Owner.setClickable(true);
Owner.setOnItemSelectedListener(this);
}
#Override
public int getCount() {
return (dictionaries == null ) ? 0 : dictionaries.size() + offset ;
}
#Override
public Object getItem(int position) {
if ( position > (offset - 1) )
return dictionaries.get(position - offset);
else
return null;
}
#Override
public long getItemId(int position) {
if ( position > (offset - 1) )
return dictionaries.get(position-offset).GetKey();
else
return -1;
}
#Override
public int getItemViewType(int position) {
return 1;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//rendering my items...
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public boolean isEmpty() {
return ( dictionaries != null ) ? false : true;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
//rendering dropdowns
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
SetSelectedItem((int)id);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
SetSelectedItem(null);
}
public void SetSelectedItem(Integer byKey)
{
if ( byKey == null|| (byKey == -1 && allowNull))
{
selectedPosition = 0;
if ( allowNull)
selectedKey = -1;
else
if (dictionaries!=null&& dictionaries.size()>0)
selectedKey = dictionaries.get(0).GetKey();
if (selectedKey > -1)
firstSelected = true;
handleItemClick(selectedKey);
Owner.setSelection(selectedPosition);
return;
}
for(Dictionary entry : dictionaries )
if ( entry.GetKey() == byKey.intValue() )
{
selectedKey = byKey;
selectedPosition = dictionaries.indexOf(entry) + offset;
handleItemClick(selectedKey);
break;
}
// Log.i("MAH", "setSelectedItem("+selectedPosition+")");
firstSelected = true;
Owner.setSelection(selectedPosition);
}
}
EDIT:
After some debugging i think in this code (Absspinner.java) is problem.
#Override
public void setSelection(int position) {
setNextSelectedPositionInt(position); //works fine
requestLayout(); // ??
invalidate(); // ??
}
EDIT2:
Spinner is inside TableLayout if I move it outside tablelayout its works fine. So my new question is: how i can refresh view inside TableLayout ?