NavigationView: Mark menu as dirty - java

I am using the android.support.design.widget.NavigationView. During the lifetime of this view the menu items get changed (removed, renamed and added) dynamically. However these changes do not get displayed directly, but only after the view has been destroyed and created again (e.g. on orientation change).
Is there a way force it to update the menu?

Adding a dynamic menu to NavigationView is currently bug on Design Support library. And I see that the someone has been report it to android bug source tracking. So wait till the bug will fixed. But if you want the temporary solution you can do it. First add your dynamic menu ..
navView = (NavigationView) findViewById(R.id.navView);
Menu m = navView.getMenu();
SubMenu topChannelMenu = m.addSubMenu("Top Channels");
topChannelMenu.add("Foo");
topChannelMenu.add("Bar");
topChannelMenu.add("Baz");
After adding your menu just write below code ..
MenuItem mi = m.getItem(m.size()-1);
mi.setTitle(mi.getTitle());
https://code.google.com/p/android/issues/detail?id=176300

Related

Prevent chip from double click

I have a chipgroup and some chips inside. I loop through this chipgroup, get every chip and add a checkedChangeListener for it.
for (int i = 0; i < chipGroup.getChildCount(); i++) {
final Chip chip = (Chip) chipGroup.getChildAt(i);
chip.setOnCheckedChangeListener((buttonView, isChecked) -> {
//My code
});
}
So when I open my app and click on chip, e.g. chip1, it selects it. Then when I click on that chip1 second time, it also fires the checkedChangeListener and runs my code inside it. The isChecked status is not helping, because it just changes it value like true->false->true->false on every click. But I just don't want to run my code inside onCheckedChangeListener, if the chip is already checked.
One solution I think is to save my selected chip inside fragment or ViewModel. What's your solution?
I believe you can just set a setOnCheckedChangeListener on the chipGroup instead of each individual chip. That listener will pass in an ID and isChecked as parameters. I believe using this callback on the group will be help resolve your issue. Hopefully that helps with the issue you're having.
More info on https://material.io/components/chips/android#using-chips

How to navigate between child Fragments?

I understand how to navigate between fragments using Jetpack's Navigation Component, but I haven't been able to find is how to navigate from one child fragment to another child fragment.
The following is what I've done so far:
https://pastebin.com/dNQ0Ep4S the code example is pretty big so sum it up, I'm trying to do is" A>B and Ba>Bb". Ba is a fragment inside of fragment B. I'm not sure how to set up the nav graph for something like that
The navigation works until the home fragment. The bot nav just doesn't seem to work. It always displays the pending layout. Another thing I tried was setting the nav graph of the home to the same one used for the login and adding the pending and history fragments to the nav file without any actions. But the home loads the login, the tabs work, but they're replacing the home fragment instead of being placed in the home nav host.
Update
I managed to find the problem, but I'm stuck trying to find a solution.
So B seems to be getting the navhost for A when I setup the botnavview to the navcontroller. So calling NavController navController = NavHostFragment.findNavController(this); from B returns the navhost of A. I'm at a lost here. If I do this NavController navController2 = Navigation.findNavController(currentActivity, R.id.homeNavHostFragmentContainer); (homeNavHostFragmentContainer being the navhostfor B) still returns the navhost for A. For some reason, I can't get a reference to B's navhost.
Usually we use: NavigationUI with jetpack, i recommend this, https://developer.android.com/guide/navigation with nav_graph.xml with NavigationDirections such as:
val direction = FirstFragmentDirections.actionSecondFragment()
Navigation.findNavController(requireView()).navigate(direction)
Or you can use non-jetpack way, i do not recommend, but depending on your UI you may need it:
fun displayChildFragment(frameId: Int, fragment: Fragment) {
requireActivity().supportFragmentManager?.let {
val transaction = it.beginTransaction()
//transaction.setTransition(TRANSIT_FRAGMENT_OPEN)
transaction.replace(frameId, fragment).commit()
}
}
My problem was that I misunderstood how NavHostFragment.findNavController() functions. Fragment B is not a navhost is just a regular Fragment. The navhost for B is a child of B. The argument for findNavController() has to be a NavHostFragment not a regular Fragment. So by passing, this (being B), it wasn't getting a NavFragment, just a regular Fragment. I thought the method would have extracted the navhost from whatever fragment was passed. Guess the documentation caused a bit of confusion. To get the correct navhost, I had to get the navhost from the fragment manager like so getChildFragmentManager().findFragmentById(navHostResId) (in my case, navHostResId was the id of the fragment container in B). Then everything worked beautifully.

How enable or disable correctly an Action

i have a little problem when i try to disable an Action of my Netbeans platform project. When the app starts, some Actions must be disabled, and i do that with this method:
CallableSystemAction.get(BuildProjectAction.class).setEnabled(FLAG);
It works, because the BuildProjectAction is disabled, but the corresponding items of the MenuBar and the Toolbar remains enabled until i click on one of it.
Only later that i have clicked on it, the comportament start to work correctly.
First question: Why?
If i want disable an Action, it's obvious that i want disable also the relative Icon in the Menu and in the Toolbar, so it must be automatic when i call Action.setEnabled(false).
It doesn't have sense that the Icons are not refreshed if i don't click on they.
Same problem if i try to use .getToolbarPresenter().setEnabled(false); and .getMenuPresenter().setEnabled(false);
For start the application with the icons disabled, I have tried to set the lazy attribute to FALSE and declare the image programmatically with the method setIcon(new ImageIcon(image)); that sets the same image for Menu and Toolbar.
And it works; there is only another problem: Menu and Toolbar have icons of different size (16x16 and 24x24).
It doesn't have sense that the if i set the icon with the #ActionRegistration(iconBase = "image.png") the correct icon is automatically selected, but if i use the method .setIcon(), it doesn't.
I have read some articles about Action, CookieAction, Lookup, but the only thing that i want is disable the graphic elements in the same moment when i disable the Action.
Second question: How i can do that?
This is an example of my Action.
#ActionID(
category = "Run",
id = "BuildProjectAction")
#ActionRegistration(
lazy = true,
iconBase = "images/icons/compile.png",
displayName = "#CTL_BuildProjectAction")
#ActionReferences({
#ActionReference(
path = "Menu/Run",
position = 3),
#ActionReference(path = "Toolbars/Run",
position = 3),
#ActionReference(
path = "Shortcuts",
name = "D-B")
})
#Messages("CTL_BuildProjectAction=Build Project")
public final class BuildProjectAction extends CallableSystemAction {
#Override
public void actionPerformed(ActionEvent e) {...}
#Override
public void performAction() {}
#Override
public String getName() {
return Bundle.CTL_BuildProjectAction();
}
#Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
Thanks
The easiest way to create an action that is disabled at startup is to use the platform’s New Action Wizard to create your action, and to create one that depends on a "context" -- this is, on finding a specific object in the global lookup. If no object is available in the lookup, as at startup, then the action will be disabled.
The menu and toolbar graphic elements are bundled together with your action via the annotations. This means that enabled/disabled state of your context-aware action will automatically affect the icons in the menu and toolbar as well.
This article by Geertjan Wielenga has a walkthrough on creating a context-aware action:
http://netbeans.dzone.com/how-to-make-context-sensitive-actions
When you want to enable your action, you will add the object on which the action depends into the global lookup, which will cause the action (and its graphic elements) to be enabled.
This entry in the platform’s Developer FAQ has some examples of how to add an object to the global context:
http://wiki.netbeans.org/DevFaqAddGlobalContext
If you need to create an action that depends on a more complex set of conditions there is some discussion, as well as a code sample illustrating how to do this, in this platform developer list thread:
http://forums.netbeans.org/ptopic55295.html
The grayed-out versions of the icons that are shown when your action is disabled are created automatically by the platform. You only have to provide the "normal" non-grayed-out images.
As for the icons of different sizes, it’s a matter of filename convention. If your annotation declares the icon with #ActionRegistration(iconBase = "image.png”), then you will provide a 16x16 image called “image.png” and a 24x24 version called “image24.png”. The platform will find and use the appropriate size in the menu and toolbar.

Disable/enable toolbar menu item depending on toggle sate

I am working with enable/disable state of toolbar items.
I need to disable second menu until the first one is in toggle on state. For this I try to get toggle state of the first menu item. But the state is always NULL.
ICommandService service = (ICommandService) PlatformUI.getWorkbench().
getService(ICommandService.class);
Command command = service.getCommand("com.commandID");
State state = command.getState("org.eclipse.ui.commands.toggleState");
Somebody knows what is the problem? Maybe there is a better way to solve it?
Have you registered ToggleState for your command?
Since it is possible to have multiple menu contributions for the same
command, we have to keep track of the state in a central place.
Imagine a toggle button triggerable from the main menu and a views
toolbar. The state of these buttons are keept in sync by storing the
state directly in the command. The key to this is the
org.eclipse.jface.commands.ToggleState.
<command id="org.eclipse.example.command.toggle"
name="Toggle Me">
<state class="org.eclipse.jface.commands.ToggleState"
id="org.eclipse.example.command.toggleState" />
</command>
Please read this blog post for more details.

Nested Android SlidingMenus possible?

I'm using the sliding menu library here: https://github.com/jfeinstein10/SlidingMenu/
and I have an activity that inherits from SlidingMenuActivity with a sliding menu that works perfectly, but I also want to add SlidingMenus to each row in a list fragment that is shown as part of this SlidingMenuActivity subclass. It seems that the way I'm doing it doesn't work at all; the touches get intercepted and they don't let me click on a list row, but I can't swipe the sliding menu into appearance, nor can I see the SlidingMenu when it's closed.
This is the code that I'm using to add the sliding menu to each list row:
private void makeSlidingMenu(View view) {
FrameLayout menuClosedFrame = // ... the above view
RelativeLayout menuLayout = // ... the behind view
SlidingMenu slidingMenu = new SlidingMenu(view.getContext());
slidingMenu.setContent(menuClosedFrame);
slidingMenu.setMenu(menuLayout);
slidingMenu.setBackgroundColor(Color.RED);
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
slidingMenu.setTouchModeBehind(SlidingMenu.TOUCHMODE_FULLSCREEN);
slidingMenu.setBehindScrollScale(1.0f);
slidingMenu.setFadeDegree(0.0f);
RelativeLayout layout = (RelativeLayout)view;
layout.addView(slidingMenu, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) {{
addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
}});
}
It's not pretty, but it seems to get the job done on a normal activity that doesn't have a list view and is not a SlidingMenuActivity. It just doesn't work in a nested scenario with a ListView for me. Is there anything else I could be doing wrong? If posting more code would help let me know. Thanks!
Figured it out; the way I was adding the sliding menu to the row was causing it to be sized improperly I think; I fixed it by adding it to a framelayout instead that also contains the contents I want to show since i want the cell's main content to remain static.

Categories