I have to implement the following functionality. See the picture.
Can I change the functionality of Navigation drawer? I haven't any found fix for my problem.
I hope you can help me, thanks in advance.
Yes it's possible. However I advise you against it because it kind of breaks the UI.
If you choose to do it though, first you need to be able to access the overflow menu (circled button). This was answered before here, so I'll just provide a style.xml snippet:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionOverflowButtonStyle">#style/Overflow</item>
</style>
<style name="Overflow" parent="Widget.AppCompat.ActionBar">
<item name="android:contentDescription">OVERFLOW</item>
</style>
Then, when the home (navigation drawer) button is clicked you open the overflow menu:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
final View decor = getWindow().getDecorView();
ArrayList<View> results = new ArrayList<>();
decor.findViewsWithText(results, "OVERFLOW",
View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
if (results.size() == 1) {
results.get(0).performClick();
return true;
}
}
return super.onOptionsItemSelected(item);
}
Related
I am creating an app wherein I have three items in the action bar. I want that when I click on one of the item, it should get highlighted.
I went through few examples available but concluded that I will have to create style using
ActionBar Style Generator tool.
I referred the following link.. but was not satisfied
how to highlight a menu item on selection?
Is this the only way to go about?
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:actionBarItemBackground">#drawable/action_bar_item_selector</item>
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_focused="true"
android:drawable="#drawable/ic_action_blue" />
<item android:state_pressed="true"
android:drawable="#drawable/ic_action_green" />
<item android:drawable="#android:color/transparent" />
</selector>
But the selection does not remain stagnant as it is for state_pressed and state_focused.
I want the item to remain highlighted till the user is on that activity.
More elegant way of handling the issue , is to simply have a boolean value that will check
both states , If you are using the same drawable with different state colors , i will recommend
you to use the colorFilter method to apply to your drawables.
private boolean mSomeValue = true;
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// determine the menu item you want to highlight when selected
switch(item.getItemId) {
case yourItem : {
if (mSomeValue) {
item.getIcon().setColorFilter(YourColor, PorterDuff.Mode.MULTIPLY);
mSomeValue = false;
} else {
mSomeValue = true;
item.getIcon().setColorFilter(Default, PorterDuff.Mode.MULTIPLY);
}
break; ...
}
}
return super.onOptionsItemSelected(item);
}
You can define a theme and inherit the Action bar theme you want (for instance Theme.Sherlock.Light.DarkActionBar), set the value of the android:actionBarItemBackground attribute to override the default one in the inheritted theme.
<style name="MyTheme" parent="Theme.Sherlock.Light.DarkActionBar">
<item name="android:actionBarItemBackground">custom_selector</item>
</style>
I am creating an app wherein I have three items in the action bar. I
want that when I click on one of the item, it should get highlighted.
I am not sure if the following will work properly:
Create two sets of icons for each of the menu items: one for the default look, the other highlighted (in whatever way you feel: change the color, change the background color etc.). Declare a global Menu variable to hold the menu item:
// Global variable // Not good practice, but needed in this case
Menu mainMenu;
....
....
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_name, menu);
mainMenu = menu;
return true;
}
In onMenuItemSelected(int featureId, MenuItem item):
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
for (int i = 0; i < mainMenu.size(); i++) {
// Set default icons
if (mainMenu.getItem(i).getItemId() == R.id.action1) {
mainMenu.getItem(i).setIcon(R.drawable.icon_default1);
} else if (mainMenu.getItem(i).getItemId() == R.id.action2) {
mainMenu.getItem(i).setIcon(R.drawable.icon_default2);
} else if (.....) {
.....
}
}
if (item.getItemId() == R.id.action1) {
item.setIcon(R.drawable.icon_highlighted1);
} else if (item.getItemId() == R.id.action2) {
item.setIcon(R.drawable.icon_highlighted2);
} else if(.....) {
.....
}
return super.onMenuItemSelected(featureId, item);
}
I guess you can fine-tune this by checking against item.getItemId() inside the for-loop itself.
Ok, so i suggest you to create two different items in your menu.xml:
<item
android:id="#+id/action_item1"
/>
<item
android:id="#+id/action_item2"
android:visible="false"
/>
Then, in the activity in which you want to highlight your item, override the ononPrepareOptionsMenu , use the menu paremeter to catch your desired item by using the menu.findItem(R.id.your_item_id). And finally toggle the visibility of your items.
You will need to refresh your action bar items automatically by using invalidateOptionsMenu
Let me know if that helps !
I want to add a standard Up Button icon ( < like this ) in action bar.
I added this in the styles:
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:homeAsUpIndicator">#drawable/navigation_previous_item</item>
</style>
I enabled home Button in onCreate:
getActionBar().setHomeButtonEnabled(true);
And added action event:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case android.R.id.home:
onBackPressed();
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
Problem is that i can't see the ( < ) icon. Application icon is padded to the right, like there is a place for my drawable, but it doesn't show me the icon . . .
try getActionBar().setDisplayHomeAsUpEnabled(true); and it should work
I have an ActionBar using ActionBar Sherlock where I need it to display overflow because I have more actions than room. But, it doesn't show the overflow icon. Here is my configuration:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_search"
android:icon="#drawable/action_search"
android:title="#string/menu_search"
android:showAsAction="ifRoom|withText"/>
<item android:id="#+id/menu_library"
android:icon="#drawable/hardware_headphones"
android:title="#string/my_music"
android:showAsAction="ifRoom|withText"/>
<item android:id="#+id/menu_downloads"
android:icon="#drawable/av_download"
android:title="#string/downloads"
android:showAsAction="ifRoom|withText"/>
</menu>
And here is code to set it up:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getSupportMenuInflater();
menuInflater.inflate(R.menu.shopping_menu, menu);
MenuItem searchMenuItem = menu.findItem(R.id.menu_search);
searchMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
startActivity(new Intent(ShopActivity.this, SearchDialog.class));
return false;
}
});
MenuItem downloadMenuItem = menu.findItem(R.id.menu_downloads);
downloadMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
startActivity( new Intent(ShopActivity.this, DownloadQueueActivity.class) );
return false;
}
});
MenuItem myMusicItem = menu.findItem(R.id.menu_library);
myMusicItem.setOnMenuItemClickListener( new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
startActivity(new Intent(ShopActivity.this, MyMusicActivity.class));
return false;
}
});
return true;
}
I've looked over the demos in ActionBar Sherlock, but I can't tell what they do differently to get the overflow than what I'm doing. So what's happening here why its not showing?
If you have a physical menu key, the overflow indicator does not show. That is a behaviour by design. See here for more details on another question asked.
Hmm I think there are two issues here. First, as t0mm13b states, if the device has a physical menu key, the overflow indicator does NOT show. This is by design. Although in my experience, it doesn't apply to every device (unfortunately...)
The second issue is that, if you want to force an item to the overflow, you need to set the showAsAction to "never". Otherwise, the only elements that appear in the overflow are ones that simply "don't fit" in the action bar. And given that you have 3 items that you want to display with text.. you're pretty much guranteed to have at least one overflow item, and therefore the overflow icon (with the caveat of the first paragraph)
Try by changing the android:showAsAction tag to app:showAsAction according to the Android guide in the menu_main.xml file as shown below
Add this line if not present
menu xmlns:app="http://schemas.android.com/apk/res-auto"
<item android:id="#+id/action_search"
android:icon="#drawable/search_icon"
android:title="#string/action_search"
app:showAsAction="always"/> <!--change here android: to app:-->
<item android:id="#+id/action_location"
android:icon="#drawable/location_icon"
android:title="#string/action_locate"
app:showAsAction="always"/>
</menu>
I have several Views on an Activity which a user wants to touch quickly in succession and I capture these touches using a TouchListener and handling MotionEvent.ACTION_DOWN. However, if the user is using two hands, it's very likely that the next View will be 'Touch'ed before the user pulls the previous finger up. In this scenario, a MotionEvent.ACTION_MOVE is fired for the first view rather than the desired MotionEvent.ACTION_DOWN for the second view.
Is there any way to work around or prevent this behavior? I've tried dispatching a new event with MotionEvent.ACTION_UP and also removing the event listener but neither seem to work.
The easiest way I found to force single touch across an entire app is to set it using a theme:
<style name="MyTheme" parent="#android:style/Theme.Holo.Light">
<item name="android:windowEnableSplitTouch">false</item>
<item name="android:splitMotionEvents">false</item>
</style>
Manifest:
<application
android:label="#string/app_name"
android:theme="#style/MyTheme" >
if someone still searching for best solution,
put in the xml the following code :
android:splitMotionEvents = false
I did it like this :
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if(event.getPointerCount() > 1) {
System.out.println("Multitouch detected!");
return true;
}
else
return super.onTouchEvent(event);
}
I think you can override onTouchEvent for any view.
The best way to work around this scenario is to use a ViewGroup and implement the onInterceptTouchEvent method to manually route the touch events as you see fit.
This was originally answered here:
Android multitouch! hack anyone?
Code implementing this solution (found in the comments section of the answer to the above question) is found here:
http://pastebin.com/hiE1aTCw
I have solved this using a custom method - which I did not want to do If anyone finds a better way I'd like to hear about it Thanks:
public static void setViewGroupEnebled(ViewGroup view, boolean enabled)
{
int childern = view.getChildCount();
for (int i = 0; i< childern ; i++)
{
View child = view.getChildAt(i);
if (child instanceof ViewGroup)
{
setViewGroupEnebled((ViewGroup) child,enabled);
}
child.setEnabled(enabled);
}
view.setEnabled(enabled);
}
Override dispatchTouchEvent and intercept all touches there, for all multi touches the pointercount is more than one.
if(ev.getPointerCount() > 1)
{
Log.d("Multitouch detected!");
ev.setAction(MotionEvent.ACTION_CANCEL);
}
This cancels the touches and clears the pressed state of the buttons without taking any further action.
For me it worked like this.
I just put this line in all active styles in my app
<item name="android:splitMotionEvents">false</item>
my style for example
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="android:splitMotionEvents">false</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:splitMotionEvents">false</item>
</style>
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
horizentalLinearGridItem.setMotionEventSplittingEnabled(false);
}
Here horizentalLinearGridItem is parentLayout view where we insert child views.
In my code its LinearLayout. In this LinearLayout I added child views. But when I clicked two child views simultaneously, both were getting the events. To block that I used the above code.
I got it to work for me by just adding some code in OnTouchEvent method,
boolean action_down_required = false;
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if(event.getPointerCount() > 1){
action_down_required = true;
return true;
}
if(action_down_required){
action = MotionEvent.ACTION_DOWN;
}
switch (action) {
case MotionEvent.ACTION_DOWN:
// your code goes here...
action_down_required = false;
break;
// Other events...
I have the following menu layout in my Android app:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/item1"
android:titleCondensed="Options"
android:title="Highlight Options"
android:icon="#android:drawable/ic_menu_preferences" />
<item android:id="#+id/item2"
android:titleCondensed="Persist"
android:title="Persist"
android:icon="#android:drawable/ic_menu_preferences"
android:checkable="true" />
</menu>
My problem is that the second menu item doesn't appear to be "checkable" when I run my app in the Android emulator. There should be a green tick about the item, right? To indicate that its checkable.
Am I doing something wrong?
Layout looks right. But you must check and uncheck menu item in code.
From the documentation:
When a checkable item is selected, the system calls your respective item-selected callback method (such as onOptionsItemSelected()). It is here that you must set the state of the checkbox, because a checkbox or radio button does not change its state automatically. You can query the current state of the item (as it was before the user selected it) with isChecked() and then set the checked state with setChecked().
Wrap the items in a group element, like this:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="all">
<item android:id="#+id/item1"
android:titleCondensed="Options"
android:title="Highlight Options"
android:icon="#android:drawable/ic_menu_preferences">
</item>
<item android:id="#+id/item2"
android:titleCondensed="Persist"
android:title="Persist"
android:icon="#android:drawable/ic_menu_preferences"
android:checkable="true">
</item>
</group>
</menu>
From the Android docs:
The android:checkableBehavior attribute accepts either:
single - Only one item from the group can be checked (radio buttons)
all - All items can be checked (checkboxes)
none - No items are checkable
You can create a checkable menu item by setting the actionViewClass to a checkable widget like android.widget.CheckBox
res/menu/menu_with_checkable_menu_item.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_favorite"
android:checkable="true"
android:title="#string/action_favorite"
app:actionViewClass="android.widget.CheckBox"
app:showAsAction="ifRoom|withText" />
</menu>
And you can can even style it to be a checkable star if you set actionLayout to a layout with a styled android.widget.CheckBox
res/layout
/action_layout_styled_checkbox.xml
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/starStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
res/menu/menu_with_checkable_star_menu_item.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_favorites"
android:checkable="true"
android:title="#string/action_favorites"
app:actionLayout="#layout/action_layout_styled_checkbox"
app:showAsAction="ifRoom|withText" />
</menu>
To set the value
menuItem.setChecked(true/false);
To get the value
menuItem.isChecked()
Cast MenuItem to CheckBox
CheckBox checkBox= (CheckBox) menuItem.getActionView();
I've found that the best solution was to just use the onOptionsItemSelected() method as of my current API (27-28).
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
//Copy from here...
int itemId = item.getItemId();
if(item.isChecked())
{
if(R.id.edit_tile_checkbox == itemId) //Individual checkbox logic
{ /*TODO unchecked Action*/}
item.setChecked(false); //Toggles checkbox state.
}
else
{
if(R.id.edit_tile_checkbox == itemId) //Individual checkbox logic
{/*TODO checked Action*/}
item.setChecked(true); //Toggles checkbox state.
}
//...To here in to your onOptionsItemSelected() method, then make sure your variables are all sweet.
return super.onOptionsItemSelected(item);
}
I spent way to long on here for this answer. and for whatever reason, the answers above didn't help (I'm a returning newbie I probably mucked something up I'm sure).
There could be a better way of doing this so helpful criticism is welcomed.
READ THIS
As has been said the "manual checking" is only the tip of the iceberg. It flashes the menu away so fast the users don't see anything happen and it is very counter intuitive, frustrating, and effectively utter crap. The REAL TASK (therefore) is allowing the check box event to be digested by the users mind.
Good news: this can be done and it does work and this is how you do it. #TouchBoarder had it best so I will copy his code. then develop it.
the idea is to detect if the checkbox is clicked, then (and only if that one is picked) slightly suppress the menu removal, add a timer for 500ms then close the menu, this give the "tick" animation of the checkbox time to run and creates the right "feel"
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_favorite"
android:checkable="true"
android:title="#string/action_favorite"
app:actionViewClass="android.widget.CheckBox"
app:showAsAction="ifRoom|withText" />
</menu>
then you make this method as usual, but you make sure you add all this extra bumpf
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the bottom bar and the top bar (weird)
BottomAppBar bottomBar = findViewById(R.id.bottom_app_bar_help);
Menu bottomMenu = bottomBar.getMenu();
getMenuInflater().inflate(R.menu.bottom_nav_menu, bottomMenu);
for (int i = 0; i < bottomMenu.size(); i++) {
bottomMenu.getItem(i).setOnMenuItemClickListener(item -> {
if (item.getItemId()==R.id.action_favorite){
item.setChecked(!item.isChecked());
// Keep the popup menu open
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
item.setActionView(new View(frmMain.this));
item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
final Handler handler = new Handler();
handler.postDelayed(() -> bottomMenu.close(), 500);
return false;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
final Handler handler = new Handler();
handler.postDelayed(() -> bottomMenu.close(), 500);
return false;
}
});
return false;
}
else {
return onOptionsItemSelected(item);
}
});
}
return true;
}
the other menu events are here
public boolean onOptionsItemSelected(MenuItem item) {
// Bottom Bar item click
try {
switch (item.getItemId()) {
case R.id.mnuExit:
MenuClick(ClickType.LOGOUT);
return true;
case R.id.mnuList:
MenuClick(ClickType.LIST);
return true;
default:
return super.onOptionsItemSelected(item);
}
} catch (Exception e) {
e.printStackTrace();
}
return super.onOptionsItemSelected(item);
}
Answering because the answers here seem long and convoluted.. I have some exact Kotlin code here
Override your activity at the top and override the function onMenuItemClick, Have a function to handle the button click to open the menu.
Have an array or list which holds the checked value and sets the check when the menu is re-created
Note: This code does not keep the menu open, It only ensures that checked items remain checked.
I noted there are lots of solutions to that on stack overflow, so have a look at them if that's what you desire
class exampleActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener {
private var checkChecked = arrayListOf(false,false)
//some code
fun clickBTN(v: View){
val popup = PopupMenu(this,v)
popup.setOnMenuItemClickListener(this)
popup.inflate(R.menu.yourmenufilename)
//assuming you have 2 or more menu items
popup.menu[0].isChecked = checkChecked[0]
popup.menu[1].isChecked = checkChecked[1]
popup.show()
}
override fun onMenuItemClick(item: MenuItem?): Boolean {
when(item?.itemID){
R.id.item0 -> {
item.isChecked = !item.isChecked
checkChecked[0] = item.isChecked
return true
}
R.id.item1 -> {
item.isChecked = !item.isChecked
checkChecked[1] = item.isChecked
return true
}
}
}
of course in XML you should have your Button and Menu setup. An example menu is here
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/item0"
android:title="#string/hi"
android:checkable="true"/>
<item android:id="#+id/item1"
android:title="#string/yo"
android:checkable="true"/>
</menu>
This may be theme dependant but my menu didn't show a checkbox. I found this :
Note: Menu items in the Icon Menu cannot display a checkbox or radio
button. If you choose to make items in the Icon Menu checkable, then
you must personally indicate the state by swapping the icon and/or
text each time the state changes between on and off.
For Adding Menu items Programmatically,
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("Item1").setActionView(R.layout.action_layout_checkbox).setCheckable(true);
return super.onCreateOptionsMenu(menu);
}
res/layout /action_layout_checkbox.xml
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
I have two items in the menu and set to checkable in menu.xml file like below
<item
android:id="#+id/A"
android:title="A"
app:showAsAction="never"
android:checkable="true"/>
<item
android:id="#+id/B"
android:title="B"
app:showAsAction="never"
android:checkable="true"/>
and logic for the menu checkboxes is below.
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.A:
//logic goes here
if(item.isChecked())
{
//logic is it is checked
item.setChecked(false);
}
else
{
//logic is it is not checked
item.setChecked(true);
}
return true;
case R.id.B:
//logic for second checkbox goes here
if(item.isChecked())
{
//logic is it is checked
item.setChecked(false);
}
else
{
//logic is it is not checked
item.setChecked(true);
}
return true;
default:
return super.onOptionsItemSelected(item);
}