I am looking for a way to have the options menu persist on screen as soon as the activity is opened without pressing the menu button of the simulator and it should be there until one of the options in the menu is pressed
Currently I have made an option menu like this:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/icon"
android:icon="#drawable/icon" />
<item android:id="#+id/text"
android:title="Text" />
<item android:id="#+id/icontext"
android:title="Icon and text"
android:icon="#drawable/icon" />
</menu>
And my code is:
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId())
{
case R.id.icon:
break;
case R.id.text:
break;
case R.id.icontext:
break;
}
return true;
}
Please suggest changes in my code.
Activity‘s option menu can be programatically opened and closed with the openOptionsMenu and closeOptionsMenu respectively
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
openOptionsMenu();
}
and to close:
closeOptionsMenu();
for lvls that do not support onAttachedToWindow could be used delayed execution(Not the best way):
new Handler().postDelayed(new Runnable() {
public void run() {
openOptionsMenu();
}
}, 1000);
I haven't tried this one, but you could look at openOptionsMenu.
Then after it's open you should try to intercept the menu button press and the back button press (as you would close the menu otherwise) and only disable this once one of the option items has been selected.
With this said, this all looks like a hack, so maybe you should consider a different solution for what you want to achieve.
Related
I have a TextView where a user is able to select a text. By default the following options appear: "Copy", "Share" and "Select All".
I need to override them with custom options. But I can't find how to do that. I went through the documentation and this nice article but no lack. The article explains how to extend the menu when a user presses three-dots-button which is not what I need.
Question: How can I override default "Copy", "Share" and "Select All" options in text section menu?
Here is how my view looks like:
<TextView
android:id="#+id/transcript"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
And in java code I have:
transcript.setTextIsSelectable(true);
transcript.setFocusable(true);
transcript.setFocusableInTouchMode(true);
You can use TextView.setCustomSelectionActionModeCallback() to do this.
Documentation: https://developer.android.com/reference/android/widget/TextView.html#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback)
I put together a very simple app to demonstrate how to use this feature.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView text = (TextView) findViewById(R.id.text);
CustomActionModeCallback callback = new CustomActionModeCallback(this);
text.setCustomSelectionActionModeCallback(callback);
}
}
activity_main.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:text="#string/lorem_ipsum"
android:textIsSelectable="true"/>
</FrameLayout>
CustomActionModeCallback.java
public class CustomActionModeCallback implements ActionMode.Callback {
private final Context context;
public CustomActionModeCallback(Context context) {
this.context = context;
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
menu.clear();
mode.getMenuInflater().inflate(R.menu.menu_custom, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (item.getItemId() == R.id.custom_one) {
Toast.makeText(context, "One!", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
}
else if (item.getItemId() == R.id.custom_two) {
Toast.makeText(context, "Two!", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
}
else if (item.getItemId() == R.id.custom_three) {
Toast.makeText(context, "Three!", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
}
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
}
menu_custom.xml
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/custom_one"
android:title="One"
app:showAsAction="never"/>
<item
android:id="#+id/custom_two"
android:title="Two"
app:showAsAction="never"/>
<item
android:id="#+id/custom_three"
android:title="Three"
app:showAsAction="never"/>
</menu>
Nothing much to comment on in MainActivity or either xml file. All the magic happens in CustomActionModeCallback.
Both onCreateActionMode() and onPrepareActionMode() can be used to add your custom menu items to the menu. If you use onCreateActionMode(), the system will add some extra options into an overflow menu, like this:
If you use onPrepareActionMode(), the extra items won't be added.
Note that you must return true from onCreateActionMode() no matter what (returning false causes the menu to not be displayed), but you only have to return true from onPrepareActionMode() if you've actually modified the menu.
You can handle the user's clicks on your custom items inside onActionItemClicked(). In my example, I simply show a Toast and then close the contextual menu (using ActionMode.finish()). In this method, you should return true only on menu items that you handle yourself; returning false allows the system default action to happen (such as if you want to give the user the option to select all text).
Finally, onDestroyActionMode() is called when the menu is closed. Perhaps you have some use for this; I did not.
I have generated a popUp Menu on button click (as the layout is custom layout so couldn't use onCreateOptionsMenu). Everything is working fine except that the menu looks odd. It has got a shadow behind it which doesn't seem to go well with the app. Is there any way in which I can remove the shadow or make the popup menu look like the menu generated using onCreateOptionsMenu.
Below is the image of my popup Menu
Code: (options_menu.xml)
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/option1" android:title="#string/option1"
android:orderInCategory="101" android:showAsAction="always|withText" />
<item android:id="#+id/option2" android:title="#string/option2"
android:orderInCategory="102" android:showAsAction="always|withText" />
</menu>
Activity:
popMenuBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context wrapper = new ContextThemeWrapper(MenuActivity.this, myPopupMenuTextAppearance);
mPopupMenu = new PopupMenu(wrapper, v);
MenuInflater menuInflater = mPopupMenu.getMenuInflater();
menuInflater.inflate(R.menu.options_menu, mPopupMenu.getMenu());
mPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.option1:
startActivity(new Intent(this, XYZ.class));
return true;
case R.id.option2:
someFunction();
return true;
default:
Toast.makeText(this,"You Clicked : " + item.getTitle(),Toast.LENGTH_SHORT).show();
return true;
}
}
});
mPopupMenu.show();
}
});
I am trying to enable the user to stops and starts service which I am implementing from the Menu where the text is will be changed when he clicks it so I want to add ToggleButton as option in the menu tool but nothing is being display in my case now. How can I fix it?
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<ToggleButton
android:id="#+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="Off"
android:textOn="On" />
</menu>
MainActivity:
public class MainActivity extends ActionBarActivity {
ToggleButton tButton;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.toggle:
tButton = (ToggleButton) findViewById(R.id.toggle);
tButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (((ToggleButton) v).isChecked()) {
Intent i = new Intent(MainActivity.this,
TrackingService.class);
startService(i);
System.out.println("test is checked, start service");
} else {
// Stop the service when the Menu button clicks.
Intent i = new Intent(MainActivity.this,
TrackingService.class);
stopService(i);
System.out.println("test is NOT checked, stop service");
}
}
});
return true;
default:
return false;
}
}
}
Edit:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.checkable_menu:
if (isChecked = !item.isChecked()) {
item.setChecked(isChecked);
Intent i = new Intent(this, TrackingService.class);
startService(i);
System.out.println("test if onOptionsItemSelected");
} else {
Intent i = new Intent(this, TrackingService.class);
stopService(i);
System.out.println("test else onOptionsItemSelected");
}
return true;
default:
System.out
.println("test default onOptionsItemSelected was invoked.");
return false;
}
}
It is easy. Rather you will have your toggle button on Toolbar.
<item
android:id="#+id/show_secure"
android:enabled="true"
android:title=""
android:visible="true"
app:actionLayout="#layout/show_protected_switch"
app:showAsAction="ifRoom" />
And this is your show_protected_switch.xml layout.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ToggleButton
android:id="#+id/switch_show_protected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/switch_ptotected_btn_selector"
android:textOff=""
android:textOn=""/>
</RelativeLayout>
And in code:
ToggleButton mSwitchShowSecure;
mSwitchShowSecure = (ToggleButton) menu.findItem(R.id.show_secure).getActionView().findViewById(R.id.switch_show_protected);
mSwitchShowSecure.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b){
//Your code when checked
} else {
//Your code when unchecked
}Y
}
});
Output!
It is rather big but you can adjust its size, obviously
I know its very a long time to post an answer, but it may help someone :)
I followed this link and update some of the implemented solution as the app was crashed before these modifications
And below is the full solution:
1- Create a new xml file under layout folder and name it switch_layout.xml and put the below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<Switch
android:id="#+id/switchAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
</RelativeLayout>
2- Add the below menu item in the main.xml file under menu folder:
<item
android:id="#+id/switchId"
android:title=""
app:actionLayout="#layout/switch_layout"
app:showAsAction="always" />
3- Go to your activity and below is a full implementation for onCreateOptionsMenu method:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem item = (MenuItem) menu.findItem(R.id.switchId);
item.setActionView(R.layout.switch_layout);
Switch switchAB = item
.getActionView().findViewById(R.id.switchAB);
switchAB.setChecked(false);
switchAB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
Toast.makeText(getApplication(), "ON", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(getApplication(), "OFF", Toast.LENGTH_SHORT)
.show();
}
}
});
return true;
}
As mentioned above, you can't add toggle button to the menu. You can use the android:checkable property in your menu item to handle the two states.
Something like:
Menu:
<item
android:id="#+id/checkable_menu"
android:checkable="true"
android:title="#string/checkable" />
Activity:
private boolean isChecked = false;
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem checkable = menu.findItem(R.id.checkable_menu);
checkable.setChecked(isChecked);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.checkable_menu:
isChecked = !item.isChecked();
item.setChecked(isChecked);
return true;
default:
return false;
}
}
PS: Copied the code from here.
Or you can just update your item icon on click event to show the two states with item.setIcon(yourDrawable));
You cannot put any widget in <menu> and expect it to work. What you can put there is documented here and it's basically limited to menu <item> and <group>. No buttons, toggles and other widgets are supported. If that would be sufficient you can use android:checkable on the <item> or use old-skool approach and alter menu item depending on the state (if service is on, then your item should read turn service off and vice versa).
In the menu xml you add items not widgets (no buttons/textviews etc)
You simply specify an ID and an ICON for the item, then inflate them in your activities onCreateOptionsMenu() method.
then there is a method called onOptionsItemSelected(MenuItem item) check items id against the ids your expecting.
If its equal to your toggle service option determine service state and alter, if you want to have a toggle button function you can use item.setIcon(drawable) here.
Menu resources are distinct from conventional layouts; you cannot simply add widgets into them and expect them to work. The only elements allowed inside a menu resource is <item> or <group>.
Using a custom layout inside a menu isn't possible, I'm afraid. You may instead want to replace the entire menu with a PopupWindow, and supply your layouts there instead.
You may want to consider two alternatives:
Using a conventional menu entry as a toggle, or
Placing the ToggleButton immediately inside the Actionbar/Toolbar, instead of inside the menu.
I want to add action to add action to main.xml button.
here is my code:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/SendMes"
android:showAsAction="ifRoom|withText"
android:textColor="#ff0000"
android:textColorHighlight="#ff0000"
android:textColorHint="#ff0000"
android:textColorLink="#ff0000"
android:enabled="True"
android:title="Pargi"/>
Just how to start something like onclicklistner?
You need to override onOptionsItemSelected method in your activity in order to trap the selected item's click event:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//get the item id, match with required one and do your stuff
}
Make sure you inject your menu xml file too:
#Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
getMenuInflater().inflate(R.menu.your_whatever_menu_file, menu);
return true;
}
For more info, read this.
Use the onOptionsItemSelected like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.SendMes:
//Do whatever you want
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
have u tried adding>> android:onClick="YOUR_METHOD_IN_ACTIVITY" ?
so I am trying to get my menu item, that is show on the action bar to behave like a checkable menu option. The firs part works, meaning it is checkable and when I press it, and set in code the setChecked(true) it works. But what does not work is the visual part. There is no change in how a menu item looks on the action bar in checked and unchecked states? I tried using invalidateOptionsMenu() but that does not do the job, and not only that, with that line in my code I can't get out of the checked state?!?
What happens is that invalidate OptionsMenu() seams to unset the checked state and I end up 'looping', or on every press of that menu item I keep going to the unchecked part of the code where it gets checked and with invalidate it gets unchecked I guess...
Here is the code from my XML file for menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/lenslist_menu_add"
android:showAsAction="always"
android:title="#string/add"/>
<item android:id="#+id/lenslist_menu_delete"
android:showAsAction="always"
android:checkable="true"
android:title="#string/delete"/>
</menu>
And here is the java code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.lenslist_menu_add:
return true;
case R.id.lenslist_menu_delete:
if (item.isChecked() == true) {
item.setChecked(false);
deleteMode = false;
lensAdapter.setDeleteMode(false);
} else {
item.setChecked(true);
deleteMode = true;
lensAdapter.setDeleteMode(true);
}
lensAdapter.notifyDataSetChanged();
return true;
}
return super.onOptionsItemSelected(item);
}
Thanks!
Checkable items appear only in submenus or context menus.
You are using them as main menu items, hence it will not work.
SOURCE: Download the API DEMOS, and open the file ApiDemos/res/menu/checkable.xml, you'll see it as a comment on line 13. I don't know why they don't mention this in the Developer Documentation
reference with comment.:
http://alvinalexander.com/java/jwarehouse/android-examples/platforms/android-2/samples/ApiDemos/res/menu/checkable.xml.shtml
Or just do it yourself
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.item1).setIcon(menu_checked?R.drawable.menu_ico_checked:R.drawable.menu_ico_unchecked);
return super.onPrepareOptionsMenu(menu);
}
and in onOptionsItemSelected do:
....
menu_checked=!menu_checked;
invalidateOptionsMenu();
The best solution is to set the actionLayout of the <Item> to a CheckBox. This solution gives you a native-looking checkbox (with material animations etc), with a font that matches the other items, and it works both as an action and in the submenu.
Create a new layout called action_checkbox.html:
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:checked="false"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Menu"
android:id="#+id/action_item_checkbox"
/>
Set your <Item> like this. Note that you need the Checkable and Checked still in case it is shown in a sub-menu (in which case the actionLayout is ignored.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="#+id/menu_action_logging"
android:title="#string/action_logging"
android:orderInCategory="100"
android:showAsAction="always"
android:checkable="true"
android:checked="false"
android:actionLayout="#layout/action_checkbox"
/>
</menu>
In your code, when the menu is created we need to a) set the title of the checkbox to match the menu item title, b) restore the checked state of both the menu checkable, and our extra checkbox, and c) add an onClicked() listener for our extra checkbox. In this code I am persisting the state of the checkbox in a RetainedFragment.
// Set the check state of an actionbar item that has its actionLayout set to a layout
// containing a checkbox with the ID action_item_checkbox.
private void setActionBarCheckboxChecked(MenuItem it, boolean checked)
{
if (it == null)
return;
it.setChecked(checked);
// Since it is shown as an action, and not in the sub-menu we have to manually set the icon too.
CheckBox cb = (CheckBox)it.getActionView().findViewById(R.id.action_item_checkbox);
if (cb != null)
cb.setChecked(checked);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.menu_main, menu);
super.onCreateOptionsMenu(menu, inflater);
// Restore the check state e.g. if the device has been rotated.
final MenuItem logItem = menu.findItem(R.id.menu_action_logging);
setActionBarCheckboxChecked(logItem, mRetainedFragment.getLoggingEnabled());
CheckBox cb = (CheckBox)logItem.getActionView().findViewById(R.id.action_item_checkbox);
if (cb != null)
{
// Set the text to match the item.
cb.setText(logItem.getTitle());
// Add the onClickListener because the CheckBox doesn't automatically trigger onOptionsItemSelected.
cb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(logItem);
}
});
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_action_logging:
// Toggle the checkbox.
setActionBarCheckboxChecked(item, !item.isChecked());
// Do whatever you want to do when the checkbox is changed.
mRetainedFragment.setLoggingEnabled(item.isChecked());
return true;
default:
break;
}
return false;
}