In Android 3.0, when you select some text for example, the ActionBar switches to a ContextMenu-like mode, which enables you to do actions with the selected text: copy/share/etc, and a "Done" button appears on the left side to enable the user to leave this mode.
How can I switch the ActionBar into this mode in my app (with my menu items of course)? I just couldn't find this in the docs.
To use the new contextual action bar, see "Enabling the contextual action mode for individual views".
It states:
If you want to invoke the contextual action mode only when the user selects specific
views, you should:
Implement the ActionMode.Callback interface. In its callback methods, you
can specify the actions for the contextual action bar, respond to click events on action items, and handle other lifecycle events for the action mode.
Call startActionMode() when you want to show the
bar (such as when the user long-clicks the view).
For example:
Implement the ActionMode.Callback interface:
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
shareCurrentItem();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
Notice that these event callbacks are almost exactly the same as the callbacks for the options menu, except each of these also pass the ActionMode object associated with the event. You can use ActionMode APIs to make various changes to the CAB, such as revise the title and
subtitle with setTitle() and setSubtitle() (useful to indicate how many items are
selected).
Also notice that the above sample sets the mActionMode variable null when the
action mode is destroyed. In the next step, you'll see how it's initialized and how saving
the member variable in your activity or fragment can be useful.
Call startActionMode() to enable the contextual
action mode when appropriate, such as in response to a long-click on a View:
someView.setOnLongClickListener(new View.OnLongClickListener() {
// Called when the user long-clicks on someView
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
When you call startActionMode(), the system returns
the ActionMode created. By saving this in a member variable, you can
make changes to the contextual action bar in response to other events. In the above sample, the
ActionMode is used to ensure that the ActionMode instance
is not recreated if it's already active, by checking whether the member is null before starting the
action mode.
Enabling batch contextual actions in a ListView or GridView
If you have a collection of items in a ListView or GridView (or another extension of AbsListView) and want to
allow users to perform batch actions, you should:
Implement the AbsListView.MultiChoiceModeListener interface and set it
for the view group with setMultiChoiceModeListener(). In the listener's callback methods, you can specify the actions
for the contextual action bar, respond to click events on action items, and handle other callbacks
inherited from the ActionMode.Callback interface.
Call setChoiceMode() with the CHOICE_MODE_MULTIPLE_MODAL argument.
For example:
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 invalidate() request
return false;
}
});
That's it. Now when the user selects an item with a long-click, the system calls the onCreateActionMode()
method and displays the contextual action bar with the specified actions. While the contextual
action bar is visible, users can select additional items.
In some cases in which the contextual actions provide common action items, you might
want to add a checkbox or a similar UI element that allows users to select items, because they
might not discover the long-click behavior. When a user selects the checkbox, you
can invoke the contextual action mode by setting the respective list item to the checked
state with setItemChecked().
Yeah, I couldn't find it either -- I had to ask at Google I|O.
Use startActionMode(). Here is one of their samples that demonstrates it. I need to do more work in this area myself.
Maybe a bit late but here's a tutorial for the actionmode:
http://www.vogella.com/articles/AndroidListView/article.html#listview_actionbar
Related
I have created an action bar Search in the action bar menu.
Well, I am trying to make it go to its normal state if I click a go button or a click anywhere on the screen. Here is my code :
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
final EditText editText = (EditText) menu.findItem(
R.id.menuSearch).getActionView();
editText.addTextChangedListener(textWatcher);
menuItem = menu.findItem(R.id.menuSearch);
menuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
menuItem.collapseActionView();
// Do something when collapsed
return true; // Return true to collapse action view
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
//editText.clearFocus();
return true; // Return true to expand action view
}
});
return true;
}
It works well. But, It doesn't go to its normal state. I used this function
menuItem.collapseActionView();
But, no use. Thanks in advance
try this code
menuItem.collapseActionView();
inside
public boolean onOptionsItemSelected(MenuItem item) {
The framework calls onMenuItemCollapsed() to notify your code that the search view has been collapsed. A call to "menuItem.collapseActionView()" does no good in that method body. Your calls to collapseActionView() should be in the code where you want to force the view to be collapsed, such as a keystroke handler for the Go button.
I have an Activity with a Fragment containing a ListView with items, on which the user can click and invoke the Contextual Action Mode.
What I like to happen is as the documentation is stating:
The contextual action bar is not necessarily associated with the
action bar. They operate independently, even though the contextual
action bar visually overtakes the action bar position.
However, this is the behavior I'm currently experiencing. As of now, the Contextual Action Mode appears above the ActionBar, as the figure below shows.
What I've tried so far without success:
Moving the ActionMode logic from the Fragment to the host Activity.
Setting <item name="windowActionModeOverlay">true</item> in my theme.
Call getActivity().getMenuInflater() instead of mode.getMenuInflater().
This is my code where I invoke the Contextual Action Menu
public class NotesFragment extends Fragment implements View.OnClickListener{
private ActionMode mActionMode;
#Override
public void checkBoxChecked(Note which) {
if (mActionMode == null)
mActionMode = getActivity().startActionMode(mActionModeCallback);
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context, menu);
return true;
}
// Called each time the action mode is shown.
// Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.context_delete:
//Do work unrelated to topic
mode.finish(); // Action picked, so close the CAB
return true;
case R.id.context_move:
//Do work unrelated to topic
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
}
EDIT:
This is the Activity, in which the Fragment resides:
public class MainActivity extends ActionBarActivity implements DialogFragmentMoveNote.DialogFragmentMoveNoteListener,
DialogFragmentRemoveNote.DialogFragmentRemoveNoteListener, DialogFragmentAddNewFolder.DialogFragmentAddNewFolderListener,
DialogFragmentDeleteFolder.DialogFragmentDeleteFolderListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onAddNewFolderPositiveClick(Folder folder) {
//Tell the fragment to do work
}
#Override
public void onRemoveNotesPositiveClick() {
//Tell the fragment to do work
}
#Override
public void onMoveNotePositiveClick(String chosenFolder) {
//Tell the fragment to do work
}
#Override
public void onDeleteFolderPositiveClick() {
//Tell the fragment to do work
}
private void displayNoteDetailsFromWidget(String noteId){
//Tell the fragment to do work
}
}
Why is the Contextual Action Menu not visually overtaking the ActionBar, as the documentation state is should?
Solution to this was to add
<item name="android:windowActionModeOverlay">true</item>
to my Theme, which now looks like
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="android:windowActionModeOverlay">true</item>
</style>
I found the solution after looking at this answer
I This is from https://developers.facebook.com/docs/android/scrumptious/authenticate
This is my code (identical from the tutorial) for the options menu part
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// only add the menu when the selection fragment is showing
if (fragments[SELECTION].isVisible()) {
if (menu.size() == 0) {
settings = menu.add(R.string.settings);
}
return true;
} else {
menu.clear();
settings = null;
}
return false;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
if (item.equals(settings)) {
showFragment(SETTINGS, true);
return true;
}
return false;
}
whats happening is this works most of the time but I found a test case I couldn't debug. When you logout, the menu item still shows and you have to click it to make it disappear.(it shouldn't appear at all). This wasn't a huge concern to me at the beginning but I found that when you logged in again after you clicked the menu item to make it disappear, the options menu doesn't appear at all.
I think I found the problem, I leave it up for others. From When and how often onPrepareOptionsMenu() method is called for ActionBar? ,I got that "On Android 3.0 and higher, you must call invalidateOptionsMenu() when you want to update the menu, because the menu is always open. The system will then call onPrepareOptionsMenu() so you can update the menu items."
When I logged out, even thought there were no actual menu items, the menu was still open. However when I clicked the menu when it was empty, it messed it up so that when I logged in, show wouldn't work. I don't understand that part yet. I was hoping someone can elaborate what happened during that part
How to create custom menu for webview when longpress event occur as shown in image at the top?
public class MainActivity extends Activity {
private String data;
private WebView webview;
private String clipdata = "";
private boolean mark_text;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webview = (WebView) this.findViewById(R.id.webView1);
data = "The entire plan-to-produce process, including enterprise-level planning and scheduling, plant-level operations, manufacturing execution, batch manufacturing, and quality management. Capabilities for Big Data management and process integration support the use of real-time data from the shop floor to maintain batch traceability and genealogy. Embedded quality and compliance controls enable process manufacturers to manage exceptions and address nonconformance through corrective and preventive actions for batches. Leveraging mobile and cloud as well ![enter image description here][2]as on-premise technologies, this level of production control helps increase throughput, set predictable and shorter cycle times, improve asset utilization, and help ensure that inventory targets are met.</body></html>";
webview.loadDataWithBaseURL("", data, "text/html", "UTF-8", "");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_search:
Toast.makeText(this, "action_search selected", Toast.LENGTH_SHORT)
.show();
return true;
case R.id.action_settings:
Toast.makeText(this, "action_settings selected", Toast.LENGTH_SHORT)
.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
I have update answer with my code. plz check it and say how how can I disable this default action bar and add my own action bar but at the same time text selection functionality should work.
This is called a Contextual Action Bar, it's an overlay on top of the default action bar.
There is a good tutorial here which describes how to work with it.
To get own action bar to work there while still keeping the selection functionality is going to be tricky to say the least I'm afraid...
To add actions to the action bar, create a new XML file in your project's res/menu/ directory.
main_activity_actions.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Search, should appear as action button -->
<item android:id="#+id/action_search"
android:icon="#drawable/ic_action_search"
android:title="#string/action_search"
android:showAsAction="ifRoom" />
<!-- Settings, should always be in the overflow -->
<item android:id="#+id/action_settings"
android:title="#string/action_settings"
android:showAsAction="never" />
</menu>
Add the Actions to the Action Bar
To place the menu items into the action bar, implement the onCreateOptionsMenu() callback method in your activity to inflate the menu resource into the given Menu object. For example:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
Respond to Action Buttons
When the user presses one of the action buttons or another item in the action overflow, the system calls your activity's onOptionsItemSelected() callback method. In your implementation of this method, call getItemId() on the given MenuItem to determine which item was pressed—the returned ID matches the value you declared in the corresponding element's android:id attribute.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_search:
Toast.makeText(this,"action_search selected",Toast.LENGTH_SHORT).show();
return true;
case R.id.action_settings:
Toast.makeText(this,"action_settings selected",Toast.LENGTH_SHORT).show();
return true;
default:
return super.on
OptionsItemSelected(item);
}
}
for further guidance refer the official doc
first create your own ActionModeCallBack then you need to create a class and extend WebView and overwrite this method:
public ActionMode startActionMode(ActionMode.Callback callback)
{
actionModeCallback = new CustomizedSelectActionModeCallback();
return super.startActionMode(actionModeCallback);
}
update: look at this
It's work for me...
I want to remove COPY, SELECT ALL and FIND from android contextual action bar and add custom menu items.
This is appearing while selecting text on webview. I am trying to add Text Highlights on webview using js.
In order to accomplish what you want, you will need to create an entirely new contextual action bar. This is done through creating a custom ActionMode. Within your WebView, create a nested class that implements ActionMode.Callback. You can use this as a template:
public class CustomWebView extends WebView {
private ActionMode.Callback mActionModeCallback;
#Override
public ActionMode startActionMode(ActionMode mode) {
// This block is directly from the WebView source code.
ViewParent parent = getParent();
if (parent == null) {
return null;
}
mActionModeCallback = new CustomActionModeCallback();
return parent.startActionModeForChild(this, mActionModeCallback);
}
private class CustomActionModeCallback implements ActionMode.Callback {
// Called when the action mode is created; startActionMode() was called
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
// Called each time the action mode is shown.
// Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// This method is called when the selection handlebars are moved.
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_button_1:
// Do stuff
break;
case R.id.menu_button_2:
// Do stuff
break;
default:
// You did not handle the action, so return false
// If you have implemented a case for every button,
// this block should never be called.
return false;
}
// If you want to close the CAB immediately after
// picking an action, call mode.finish().
// If you want the CAB to persist until the user clears the selection
// or clicks the "Done" button, simply return true.
mode.finish(); // Action picked, so close the CAB
return true;
}
// Called when the user exits the action mode
#Override
public void onDestroyActionMode(ActionMode mode) {
mode = null;
}
}
}
Be sure to define a menu in your XML resources. Here is an example to go with the above template:
<!-- context_menu.xml -->
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_button_1"
android:icon="#android:drawable/menu_button_1"
android:showAsAction="always"
android:title="#string/menu_button_1">
</item>
<item
android:id="#+id/menu_button_2"
android:icon="#drawable/menu_button_2"
android:showAsAction="ifRoom"
android:title="#string/menu_button_2">
</item>
</menu>
I noticed you did not explicitly state that you want to replace SHARE and WEB SEARCH. Unfortunately, this method does require you to implement all functionality on your own. However, you can dig into the source code (I would start in ActionMode.java) for those functions. Implement a new case in CustomActionModeCallback.onActionItemClicked (where you handle your button events), copy/paste the functionality from source, and add a corresponding button in your XML file. You can even use the native icon for those functions: android:icon="#android:drawable/[name_of_desired_icon]
For reference, this information is from the Android Developers website.
http://developer.android.com/guide/topics/ui/menus.html#CAB
May be this helps you and also stack members...
https://github.com/btate/BTAndroidWebViewSelection