I added a spinner to menu and I would like to add items dynamically to the spinner. But the problem is that Spinner is pretty deep in layouts.
I have a view of main action with navigation -> that includes main action view and contains NavigationView -> NavigationView has menu -> menu contains items -> one of items contains another menu and first item of that menu is Spinner.
Is there any better way to add dropdown to the menu? If not, how do I access the spinner?
Thanks for the help
Code:
MainActivity.kt:
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, AdapterView.OnItemSelectedListener{
private lateinit var activities: Spinner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_with_nav)
activities = this.findViewById(R.id.menu_activity_select) //--- throws exception
activity_main_with_nav.xml :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start"
android:theme="#style/Theme.AppCompat.Light.NoActionBar">
<include
layout="#layout/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_main"
app:menu="#menu/main_menu" />
</android.support.v4.widget.DrawerLayout>
main_menu.xml :
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_activity"
android:title="#string/menu_activity">
<menu>
<item android:id="#+id/menu_activity_select"
android:title="#string/menu_activity_select"
app:actionViewClass="android.widget.Spinner"
/> <!-- this is the spinner I am looking for -->
<item android:id="#+id/menu_activity_activate_devices"
android:icon="#android:drawable/ic_dialog_dialer"
android:title="#string/menu_activity_activate_devices" />
<item android:id="#+id/menu_activity_camera"
android:icon="#android:drawable/ic_menu_camera"
android:title="#string/menu_activity_camera" />
</menu>
</item>
<group>
<item android:id="#+id/menu_scan_qr"
android:icon="#drawable/ic_codigo_qr"
android:title="#string/menu_scan_qr" />
<item android:id="#+id/menu_calendar"
android:icon="#android:drawable/ic_menu_month"
android:title="#string/menu_calendar" />
<item android:id="#+id/menu_settings"
android:icon="#android:drawable/ic_menu_manage"
android:title="#string/menu_settings" />
</group>
</menu>
It should not matter how deep the spinner is in the layout. If you are calling findViewById() in the correct view hierarchy, it should give you the instance of spinner. Once you get the instance of the spinner you just need to set the adapter with items. If you want to add items dynamically just add the new item in the whatever data structure have you used for the adapter. After then call notifyDataSetChanged() on the adapter.
Related
I am developping an application which asks you to log in, and start an activity depending on your account. The problem is that I have a drawer layout, and I need to change the menu.xml file depending of the activity. I know that it is possible to use conditional structures in an XML file. Is there any way to retrieve the name of the calling Activity in the XML file?
That would allow me to load a different menu depending of the name of the activity calling the XML file.
This is the XML file calling the menu_main.xml file :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.NavigationView
style="#style/nav_view"
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:itemTextColor="#FFFFFF"
app:menu="#menu/menu_main"/>
And the XML file :
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:checkableBehavior="single"
>
<item
android:id="#+id/nav_profile"
android:checked="true"
android:title="#string/nav_profile"/>
<item
android:id="#+id/nav_search"
android:title="#string/nav_organisation"/>
<item
android:id="#+id/nav_logout"
android:title="#string/nav_logout"
/>
</group>
Thanks in advance !
Do you really want to do such a thing inside a xml?
You can set menu dynamically prom java code:
navigationView.getMenu().clear(); //clear old items
navigationView.inflateMenu(R.menu.new_navigation_drawer_items); //inflate new menu
or
Menu menu = navigationView.getMenu(); //get current menu
menu.add();//add an item
I need your help please help me.
I have a navigation drawer in my app. i want to move navigation drawer to right completely . I moved the navigation itself but i want to move menu items to right too.
My Screenshot of Navigation Drawer
Activity_main:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_marginleft="100dip"
android:fitsSystemWindows="true"
tools:openDrawer="end">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
My items of menu in xml :
Activity_Main_Drawer:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/nav_home" />
<item
android:id="#+id/nav_photos"
android:icon="#drawable/ic_photo_library_black_24dp"
android:title="#string/nav_photos" />
<item
android:id="#+id/nav_movies"
android:icon="#drawable/ic_local_movies_black_24dp"
android:title="#string/nav_movies" />
<item
android:id="#+id/nav_notifications"
android:icon="#drawable/ic_notifications_black_24dp"
android:title="#string/nav_notifications" />
<item
android:id="#+id/nav_settings"
android:icon="#drawable/ic_settings_black_24dp"
android:title="#string/nav_settings" />
</group>
<item android:title="Other">
<menu>
<item
android:id="#+id/nav_about_us"
android:title="#string/nav_about_us" />
<item
android:id="#+id/nav_privacy_policy"
android:title="#string/privacy_policy" />
</menu>
</item>
</menu>
first: You can put your device in RTL mode, go to develop settings (Force RTL layout direction).
After doing this all the layouts will mirror correctly.
If you don't want to change the whole device into RTL use this code in onCreate method of mainactivity before super and before you inflate the content view
window.decorView.layoutDirection = View.LAYOUT_DIRECTION_RTL
You need to use a custom layout for NavigationView.
According to this: http://www.kamilslesinski.com/home/navigation-drawer-customising-navigationview-items you can override the layout by copying original file and customizing it, or you can add a reference to your custom layout, like that:
how to customize snackBar's layout?
in refs.xml.
I have this Layout:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- The ActionBar -->
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- The main content view -->
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- The navigation drawer -->
<android.support.design.widget.NavigationView
android:id="#+id/nvView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
app:menu="#menu/drawer_menu"
app:headerLayout="#layout/nav_header"/>
So, looking that in NavigationView we have the attribute:
app:menu="#menu/drawer_menu"
And I have this XML id menu folder.
I wanna make dynamic menus, ie, in code I should mount the 'MenuItem' objects and set into NavigationView.
Is this correct?
Is this best pratice?
Is this possible?
Note: My code is working with 'static drawer_menu', I want to improve it.
I'm waiting.
[EDIT]
I make it:
Menu menu = nvDrawer.getMenu();
for (KSMenuItem kmi : menus.values()) {
if (menu.size() == 0) {
menu.add(kmi.getId());
}
if (menu.getItem(kmi.getId()) == null) {
menu.add(kmi.getId());
}
MenuItem mi = menu.getItem(kmi.getId());
mi.setIcon(kmi.getIcon());
mi.setTitle(kmi.getTittle());
}
But this error happened:
06-27 15:26:15.538 15335-15335/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.sticdev30.newdrawer, PID: 15335
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sticdev30.newdrawer/com.example.sticdev30.newdrawer.MainActivity}: android.content.res.Resources$NotFoundException: String resource ID #0x1
KSMenuItem is a POJO with my menu data. In kmi.id I informed incremental integers...
I'm waitning
You can re-inflate NavigationViewat runtime with 2 lines of code using public method inflateMenu. In this example i re-inflate with new_navigation_drawer_items.xml
navigationView.getMenu().clear(); //clear old inflated items.
navigationView.inflateMenu(R.menu.new_navigation_drawer_items); //inflate new items.
You can add menus dynamically by following steps :
Step1. Obtain menu object from Navigation View NavigationView.getMenu()
Step2. Add any item to the menu using Menu.add()
We can dynamically add/remove menu items.
Suppose we have this menu items `
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#mipmap/home_icon_x48"
android:title="Home" />
<item
android:id="#+id/nav_part_catalouge"
android:icon="#mipmap/catalogue_icon_x48"
android:title="Parts Catalogue" />
<item
android:id="#+id/nav_favourite"
android:icon="#mipmap/my_favourate_x48"
android:title="My-Favourite" />\
<item
android:id="#+id/nav_opencarrequest"
android:icon="#mipmap/cart_request"
android:title="Cart-Request" />
<item
android:id="#+id/nav_setting"
android:icon="#mipmap/settings_x48"
android:title="Settings" />
</group>
<item android:title="">
<menu>
<item
android:id="#+id/nav_logout"
android:icon="#mipmap/logout_icon_x48"
android:title="Logout" />
</menu>
</item>
`
In Activity we can add or remove menuitems based on our condition
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);// your activity layout here
NavigationView navigationView= (NavigationView) findViewById(R.id.nav_view); // navigation view which holds menu items
navigationView.setNavigationItemSelectedListener(this);
if(yourCondition){
navigationView.getMenu().getItem(0).setVisible(false); //if you want to hide first item
navigationView.getMenu().getItem(1).setVisible(true); // if you want to show second menu item should be visible
}
}
Hope it will help.
Seems like kmi.getId() returns int(or long).
But Menu.add(int) adds menu with title from the given string resources, which is usually represented as R.string.something, and not for usual integer values.
Menu.add(CharSequence) does add menu with title of CharSequence, so you need to do some int-to-string conversion like menu.add(kmi.getId() + "");
My question is related to recently released Navigation View from Design Support Library.
I want to position Log In at the bottom of the Navigation View, how I can do this?
My menu XML right now, look like this :
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/navigation_sub_item_1"
android:icon="#drawable/ic_action_event"
android:title="#string/home" />
<item
android:id="#+id/navigation_sub_item_2"
android:icon="#drawable/ic_action_person"
android:title="#string/profile" />
<item
android:id="#+id/navigation_sub_item_3"
android:icon="#drawable/ic_action_labels"
android:title="#string/tags" />
<item
android:id="#+id/navigation_sub_item_4"
android:icon="#drawable/ic_action_settings"
android:title="#string/log_in" />
</group>
</menu>
Here is my layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#color/white_1000">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar">
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/main_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/drawer_menu" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
Do you want your "Log In" item to be fixed at the bottom of the Navigation View?
You can do that by nesting additional views/layouts within NavigationView. NavigationView extends FrameLayout, so you can wrap it around child views.
I posted more information on NavigationView footers here. Also see the other answers in that post for more layout options.
Edit
FYI: If you use the "fixed footer" approach, you are basically removing the footer item (e.g. "Log In" in your example) from the menu. That means you have to implement click and other handlers yourself.
I think navigation menu works like a listview. So Items will be placed in a list.
If you want one item to be placed at the bottom, you can customise within the NavigationView Tag in layout xml
I have a listview, where I want to highlight selected items in a custom way. I'm setting every item properties in the adapter's getView method, including itemView.setSelected(true).
The main layout defines the listview in the following way:
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="multipleChoice"
android:listSelector="#drawable/list_selector" />
(Playing with choice mode does not help either).
The list_selector is an almost empty stub:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#android:color/transparent" />
</selector>
I don't need specific styles for listview as a whole, so I'd leave a default one, but according to this answer, we need a selector for a listview for item selector to work. Anyway, without the list_selector the problem remains.
The listview item layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:background="#drawable/listitem_background"
android:orientation="vertical">
and it references the following listitem_background selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="#android:color/white" />
<item android:drawable="#android:color/transparent" />
</selector>
The problem is, that selected items do not have white background.
If I change android:state_selected="true" selector in the listitem_background to, for example, android:state_pressed="true", then the selector starts to work, that is item background becomes white if an item is touched.
So, I suppose, there is an error either in the selectors, or in the way how I select items.
I can write a workaround by setting background from Java or utilizing checkable states, but I want to understand and fix current problem with selectors. Thanks in advance.
What about adding this line in your item view?
android:background="?android:attr/activatedBackgroundIndicator"
For instance:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/activatedBackgroundIndicator"
android:orientation="vertical" >
<TextView
android:id="#+id/textViewListRowOption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical" />
</LinearLayout>
Then the selector looks something like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="#android:integer/config_mediumAnimTime">
<item android:drawable="#drawable/list_pressed" android:state_pressed="true"/>
<item android:drawable="#drawable/list_selected" android:state_activated="true"/>
<item android:drawable="#drawable/list_default"/>
</selector>
And the list view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listViewMainFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:listSelector="#drawable/list_item_selector"
android:choiceMode="singleChoice">
</ListView>
</LinearLayout>
Try this one to change the selected list item.Put it inside the list view.
if (currentSelectedView != null && currentSelectedView != v) {
unhighlightCurrentRow(currentSelectedView);
}
currentSelectedView = v;
highlightCurrentRow(currentSelectedView);
private void unhighlightCurrentRow(View rowView) {
rowView.setBackgroundColor(Color.TRANSPARENT);//to set a color for un-seclected row
}
private void highlightCurrentRow(View rowView) {
rowView.setBackgroundResource(R.drawable.selector_img);//to set a color for seclected row
}