When i do a long click on an item in the list view(which triggers the contextual action bar to show up), the list view automatically scrolls to the end. This behaviour is very irritating if the user had selected an item after scrolling up.
Using breakpoints i verified that this happens after onItemCheckedStateChanged() in the MultiChoiceModeListener implementation has completed. But i am not sure what code gets executed after this that causes the behaviour.
Removing the transcriptMode attribute from the list view layout resolves the issue. But i don't want to remove it as it is required to scroll automatically when the data has changed in the cursor. Any ideas what is causing the problem?
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Get the chat messages list view from the layout
lv_chatMessages = (ListView) getActivity().findViewById(
R.id.listview_chat);
// Instantiate the adapter for the chat messages
adpt_chat = new ChatMessagesAdapter(getActivity());
// connect the adapter to the list view
lv_chatMessages.setAdapter(adpt_chat);
//Implement multi choice mode listener for the list view
//only if Android API 11 or higher
if (Utils.hasHoneycomb()) {
//Enable selection of multiple chat messages
lv_chatMessages.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
//Handle Action mode events
lv_chatMessages
.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public boolean onActionItemClicked(ActionMode mode,
MenuItem item) {
switch(item.getItemId()){
case R.id.delete_menu :
long[] selected_IDs = lv_chatMessages.getCheckedItemIds();
int deletedRows = deleteMessages(selected_IDs);
Toast.makeText(getActivity(), deletedRows + " message(s) deleted",
Toast.LENGTH_SHORT).show();
return true; // true indicates the menu selection is handled. no further
// system handling required
default :
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode,
Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.chatsession_contextmenu, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode arg0) {
// TODO Auto-generated method stub
}
#Override
public boolean onPrepareActionMode(ActionMode arg0,
Menu arg1) {
// TODO Auto-generated method stub
return false;
}
#Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
mode.setTitle(lv_chatMessages.getCheckedItemCount() + " selected");
}
});
}
...
..
}
The list view layout :
<ListView
android:id="#+id/listview_chat"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_alignParentTop="true"
android:transcriptMode="alwaysScroll"
android:stackFromBottom="true"
android:layout_above="#id/layout_input"
android:divider="#00000000"
/>
Removing the transcriptMode attribute seems to be the only solution. I use the below code whenever i require an automatic scroll to the end :
new Handler().postDelayed(new Runnable(){
public void run(){
lv_chatMessages.setSelection(lv_chatMessages.getCount());
}
},100);
Related
I am working on an android project where I have a grid view and I am setting it up with a MultiChoiceModeListener.
When I long click, it successfully creates the contextual action bar but setting the setBackgroundResource on the initial item that creates the CAB doesn't have any affect, however all subsequent items that are selected, the background resource is successfully applied. Below is the code I am using:
gridView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
gridView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener()
{
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked)
{
Log.d("DirectoryPicker-CAB", "CheckedStateChanged");
//findViewById((int)gridView.getItemIdAtPosition(position)).setBackgroundColor(ContextCompat.getColor(DirectoryPicker.this, R.color.appPrimaryColour));
//Toast.makeText(DirectoryPicker.this, "Item CAB Clicked: Checked: " + (checked ? "true" : "false"), Toast.LENGTH_LONG).show();
Toast.makeText(DirectoryPicker.this, "Position: " + position, Toast.LENGTH_LONG).show();
if (checked)
{
//gridView.getChildAt(position).setBackgroundColor(ContextCompat.getColor(DirectoryPicker.this, R.color.appPrimaryColour));
Log.d("DirectoryPicker-View", gridView.getChildAt(position).toString());
gridView.getChildAt(position).setBackgroundResource(R.color.appPrimaryColour);
mode.invalidate();
directoryAdapter.getItem(position).setSelected(true);
selectedDirectories.add(directoryAdapter.getItem(position));
}
else
{
directoryAdapter.getItem(position).setSelected(false);
FileManager.DirectoryOrFileInfo selectedDirectory = directoryAdapter.getItem(position);
for (int i = 0; i < selectedDirectories.size(); i++)
{
if (selectedDirectories.get(i) == selectedDirectory)
{
selectedDirectories.remove(i);
selectedDirectory.setSelected(false);
}
}
gridView.getChildAt(position).setBackgroundColor(ContextCompat.getColor(DirectoryPicker.this, android.R.color.transparent));
}
mode.setTitle(selectedDirectories.size() + " selected");
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.file_dir_cab_menu, menu);
Log.d("DirectoryPicker-CAB", "OnActionModeCreate");
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
{
return true;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item)
{
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode)
{
selectedDirectories.clear();
}
});
Why does the background resource not get successfully applied for the first item that is long clicked that creates the CAB, but it works fine for all subsequent selections.
I've figured why this isn't working now. When the CAB is created, it triggers the getView function to be called again in my adapter so it ends up resetting the view back to how it was again.
I've therefore changed my adapter instead in the getView method so it checks whether the item is marked as checked, and it sets the background resource.
Is it possible to focus the List View Items through any button click?
Like i want that when user click on Floating Action Button then the listview gets focused. I dont want to show checkbox type layout on button clicked. I just want to show the same like in the screenshot on Button click.
What i did is I put the listview onItemLongClick code in the button click blocks but it doesnot work.
fabButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
listViewMessages.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listViewMessages.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
tv.setText(listViewMessages.getCheckedItemCount()+ " Selected");
}
#Override
public boolean onActionItemClicked(final ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu:
}
});
mode.finish();
return true;
default:
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.contextual, menu);
fabButton.setVisibility(View.INVISIBLE);
fabButtonn.setVisibility(View.VISIBLE);
fabButtonn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
for ( int i=0; i< messageListAdapter.getCount(); i++ ) {
listViewMessages.setItemChecked(i, true);
}
}
});
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
fabButton.setVisibility(View.VISIBLE);
fabButtonn.setVisibility(View.GONE);
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an invalidate() request
return false;
}
});
With this code if user clcik on button then he/she has too long press items again to focus the list items which is not what i want. I want to focus items right when button click. Any explanation or link provided will be helpful
I use GridView and implement multiple select.
When I select the multiple item from GridView , it will show the menu on the top of screen.
But I don't want the menu show on the top .
I set the GridView to CHOICE_MODE_MULTIPLE_MODAL and implement thr MultiChoiceModeListener of class.
Does there has any method can hide the menu when select the multiple item ?
The code of class is like the following
public class LocalFileBrowserFragment extends Fragment implements MultiChoiceModeListener
The code of setup the GridView is like the following:
private GridView fileListView;
fileListView = (GridView) view.findViewById(R.id.browserList) ;
fileListView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
fileListView.setMultiChoiceModeListener((MultiChoiceModeListener)this);
fileListView.setNumColumns(4);
And the code of MultiChoiceModeListener in GridView is like the following:
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
Log.i(TAG, "onCreateActionMode");
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
for (int i = 0; i < fileListView.getCount(); i++) {
fileListView.setItemChecked(i, false);
mSelectMap.clear();
}
mFileListAdapter.notifyDataSetChanged();
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
//Log.i(TAG, "onPrepareActionMode");
return true;
}
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// TODO Auto-generated method stub
mSelectMap.put(position, checked);
mFileListAdapter.notifyDataSetChanged();
}
I set the GridView to CHOICE_MODE_MULTIPLE_MODAL and implement thr MultiChoiceModeListener of class.
I don't want the menu show on the top.
Does there has any method can hide the menu when select the multiple item ?
I solved the problem, I used the following to show the bar.
bar = getActivity().getActionBar();
bar.show();
Save ActionMode as a field of your MultiChoiceModeListener in onCreateActionMode
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
theActionMode = mode;
return true;
}
Then finish the ActionMode in onItemCheckedStateChanged
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
// Your CheckedChange Code......
theActionMode.finish();
}
I have a fragment that contains a ListView, when I try to show a DialogFragment on the top of it the selected list items are deselected. Is it possible to keep the items selected when the DialogFragment appears/disappears?
My Fragment's onCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (DEBUG) {
Log.d(TAG, "BrowserFragment.onCreateView()");
}
View v = inflater.inflate(R.layout.fragment_filebrowser, container,
false);
listView = (ListView) v.findViewById(android.R.id.list);
listView.setAdapter(mAdapter);
listView.setOnItemClickListener(this);
listView.setEmptyView(v.findViewById(android.R.id.empty));
// FOR CONTEXT ACTION MENU
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.contexual, menu);
mode.setTitle("Choose Files");
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
Log.d(TAG, "onDestroyActionMode!");
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_delete:
SimpleDialogFragment
.createBuilder(getActivity(),
getActivity().getSupportFragmentManager())
.setTitle(R.string.delete_files)
.setMessage(R.string.confirm_delete)
.setPositiveButtonText(R.string.yes)
.setNegativeButtonText(R.string.no).show();
mode.finish();
//The rest of the program..
Screenshots:
As you can see in the second screenshot, the listview's selected items have been deselected. How can I prevent that?
UPDATE: I'm using StyledDialogs library
Found the solution, the problem was that i was calling mode.finish() right after the dialogfragment.show(). I stored the ActionMode variable and used it inside my DialogFragments positive button callback to call the .finish() instead and everything is working correctly.
I've a ListActivity
public class MyActivity extends ListActivity{
protected void onCreate(Bundle savedstate){
super.onCreate(savedstate);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
Log.i("xxx", "onPrepareActionMode");
return false;
}
public void onDestroyActionMode(ActionMode mode) {
// TODO Auto-generated method stub
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return true;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
return false;
}
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
Log.i("xxx", "pos: "+position+", checked: "+checked);
mode.setTitle(getListView().getCheckedItemCount()+" checked");
}
});
}
}
Here I can see the items getting checked but background of checked items is not changing. I know a way how to do it, have your CustomAdapter and in getView() set the background of the views that are checked. But I believe there is much simpler way to handle it. Could you tell me if there is anyway to achieve it?
Attaching the Screenshot
Ok, i got the answer by going through the source code of other app which does that. Set a statelist drawable as background for list item. In selector state_activated = true give the background drawable.