I'm doing a mobile application in Android with JAVA using a DialogFragment with Toolbar.
I want to hide a menu item conditionally.
Menu
<?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/action_favorite"
android:title="favorite"
android:icon="#drawable/ic_favorite_white_off_24dp"
app:showAsAction="always" />
<item
android:id="#+id/action_delete"
android:title="delete"
android:icon="#drawable/ic_delete_white_24dp"
app:showAsAction="always" />
<item
android:id="#+id/action_save"
android:title="save"
app:showAsAction="always" />
</menu>
Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:paddingStart="6dp"
android:paddingEnd="16dp"
app:contentInsetStartWithNavigation="0dp"
app:navigationIcon="#drawable/ic_close_black_24dp" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!-- EditText's and buttons ..... -->
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
DialogFragment
public class MyDialogFragment extends DialogFragment implements Toolbar.OnClickListener, Toolbar.OnMenuItemClickListener {
public static final String TAG = "my_dialog";
private Toolbar toolbar;
public static MyDialogFragment display(FragmentManager fragmentManager) {
NewPersonDialogFragment exampleDialog = new NewPersonDialogFragment();
exampleDialog.show(fragmentManager, TAG);
return exampleDialog;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(NewPersonDialogFragment.STYLE_NORMAL, R.style.AppTheme_FullScreenDialog);
}
#Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width, height);
dialog.getWindow().setWindowAnimations(R.style.AppTheme_Slide);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.dialog_fragment_new_person, container, false);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toolbar = view.findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.new_person_dialog_menu);
toolbar.setNavigationOnClickListener(this);
toolbar.setOnMenuItemClickListener(this);
toolbar.setTitle("Add new");
}
#Override
public void onClick(View v) {
// This is working fine
}
#Override
public boolean onMenuItemClick(MenuItem item) {
// This is working fine
switch (item.getItemId()) {
case R.id.action_favorite:
return true;
case R.id.action_delete:
return true;
case R.id.action_save:
return true;
default:
return false;
}
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// Removing item doesn't work!
menu.removeItem(R.id.action_delete);
}
}
I open the DialogFragment like this:
MyDialogFragment.display(getActivity().getSupportFragmentManager());
When I open the DialogFragment, the menu item is not hidden.
As other topics says, I have tried:
setHasOptionsMenu(true) in onActivityCreated method.
getActivity().invalidateOptionsMenu() in onPrepareOptionsMenu method.
My goal is to hide/remove a menu item based on a condition when the user opens the DialogFragment.
Related
Why option menu does not show in this code while option menu declear in Blank fragment
BasicActivity.java - Here my first entry code
public class BasicActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic);
FragmentLoader.loadFragment(this, R.id.container, new BlankFragment());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
boolean retVal = super.onCreateOptionsMenu(menu);
return retVal;
}
#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.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
activity_basic.xml xml file of activity basic
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BasicActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
BlankFragment.java - when i include toolbar option it appers but option menu in this fragment doesnot appear
public class BlankFragment extends Fragment {
private static final String TAG = BlankFragment.class.getName();
// TODO: Customize parameter initialization
#SuppressWarnings("unused")
public static BlankFragment newInstance( ) {
BlankFragment fragment = new BlankFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank, container, false);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.episodes, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
}
fragment_blank.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BlankFragment" >
<!-- tools:context=".MainActivity2">-->
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="180dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="InconsistentLayout"
android:theme="#style/Theme.Fragment.AppBarOverlay"
android:fitsSystemWindows="true" >
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/chat_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
android:background="#color/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="#+id/toolbar">
<ImageView
android:id="#+id/mainAppbarImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:minHeight="?actionBarSize"
android:padding="10dp"
android:text="#string/app_name"
android:textAppearance="#style/TextAppearance.Widget.AppCompat.Toolbar.Title" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="#style/Theme.Fragment.PopupOverlay" >
<!-- <include layout="#layout/layout_main_toolbar" />-->
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/chat_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#mipmap/ic_forward"
app:backgroundTint="#color/colorPrimary"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The structure of my app , an Activity with fragments that use navigationcomponent.
In the toolbar of my HomeFragment there is a toolbar with a search icon as a menu. This clicked icon leads to the search activity.
HomeFragment
Browsing in my app and changing fragment up to the ProfileFragment, I have the opportunity to view my lists and clicking on one of these opens another fragment to show the contents of that list
ProfileFragment, ShowListContent.
Now here's the magic
If I click on the toolbar icon to change the description of my list everything is perfect and we are delighted but ...
New HomeFragment
If I go back to the HomeFragment, the icon in the toolbar is no longer the same and I cannot go to the SearchActivity.
What can I do to avoid this problem?
Code time
public class HomeFragment extends Fragment{
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragment_home, container,
false);
initToolbar(view);
//other code
return view;
}
private void initToolbar(View view) {
Toolbar toolbar = view.findViewById(R.id.app_bar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
toolbar.inflateMenu(R.menu.menu_main_toolbar);
}
#Override
public void onCreateOptionsMenu(#NotNull Menu menu, #NotNull MenuInflater
inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.menu_main_toolbar, menu);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_search) {
Intent intent = new Intent(getActivity(), SearchActivity.class);
startActivity(intent);
}
return true;
}
}
fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#141a32"
tools:context=".fragments.HomeFragment">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/app_bar"
style="#style/toolbar"
app:menu="#menu/menu_main_toolbar"
app:titleTextAppearance="#style/Toolbar.TitleText"
app:titleTextColor="#color/white" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout">
//other code
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
ShowContentListFragment
public class ShowContentListFragment extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragments_layout_lists, container, false);
setHasOptionsMenu(true);
getDataFromSafeArgs();
initWidgets(view);
initToolbar();
return view;
}
private void initToolbar() {
toolbar.setVisibility(View.VISIBLE);
toolbar.setNavigationIcon(R.drawable.ic_friend_list_back_button);
toolbar.inflateMenu(R.menu.menu_profile_edit_list);
toolbar.setNavigationOnClickListener(v -> {
Navigation.findNavController(getView())
.navigate(R.id.action_showContentListFragment_to_profileFragmentOriginal);
movies_into_list.clear();
getAndPostMovieIntoLIstModel.clearPersonalList();
});
toolbar.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.menu_edit) {
dialogModifyDescription();
return true;
} else {
return false;
}
});
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_profile_edit_list, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
fragment_showListContent.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/big_stone"
tools:context=".fragments.MyListsFragment">
<include
layout="#layout/layout_toolbar"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
//other code
</androidx.constraintlayout.widget.ConstraintLayout>
You should have 1 toolbar and maybe 1 menu and instead disable/enable icons using menu.findItem(R.id.menu_edit).setVisible(true/false);
Maybe you could try calling requireActivity().invalidateOptionsMenu() as well.
I am trying to add ActionBar (Toolbar) inside fragment and then set Button to "end" of this action bar and add onClickListener on that button.
Cannot use support.v7.widget.ToolBar (I dont know why but I could not implement it)so I had to use androidx.appcompat.widget.Toolbar instead.
I could not find any source to follow.
app_bar_layout.xml:
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_app_toolbar"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
</androidx.appcompat.widget.Toolbar>
Fragment's design fragment_wall.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WallFragment"
android:background="#color/colorWhite">
<include
android:id="#+id/update_wall_page_toolbar"
layout="#layout/app_bar_layout"></include>
</FrameLayout>
Code in WallFragment.java
public class WallFragment extends Fragment {
public WallFragment() {
// Required empty public constructor
}
private Toolbar TopActivityToolbar;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_wall, container, false);
TopActivityToolbar = v.findViewById(R.id.update_wall_page_toolbar);
TopActivityToolbar.setTitle("Príspevky");
TopActivityToolbar.setLogo(ContextCompat.getDrawable(getActivity(),R.drawable.ic_add_circle_black_24dp));
return v;
}
}
so what was the successfull answer for me:
Inside onCreate method just add setHasOptionsMenu(true);
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
Inside my WallFragment.java in onCreateView I added setOnMenuItemClickListener just right after initializing the Toolbar
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View inflatedView = inflater.inflate(R.layout.fragment_wall, container, false);
TopActivityToolbar = inflatedView.findViewById(R.id.update_wall_page_toolbar);
TopActivityToolbar.setTitle("someTitle");
TopActivityToolbar.inflateMenu(R.menu.menu_app_actionbar_wall);
// and finally set click listener
TopActivityToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
// Your code inside Toolbar onClick...
return false;
}
});
return inflatedView;
}
Do not forget to to INFLATE the menu from res/menu/...
Add Toolbar inside fragment (AndroidX),you should use the onCreateOptionsMenu() method inside fragment.
#Override
public void onCreateOptionsMenu(
Menu menu, MenuInflater inflater) {inflater.inflate(R.menu.example_menu, menu);
}
First,you have to call setHasOptionsMenu() within the fragment's onCreate() method:
setHasOptionsMenu(true);
//For handling item selection
You can handle menu item clicks in the onOptionsItemSelected() method:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.itemId:
//action
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Full Example code is below:
In this example One activity: Main activity:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="200dp"
android:id="#+id/fragment_id"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click"
android:onClick="changeFragment"
android:layout_gravity="center"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
FrameLayout frameLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadFragment(new FirstFragment());
}
private void loadFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_id, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
public void changeFragment(View view) {
loadFragment(new SecondFragment());
}
}
There is two fragment in this example:
FirstFragment and SecondFragment.
FirstFragment.java :
public class FirstFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.first_layout,container,false);
return view;
}
#Override
public void onCreateOptionsMenu(
Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.first_item_menu, menu);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
//For handling item selection
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.itemId:
Toast.makeText(getContext(),"First Fragment item",Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
SecondFragment.java
public class SecondFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.second_frag,container,false);
return view;
}
#Override
public void onCreateOptionsMenu(
Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.second_item_menu, menu);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
//For handling item selection
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.itemId1:
Toast.makeText(getContext(),"Second Fragment item",Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
In menu file,app:showAsAction="ifRoom" in your menu item.Below is example code for menu file.
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/itemId"
android:icon="#drawable/ic_apps_black_24dp"
android:title="First"
app:showAsAction="ifRoom">
</item>
</menu>
First of all, to make it work you need to call this code in onCreateView callback of fragment that is needed to have a menu;
setHasOptionsMenu(true);
Then you are able to inflate the menu and set listener to handle clicks on item:
inflater.inflate(*R.menu.your_menu_resource*, menu);
After that you are able to override onCreateOptionsMenu and onOptionsItemSelected to provide logic that is needed:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.toolbar, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.toolbar_seetings) {
Toast.makeText(getContext(), "Menu item was clicked", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
After that you just need to handle App Bar visibility, so you need to place the code in onCreateView and it will look like that:
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
((AppCompatActivity) getActivity()).getSupportActionBar().show();
return inflater.inflate(R.layout.fragment_home, container, false);
}
I have two fragments one is list fragment and the other one i'm using it as dialog once and as fragment my problem here with option menu, in list fragment there's an item menu given show always action and in dialog fragment i don't want this item to be visible and i don't want option menu to be visible too, i have tried to
setHasOptionMenu(false)
but it didn't work and tried to setHasOptionMenu(true) and clear all items in menu but it didn't work neither.
Also, my parent activity doesn't have any code for option menu.
here's my code:
#SuppressLint("InflateParams")
public class FormGeneratorActivity extends DialogFragment {
Control mControl;
boolean doChangeTitle;
private boolean isDialog;
public static int CreatedNum = 0;
public static FormGeneratorActivity getInstance(Control mControl, boolean doChangeTitle) {
FormGeneratorActivity frag = new FormGeneratorActivity();
Bundle b = new Bundle();
b.putParcelable("control", mControl);
b.putBoolean("changeTitle", doChangeTitle);
frag.setArguments(b);
return frag;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
doChangeTitle = getArguments().getBoolean("changeTitle");
}
setHasOptionsMenu(false);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
menu.clear();
activity.invalidateOptionsMenu();
super.onPrepareOptionsMenu(menu);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
public void setDoChangeTitle(boolean doChangeTitle) {
this.doChangeTitle = doChangeTitle;
}
View view;
boolean isInflated = false;
ParentActivity activity;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (view == null) {
mControl = getArguments().getParcelable("control");
view = inflater.inflate(R.layout.form_generator_fragment, container, false);
container = (LinearLayout) view.findViewById(R.id.cont);
isInflated = true;
} else {
if (view.getParent() != null)
((ViewGroup) view.getParent()).removeAllViews();
isInflated = false;
}
return view;
}
String headerPageTitle = null;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity = (ParentActivity) getActivity();
activity.getSupportActionBar().invalidateOptionsMenu();
CreatedNum++;
}
#Override
public void onResume() {
super.onResume();
activity.setPageTitle(headerPageTitle);
setHasOptionsMenu(false);
activity.getSupportActionBar().invalidateOptionsMenu();
}
public void isDialog(boolean b) {
isDialog = b;
}
}
Option menu in DialogFragment(Fragment) with Search(SearchView) action:
MenuDialogFragment.class
public class MenuDialogFragment extends DialogFragment {
Toolbar toolbar;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.custom_dialog_layout, container, false);
toolbar = view.findViewById(R.id.custom_dialog_layout_toolbar);
toolbar.inflateMenu(R.menu.menu_custom_dialog);
Menu menu = toolbar.getMenu();
SearchView searchView = (SearchView) menu.findItem(R.id.menu_searchview).getActionView();
// DO whatever you need with menu items
return view;
}
}
menu_custom_dialog.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_searchview"
android:icon="#drawable/ic_search"
android:title="Search"
app:showAsAction="always|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"
/>
</menu>
custom_dialog_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v7.widget.Toolbar
android:id="#+id/custom_dialog_layout_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
/>
</LinearLayout>
you can try to set parent fragment like: fragment.setTargetFragment(getSupportFragmentManager().findFragmentById(R.id.frame), 1);
and in child fragment you perform (in onAttach/onDetach methods)
getTargetFragment().setMenuVisibility(true);
Maybe try to use one of the dialog themes when you call this fragment as dialog.
To do this you can use this constructor:
AlertDialog.Builder(Context context, int theme)
ie
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),
theme)
Some more explanation:
Theme not applying to DialogFragment on Android
i found out that dialog fragment only needs time to know that the option menu doesn't exist any more so i had to post delay using handler before i start the fragment
In menu/ Genre.xml:
<?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/nav_home"
android:icon="#drawable/ic_home_black_48dp"
android:title="Home" />
<item
android:id="#+id/nav_genre"
android:icon="#drawable/ic_toc_black_48dp"
android:title="Genres" />
<item
android:id="#+id/nav_download"
android:icon="#drawable/ic_get_app_black_48dp"
android:title="Download" />
</group>
<item android:title="Account">
<menu>
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_about"
android:icon="#drawable/ic_lock_open_black_48dp"
android:title="About"/>
<item
android:id="#+id/nav_signout"
android:icon="#drawable/ic_perm_identity_black_48dp"
android:title="Sign out"/>
</group>
</menu>
</item>
</menu>
In layout/GenreFragment.axml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lst_genre"
android:layout_height="match_parent"
android:layout_width="match_parent" />
In viewModel/ GenreFragmentVM:
public class GenerFragmentVM : Fragment
{
public override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
// Create your fragment here
}
ListView lst;
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
// return inflater.Inflate(Resource.Layout.YourFragment, container, false);
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.abc_list_menu_item_layout, container, false);
lst = view.FindViewById<ListView> (Resource.Id.lst_genre);
lst.SetAdapter(new ArrayAdapter<string> (this,Resource.Layout.abc_list_menu_item_layout,Resource.Menu.Genres));
//Event click on listview
lst.ItemClick+= delegate(object sender, AdapterView.ItemClickEventArgs e) {
};
}
}
Error: (19,19): Error CS1502: The best overloaded method match for
`Android.Widget.ArrayAdapter.ArrayAdapter(Android.Content.Context,
int, int)' has some invalid arguments (CS1502) (SoundCloud)
(45,45): Error CS1503: Argument #1' cannot convert
SoundCloud.GenerFragment' expression to type
`Android.Content.Context' (CS1503) (SoundCloud)
In Mainactivity.cs
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
// Set our view from the "main" layout resource
//ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
SetContentView (Resource.Layout.Main);
var mToolbar= FindViewById<Toolbar> (Resource.Id.toolbar);
//Toolbar will now take on default action bar chacracteritics
SetActionBar(mToolbar);
ActionBar.Title = "home";
//Enable suppport action bar to display hamburger
//ActionBar.SetHomeAsUpIndicator(Resource.Drawable.icon_hambuger);
//ActionBar.SetDisplayHomeAsUpEnabled (true);
//Set menu hambuger
ActionBar.SetHomeAsUpIndicator (Resource.Drawable.ic_menu_white_24dp);
ActionBar.SetDisplayHomeAsUpEnabled (true);
drawerLayout = FindViewById<DrawerLayout> (Resource.Id.drawer_layout);
navigationView = FindViewById<NavigationView> (Resource.Id.nav_view);
//Event click on navigatonView
//
CreateFragments();
LoadInditialFragment ();
navigationView.NavigationItemSelected += NavigationView_NavigationItemSelected;
}
void NavigationView_NavigationItemSelected (object sender, NavigationView.NavigationItemSelectedEventArgs e)
{
e.MenuItem.SetChecked (true);
if (e.MenuItem.ItemId != currentFragmentId) {
SwitchFragment (e.MenuItem.ItemId);
}
drawerLayout.CloseDrawers ();
}
// Khoi tao gia tri cho fragment layout
private void CreateFragments()
{
explorFragment= new ExploreFragment();
genreFragment = new GenerFragment ();
}
//
private void LoadInditialFragment ()
{
var transaction = FragmentManager.BeginTransaction ();
transaction.Add (Resource.Id.fragmentContainer, explorFragment).Hide (explorFragment);
transaction.Add (Resource.Id.fragmentContainer, genreFragment);
transaction.Commit ();
}
private void SwitchFragment(int FragmentId)
{
var transaction = FragmentManager.BeginTransaction ();
switch (currentFragmentId) {
case Resource.Id.nav_home:
transaction.Hide (explorFragment).Commit ();
break;
case Resource.Id.nav_genre:
transaction.Hide (genreFragment).Commit ();
break;
}
transaction = FragmentManager.BeginTransaction ();
switch (FragmentId) {
case Resource.Id.nav_home:
transaction.Show (explorFragment);
transaction.Commit ();
break;
case Resource.Id.nav_genre:
transaction.Show (genreFragment);
transaction.Commit ();
break;
}
currentFragmentId = FragmentId;
}
<?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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- your content layout -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:titleTextColor="#android:color/background_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout>
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:id="#+id/nav_view"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/navmenu" />
</android.support.v4.widget.DrawerLayout>
Reason for your first Build Error is as explained by SushiHangover, i.e You should be passing an instance of the parent Activity (activity which hosts this fragment) as the first parameter to ArrayAdapter Constructor.
Reason for your run-time (Object reference not set to an instance of an object) Exception is because "Activity" property is null. "Activity" property will have a value only when the Fragment attachment to parent Activity is complete. So essentially, you should not be accessing Activity property from OnCreateView Method. You can initialize your listview either in OnAttach or OnCreate callbacks. I am modifying your code accordingly.
`public class GenerFragmentVM : Fragment
{
ListView lst;
public override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
lst.SetAdapter(new ArrayAdapter<string> (this.Activity,Resource.Layout.abc_list_menu_item_layout,Resource.Menu.Genres));
}
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.abc_list_menu_item_layout, container, false);
lst = view.FindViewById<ListView> (Resource.Id.lst_genre);
//Event click on listview
lst.ItemClick+= delegate(object sender, AdapterView.ItemClickEventArgs e) {
};
return view;
}
}
Passing the Activity of your Fragment as the first arg of the Widget's ArrayAdapter
Added a return of your new view;
Code:
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView (inflater, container, savedInstanceState);
var view = inflater.Inflate (Resource.Layout.abc_list_menu_item_layout, container, false);
lst = view.FindViewById<ListView> (Resource.Id.lst_genre);
lst.SetAdapter(new ArrayAdapter<string> (this.Activity,Resource.Layout.abc_list_menu_item_layout,Resource.Menu.Genres));
//Event click on listview
lst.ItemClick+= delegate(object sender, AdapterView.ItemClickEventArgs e) {
};
return view;
}