Go back after Searching with setActionView in Android using ActionBarSherlock - android

With this code (taken from ABS examples) I'm able to add a "Search" icon in my ActionBar which will display an EditText when clicked (to search in a list):
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, searchId, Menu.NONE, R.string.menu_search)
.setIcon(android.R.drawable.ic_menu_search)
.setActionView(R.layout.collapsible_edittext)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
return true;
}
With this code I'm able to show a different layout after tapping the "Search" icon:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case searchId:
search = (EditText) item.getActionView();
search.addTextChangedListener(filterTextWatcher);
search.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
setContentView(R.layout.search);
this.allSongs = data.getSongs();
ListView list = (ListView) findViewById(R.id.songList);
list.setAdapter(new SongAdapter(this, this.allSongs));
}
return true;
}
With this code I'm able to handle my search:
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
List<Song> results = new ArrayList<Song>();
Locale locale = Locale.getDefault();
for (Song song : allSongs) {
if (song.getTitle().toLowerCase(locale).contains(s.toString().toLowerCase(locale)))
results.add(song);
}
ListView list = (ListView) findViewById(R.id.songList);
list.setAdapter(new SongAdapter(ctx, results));
}
};
When the user taps the "Search" icon, the EditText appears in ActionBar and the App Icon gains the "back" left arrow.
If the user taps "Back" button or taps the ActionBar icon (with left arrow), the EditText disappears.
I'd like to intercept this event (no, onOptionsItemSelected() doesn't fire this time) and show the previous layout, in addition to hiding the EditText.
Note: I need API8 (Android 2.2) compatibility!
Thank you!

When using an ActionView, tapping "up" or "back" doesn't result in an Ancestral Navigation (which can be handled by onOptionsItemSelected) but results in a Collapsible Action event.
Found here on Android Developers.
Handling collapsible action views
If you need to update your activity based on the visibility of your
action view, you can receive callbacks when it's expanded and
collapsed by defining an OnActionExpandListener and registering it
with setOnActionExpandListener(). For example:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options, menu);
MenuItem menuItem = menu.findItem(R.id.actionItem);
...
menuItem.setOnActionExpandListener(new OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Do something when collapsed
return true; // Return true to collapse action view
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Do something when expanded
return true; // Return true to expand action view
}
});
}
So, to answer to my question, I was searching for onMenuItemActionCollapse event.
PS: for better consistency I should move my case searchId: from onOptionsItemSelected to onMenuItemActionExpand

For the Home button, can I assume that you called
mActionBar.setHomeButtonEnabled(true);
when setting up the Sherlock Action Bar in onCreate()? I believe that's required in order to get onOptionsItemSelected() callbacks with an item ID of android.R.id.home when the home button is clicked.
For the back button, I think you just need to override onKeyDown in your activity:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
// Do something
return true;
}
return super.onKeyDown(keyCode, event);
}

Related

Toolbar won't disappear in action mode

I am trying to implement the feature that, when I am long clicking a list item, the action mode shall start and it shall be possible to delete one or more items.
I am starting in DocumentsActivity a search, which starts a Fragment DocumentsFragment with a ListView and their items. The ListAdapter is initialized and set via method call setListAdapter(this.documentsAdapter) in onCreate of Fragment. I set various listeners on the listview in the onActivityCreated in the Fragment:
public void onActivityCreated(Bundle savedInstanceState) {
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
getListView().setItemChecked(position, true);
return true;
}});
getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
menu.clear();
((DocumentsActivity)getActivity()).getMenuInflater().inflate(R.menu.documents_context_menu, menu);
return true;
}
});
super.onActivityCreated(savedInstanceState);
}
When long clicking on a listitem the action mode gets started and the menu documents_context_menu appears to be the action bar. But the problem is, the action bar appears above the toolbar and the toolbar won't disappear (see the picture).
I've tried to call getSupportActionBar().hide() or set it to null or even use another style/theme. It all didn't work. Sometimes the blue toolbar was completely white, but that is all.
I have absolutely no idea why the toolbar won't disappear. May you give some advice?
Thanks in advance!
_____ Update 1 _____
This is the styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:fitsSystemWindows">true</item>
<item name="colorAccent">#color/darkblue100</item>
<item name="android:actionOverflowButtonStyle">#style/ActionButtonOverflow</item>
<item name="actionOverflowButtonStyle">#style/ActionButtonOverflow</item>
<item name="android:actionMenuTextColor">#color/black</item>
</style>
And this is how the action bar is set in the Activity:
protected void onCreate(Bundle savedInstanceState) {
handleIntent(getIntent());
requestWindowFeature(5);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_documents);
Toolbar mToolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(mToolbar);
args = getIntent().getExtras();
if (findViewById(R.id.container_documents) != null && savedInstanceState == null) {
showDocumentsFragment();
}
}
As pointed out in the link provided in comments you just need to add following line to your AppTheme style:
<item name="windowActionModeOverlay">true</item>
It just indicates that action mode should overlay window content instead of pushing it down,it tells that you don't need any reserved space for action mode.
Well as far as i go through your code and understand it, you have done everything that you provided your Toolbar to act as ActionBar and used .NoActionBar theme except according to Android Developer you should also set the windowActionBar attribute to false in your style. enter link description here Second para clears it out.
I hope it helps!
all of this answers are fine you should try them but what you need is a ContextualMenu so you should first add views to a registerForContextMenu() so menu knows which menus are contextual then implement the onCreateContextMenu of your Activity
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
then implement onContextItemSelected() like this :
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit:
editNote(info.id);
return true;
case R.id.delete:
deleteNote(info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
then you have to perform an action on views and implement AbsListView.MultiChoiceModeListener then call setChoiceMode() with the CHOICE_MODE_MULTIPLE_MODAL argument. like this :
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Here you can do something when items are selected/de-selected,
// such as update the title in the CAB
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.menu_delete:
deleteSelectedItems();
mode.finish(); // Action picked, so close the CAB
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.context, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// Here you can make any necessary updates to the activity when
// the CAB is removed. By default, selected items are deselected/unchecked.
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an <code>invalidate()</code> request
return false;
}
});
all of what i said and ultimately more, you can find in this android developer documentation
Add:
//Set action mode null after use
public void setNullToActionMode() {
if (mActionMode != null)
mActionMode = null;
}
Or:
//Remove selected selections
public void removeSelection() {
mSelectedItemsIds = new SparseBooleanArray();
}
Actually the issue were caused by different things.
First, the windowActionBar was set true, also was the attribute fitsSystemWindows.I deleted both lines in styles.xml.
Then there was in the activity layout the attribute layout_marginTop="?actionBarSize" I did not see, following in complete confusion. But this attribute needs to be there so I am handling it in the method onActivityCreated when onCreateActionMode and onDestroyActionMode are called.
After that all I had the automagically problem that the listview items disappeared. I fixed it by commiting my fragment again in onDestroyActionMode.
public void onActivityCreated(Bundle savedInstanceState) {
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {...}
});
getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
LinearLayout ll = ((DocumentsActivity)getActivity()).findViewById(R.id.container_documents);
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) ll.getLayoutParams();
params.setMargins(0, 0, 0, 0);
ll.setLayoutParams(params);
((DocumentsActivity)getActivity()).getSupportActionBar().hide();
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.documents_context_menu, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) ll.getLayoutParams();
params.setMargins(0, R.attr.actionBarSize, 0, 0);
ll.setLayoutParams(params);
((DocumentsActivity)getActivity()).getSupportActionBar().show();
if (getFragmentManager() != null)
getFragmentManager()
.beginTransaction()
.detach(this)
.attach(this)
.commit();
}
});
super.onActivityCreated(savedInstanceState);
}
In Kotlin, assuming that your Activity extends from AppCompatActivity
You should get the instance of the support action bar and call the methods
supportActionBar?.show() or supportActionBar?.hide()
If you're using a fragment, you can access the action bar from the Fragment's activity instance
(activity as AppCompatActivity).supportActionBar?.show()

Focus ListView Items on Button Click

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

How to properly trasfer contextual action bar functionality to a toolbar

I have an activity that shows some data on a listview. when one long press an item, i have implemented a toolbar that becomes visible and allows the user to perform some actions. i don't want this actions to be at contextual action bar since my actionbar displays some information that show not be overtaken by contextual action bar
When one long press a list item, my toolbar become visible and you can do some actions like deleting.
desired output
contextual action bar should not show up when you long press a list item
when you press your phone back button when you have not performed any action but just selected list items. list selection should dissapear BUT NOT exiting the activity
Problems
after long pressing a list item, contextual action bar appears
after performing the action(e.g delete), contextual action bar still remains visible.
When i select list items and just click back button,my activity is exited instead of just disselecting list selections
here's how am handling long clicks on my listview
private class DataSelector implements AbsListView.MultiChoiceModeListener{
android.view.ActionMode mode;
#Override
public void onItemCheckedStateChanged(android.view.ActionMode mode, int position, long id, boolean checked) {
adapter.toggleSelection(position);
}
#Override
public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
this.mode =mode;
SelectionListener selectionListener = new SelectionListener();
toolbar.setVisibility(View.VISIBLE);
Button delete = (Button) toolbar.findViewById(R.id.Delete);
delete.setOnClickListener(selectionListener);
return true;
}
private class SelectionListener implements View.OnClickListener{
public void onClick(View v){
switch(v.getId()){
case R.id.Delete:
SparseBooleanArray selected = adapter.getSelecteItemsIds();
ArrayList<Long> dataIds = new ArrayList<>();
for(int i =(selected.size()-1); i>=0; i--){
if(selected.valueAt(i)){
int key = selected.keyAt(i);
d(" key is: " + key);
CountryData data = adapter.getItem(key);
long id = data.getId();
if(id != 0){
dataIds.add(id);
}
adapter.remove(data);
}
}
onDestroyActionMode(mode);
break;
}
}
}
#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) {
adapter.removeSelection();
toolbar.setVisibility(View.INVISIBLE);
}
}
Question
how can i achieve the above desired output?

Extracting words from TextView after click/press on them

is there any easy way to select whole words from TextView by touching them? This functionality is in dictionary app ColorDict.
Search for word "word"
Select word "theorem" and it now appears in the search box so I can search it faster by clicking on search.
I want to be able to select those words. That ScrollView which is on top is misleading. It appears after selecting "Select a word" in dialog which appears after long press on something in TextView (you can see word "theorem" on the bottom - long press on "theorem").
Thank you for suggestions.
Try setting this attribute to your TextView:
android:textIsSelectable="true"
EDIT:
private static final int MENU_ITEM_ID = 0x42;
private TextView targetTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
targetTextView = (TextView) findViewById(R.id.target_textview);
targetTextView.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// you can remove the default menu items if you wish
menu.removeItem(android.R.id.selectAll);
menu.removeItem(android.R.id.cut);
menu.removeItem(android.R.id.copy);
return true;
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
/*
* called when the action mode is created. Here you can
* generate action buttons for this action mode.
* */
menu.add(0, MENU_ITEM_ID, 0, "Menu Item").setIcon(android.R.drawable.ic_dialog_alert);
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// called when the action mode is about to be destroyed
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case MENU_ITEM_ID:
int start = targetTextView.getSelectionStart();
int end = targetTextView.getSelectionEnd();
CharSequence selectedText = targetTextView.getText().subSequence(start, end);
Toast.makeText(MainActivity.this, selectedText, Toast.LENGTH_SHORT).show();
mode.finish();
return true;
default:
break;
}
return false;
}
});
}

Android: AutoCompleteTextView as Collabsible ActionItem Keyboard not shown on Focus

I have an AutoCompleteTextView as Collabsible ActionItem, and i want the keyboard to be displayed when it gets expanded and focussed. This is my code in onCreateOptionsMenu():
menu.add("Search")
.setIcon(R.drawable.ic_search)
.setActionView(R.layout.collapsible_edittext)
.setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS
| MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
final MenuItem searchMenuItem = menu.getItem(0);
searchMenuItem.setOnActionExpandListener(new OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
AutoCompleteTextView autoCompleteTextView = (AutoCompleteTextView) item
.getActionView();
autoCompleteTextView
.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
Log.d(TAG, "onFocusChange: " + hasFocus);
if (hasFocus) {
mInputManager.showSoftInput(v,
InputMethodManager.SHOW_FORCED);
} else {
mInputManager.hideSoftInputFromWindow(
v.getWindowToken(), 0);
}
}
});
autoCompleteTextView.requestFocus();
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
AutoCompleteTextView autoCompleteTextView = (AutoCompleteTextView) item
.getActionView();
autoCompleteTextView.clearFocus();
autoCompleteTextView.setText("");
return true;
}
});
When I click on the ActionItem the first time, no keybord is shown. After collapsing and then clickin on the Item the keyboard gets shown. But I want the keyboard to be shown the first time the user clicks on the action item.
I'm using ActionBarSherlock if that matters.
So why is the keyboard not shown on first expansion? Any ideas?
Have you tried manually setting the focus to the edit text and manually showing the keyboard in the onOptionsItemSelected method?
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_SEARCH:
// select edittext here
// show keyboard here
return true;
}
return super.onOptionsItemSelected(item);
}
EDIT: I found this code to show the keyboard from here:
https://code.google.com/p/android-batavierenrace/source/browse/trunk/BataApp/src/com/ut/bataapp/activities/TeamsActivity.java
I tested it on my app and it works...
public static void setKeyboardFocus(final EditText primaryTextField) {
(new Handler()).postDelayed(new Runnable() {
public void run() {
primaryTextField.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
primaryTextField.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP , 0, 0, 0));
}
}, 100);
}

Categories

Resources