Toolbar actionButton disappeared and not showing again - android

I'm working with a toolbar that has a search action button, it was used to work and suddenly it stopped showing it to me. This is my code:
In my menu folder
menu_feed.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_search"
android:icon="#android:drawable/ic_menu_search"
android:title="#string/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView" />
</menu>
This is the class where i call that item and inflates it into the toolbar
FeedFragment.class
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_feed, container, false);
setupToolbar(v);
return v;
}
private void setupToolbar(View v) {
AppCompatActivity activity = (AppCompatActivity) getActivity();
toolbar = (Toolbar) v.findViewById(R.id.toolbar);
activity.setSupportActionBar(toolbar);
setHasOptionsMenu(true);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setupRV();
mFeedPostsPresenter = new FeedPostsPresenterImpl(this);
}
private void setupRV() {
mFeedPostsRV = (RecyclerView) getView().findViewById(R.id.feed_posts_list);
mFeedPostsRV.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
mFeedPostsRV.setLayoutManager(layoutManager);
RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setAddDuration(1000);
itemAnimator.setRemoveDuration(1000);
mFeedPostsRV.setItemAnimator(itemAnimator);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_feed, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_search){
Intent i = new Intent(getActivity(), SearchUsersActivity.class);
startActivity(i);
}
return super.onOptionsItemSelected(item);
}
}
For some reason I don't know why this search button disappeared from my toolbar and I can't see it again, this is my output from menu_feed.xml:
And in runtime inside my app there is no action_search:

The "collapseActionView" allows the button to be shown but as a widget. This button can be dynamic, like a search button that expands. Check this: Documentation. Try deleting this in your menu_feel.xml

Related

Implement menu in fragment in Android studio

I want to implement menu in fragment class. The fragment works fine and there is not error but there is no menu shown in the fragment. I am implementing the class in the following way
public class FilesFragment extends Fragment {
public FilesFragment() {
// Required empty public constructor
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_files, container, false);
return view;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
inflater.inflate(R.menu.files_menu,menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_setting){
Toast.makeText(getActivity(),"setting clicked",Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
}
and this is the xml file of files_menu in menu folder.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_setting"
android:title="settings"
app:showAsAction="never"/>
<item
android:id="#+id/aobut"
android:title="About"
app:showAsAction="never"
/>
</menu>
The above code is not showing the menu at all. How do menu is implemented in the fragment?
You can populate the menu in any view without any complexity. Use the following code and enjoy.
any View can be a button , imageView or any other else in which you want to inflate this menu. No need to add menu in xml. Just do in java
PopupMenu popup = new PopupMenu(context, any View);
popup.inflate(R.menu.files_menu );
popup.setOnMenuItemClickListener(item -> {
int id = item.getItemId();
if (id == R.id.action_setting) {
// do stuff
} else if (id == R.id.aobut) {
//
}
return true;
});
popup.show();

Overflow menu is not showing in an Activity with a tab style navigation implemented with TabLayout

The overflow menu icon is not showing in my Activity with a tab style navigation layout. The tabs are implemented using a ViewPager, Fragments and a TabLayout.
The overflow menu is showing in my Activities which do not have tabs which makes me think the overflow menu not showing is something to do with my implementation of the tabs navigation.
Here is a basic model of my Activity:
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_layout);
initTabLayout();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_layout, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
return super.onPrepareOptionsMenu(menu);
}
public void initTabLayout(){
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setTabTextColors(Color.parseColor("#e3e8e7"), Color.parseColor("#7e7e7e"));
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setOffscreenPageLimit(4); //this stops the tabs from losing their data when you change tabs
//sets up adapter that contains the scrolling pageAdapter and the fragment which is displayed
viewPager.setAdapter(new ActivityTabAdapter(getSupportFragmentManager(),
MainActivity.this));
tabLayout.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
And here is my FragmentPagerAdapter implementation:
public class ActivityTabAdapter extends FragmentPagerAdapter {
#Override
public Parcelable saveState() {
return super.saveState();
}
final int PAGE_COUNT = 4;
private String tabTitles[] = new String[]{"tab1", "tab2", "tab3", "tab4"};
private Context context;
public ActivityTabAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position + 1);
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
//These are fragments which hold the layouts of the tabs
public static class PageFragment extends Fragment {
public static final String ARG_PAGE = "ARG_PAGE";
Context mContext;
View tab1rootView;
View tab2Rootview;
View tab3RootView;
View tab4RootView;
Tab1 tab1;
Tab2 tab2;
Tab3 tab3;
Tab4 tab4;
private int mPage;
public static PageFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
PageFragment fragment = new PageFragment();
fragment.setArguments(args);
return fragment;
}
MenuInflater mInflater;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
mInflater = inflater;
inflater.inflate(R.menu.menu_layout, menu);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
mInflater.inflate(R.menu.menu_layout, menu);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mContext = getActivity();
mPage = getArguments().getInt(ARG_PAGE);
Log.v("whichFrag", "" + getArguments().getInt(ARG_PAGE));
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
tab1rootView = inflater.inflate(R.layout.tab1_layout, container, false);
tab2Rootview = inflater.inflate(R.layout.tab2_layout, container, false);
tab3RootView = inflater.inflate(R.layout.tab3_layout, container, false);
tab4RootView = inflater.inflate(R.layout.tab4_layout, container, false);
int i = getArguments().getInt(ARG_PAGE);
if (getArguments().getInt(ARG_PAGE) == 1) { //if 1, then we inflate tab1rootView layout
tab1 = new Tab1(tab1rootView, getActivity());
tab1.initCardViews1();
return tab1rootView;
} else if (getArguments().getInt(ARG_PAGE) == 2) { //if 2, then we inflate tab2Rootview layout
tab2 = new Tab2(tab2Rootview, mContext);
return tab2Rootview;
} else if (getArguments().getInt(ARG_PAGE) == 3) { //if 3, then we inflate tab3RootView layout
tab3 = new Tab3(tab3RootView, mContext);
return tab3RootView;
} else { //if 4, then we inflate tab4RootView layout
tab4 = new Tab4(tab4RootView, mContext);
return tab4RootView;
}
}
}
}
Here is my xml menu:
<menu 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"
tools:context="com.example.heavymagikhq.profilepageofficial.profileEditorJava.Profile_info_editor">
<item android:id="#+id/action_settings" android:title="#string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
<item
android:id="#+id/action_settings2"
android:orderInCategory="100"
android:title="#string/action_settings"
app:showAsAction="never"
android:visible="true" />
<item
android:id="#+id/action_settings1"
android:orderInCategory="100"
android:title="#string/action_settings"
android:icon="#drawable/ic_action_menu"
app:showAsAction="never"
android:visible="true" />
</menu>
I have looked at other answers on stackoverflow but I couldn't find the answer.
I'll post more information if you need it.
Thanks in advance.
Okay, so I figured it out and the answer is simple. I didn't need to use setHasOptionsMenu(true); in any of the Fragments' lifecycle stages, and you must in my experience have app:showAsAction="never"as an xml attribute on your at least one of your xml menu items.
If you're extending AppCompatActivity in the Activity which implements the TabLayout and you're also using a Toolbar in that Activity then get a reference to your Toolbar and call this.setSupportActionBar(toolbar); while passing in your Toolbar as a parameter.
It should look like so:
Toolbar toolbar = (Toolbar) findViewById(R.id.editProfileToolbar);
this.setSupportActionBar(toolbar);
And call this in the onCreate() method of your Activity.
Try moving setHasOptionsMenu to Oncreate() method of the fragment and use it only once.Also don't inflate the menu twice.Inflate once in OncreateOptionsMenu() and change the visibility of the items in OnPrepareOptionsMenu() instead of inflating again.

Refreshing RecyclerView Between Two Tabs

I have two tabs in my app. So when I delete a list from the RecyclerView of one tab it should be added to the RecyclerView. I have deleted the list from the 1st tab and added it to the list of 2nd tab's recyclerview. But, the recyclerview doesnot take the change. When I go to next activity and come back to the tabs, then it shows the change.
In short I just need to update the data sent to the adapter.
I have already used
notifyDataSetChanged() and swapAdapter()
but did not work.
Do anyone know who to make it work ?
Thank you
!
Tab 1 Fragment :
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_active_patients, container, false);
activePatientsList = (RecyclerView) view.findViewById(R.id.active_patients_recyclerview);
activePatientsList.setLayoutManager(new LinearLayoutManager(getActivity()));
final ActivePatientRecyclerAdapter activePatientRecyclerAdapter = new ActivePatientRecyclerAdapter(getActivity()
,activePatientList);
activePatientRecyclerAdapter.setOptionsCLickedListener(new ActivePatientRecyclerAdapter.OptionsCLickedListener() {
#Override
public void popUpClicked(final View view, final int position) {
PopupMenu popupMenu = new PopupMenu(getActivity(), view);
MenuInflater menuInflater = popupMenu.getMenuInflater();
menuInflater.inflate(R.menu.menu_active_patients_additional_options,
popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
int id = menuItem.getItemId();
if (id == R.id.action_discharge) {
SQLiteDBUse db = new SQLiteDBUse(getActivity());
long result = db.updateName("4", in_patients_name[position]);
if (result > -1) {
Snackbar.make(view, in_patients_name[position] + " Removed", Snackbar.LENGTH_SHORT).show();
activePatientList.remove(position);
activePatientRecyclerAdapter.notifyItemRemoved(position);
}
return false;
}
return false;
}
;
});
popupMenu.show();
}
});
activePatientsList.setAdapter(activePatientRecyclerAdapter);
return view;
}
Tab 2 Fragment :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_out_patient, container, false);
outPatientList = (RecyclerView) view.findViewById(R.id.out_patients_recyclerview);
outPatientList.setLayoutManager(new LinearLayoutManager(getActivity()));
patientListRecyclerAdapter = new PatientListRecyclerAdapter(getActivity()
, patientList);
}
});
outPatientList.setAdapter(patientListRecyclerAdapter);
return view;
}
#Override
public void onResume() {
super.onResume();
patientListRecyclerAdapter.notifyDataSetChanged();
}

How to avoid fragment's list refreshing after Navigation Drawer opens?

I have list in my fragment and NavigationDrawer in MainActivity. From NavigationDrawer I'm calling that fragment. When I have scrolled a little bit and opened NavigationDrawer again, list refreshes and starts from the top. I guess the main reason is setHasOptionsMenu(true); because when I comment this line everything is okay, but my Search in ActionBar doesn't work.
When I have scrolled a little bit:
What it should look like:
What it's actually looks:
My fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.alllists, container, false);
View header = inflater.inflate(R.layout.list_header, null);
ImageView image = (ImageView) header.findViewById(R.id.small_icon);
navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_icons);
Bundle bundle = getArguments();
position = bundle.getInt("position");
location = bundle.getString("location");
image.setImageDrawable(navMenuIcons.getDrawable(position));
context = getActivity().getApplicationContext();
DatabaseHandler db = new DatabaseHandler(context);
items = db.getAllItems(location);
tmp_items = db.getAllItems(location);
listView = (ListView) rootView.findViewById(R.id.list);
adapter = new CustomListAdapter(context, items);
listView.addHeaderView(header, "", false);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
setHasOptionsMenu(true);
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchItem = menu.findItem(R.id.action_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
if (TextUtils.isEmpty(s)) {
adapter = new CustomListAdapter(context, tmp_items);
listView.setAdapter(adapter);
}
if (tmp_s.length() > s.length()) {
adapter.getFilter(tmp_items, true).filter(s);
} else {
adapter.getFilter(tmp_items, false).filter(s);
}
tmp_s = s;
return false;
}
});
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
mSearchView.setQuery("", false);
}
I have updated my newInstance method:
public static final AllLists newInstance(int position, String location) {
AllLists mainfrag = MainActivity.getMainFragment();
if (mainfrag == null || !mainfrag.getArguments().getString("location").equals(location)) {
AllLists all = new AllLists();
Bundle bdl = new Bundle(2);
bdl.putInt("position", position);
bdl.putString("location", location);
all.setArguments(bdl);
MainActivity.setMainFragment(all);
return all;
}
return mainfrag;
}
MainActivity:
public static AllLists mainFragment = null;
...
public static void setMainFragment(AllLists fragment) {
mainFragment = fragment;
}
public static AllLists getMainFragment() {
return mainFragment;
}
Just to be clear, I change my fragments like this:
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_container, AllLists.newInstance(position, location))
.commit();
The problem is that your Fragment View will get reset each time you return to it.
To not to loose state of your main fragment, you should do "new Fragment()" only once in your newIntance method. You can make a global variable, say 'mainFragment', storing once created new Fragment(), and then apply a check that if your global variable, i.e. 'mainFragment', is not null, then return mainFragment.
This should fix your problem. But on screen rotations, a new instance will still be created, leading to again taking you back to top of your list. For the rotation problem, see :
http://blog.sqisland.com/2014/06/navigationdrawer-creates-fragment-twice.html
from the docs,
Your fragments can contribute menu items to the activity's Options
Menu (and, consequently, the Action Bar) by implementing
onCreateOptionsMenu(). In order for this method to receive calls,
however, you must call setHasOptionsMenu() during onCreate(), to
indicate that the fragment would like to add items to the Options Menu
(otherwise, the fragment will not receive a call to
onCreateOptionsMenu()).
so, lets move move the setHasOptionsMenu(true); from your onCreateView(...) call to the onCreate(...) override in your fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}

Menu item shows up when Tab is changed

I'm using fragments and I have a menu item in one of my fragments. The fragment that uses the menu item is called when an item in the List View is clicked. When the fragment with the menu item is called, and then I change the tab, the menu item is still there. I want the menu item to only show in the one fragment only.
Here is the code for Tab 1
public class Tab2Fragment extends Fragment{
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.tab_fragment, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().setTitle("Tab 2");
initView();
}
private void initView() {
((TextView)getView().findViewById(R.id.tab_text)).setText("Tab 2");
Button button = (Button) getView().findViewById(R.id.tab_btn);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
replaceFragment();
}
});
}
private void replaceFragment() {
((BaseContainerFragment)getParentFragment()).replaceFragment(new Tab2AddOnFragment(), true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
and Here is the code for Tab 3 which has the List View
public class Tab3Fragment extends ListFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] values = new String[] { "Ang na Ang na", "Sulakihin", "Somaskidot", "Moko Moko"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
getActivity().setTitle("Tab 3");
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
switch(position){
case 0:
// Create new fragment and transaction
FragmentTransaction transaction = getFragmentManager().beginTransaction();
replaceFragment();
transaction.setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// Commit the transaction
transaction.commit();
break;
default:
}
}
private void replaceFragment() {
((BaseContainerFragment)getParentFragment()).replaceFragment(new FragmentInListView(), true);
}
}
and here is the code for the fragment with the menu item
public class FragmentInListView extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getActivity().setTitle("Fragment Called in Tab 3(List View)");
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.tab_fragment,
container, false);
TextView tv= (TextView) view.findViewById(R.id.tab_text);
tv.setText("Fragment in List View");
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.travel_tips_expanded, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
and here is the code for the menu of the fragment with a menu item
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:showAsAction="never"
android:title="#string/action_settings"/>
<item
android:id="#+id/favorite"
android:showAsAction="always"
android:title="favorite"/>
Here is an image of the Fragment called when an item in the List View is clicked. And it contains the menu item.
http://s904.photobucket.com/user/fookywooky/media/tab4_zps30944a6e.png.html
And here is an image of the Fragment called when "Tab 2" is selected. As you can see, the menu item is still there but i don't want it to be there. Also, this is the case even if you click Tab 1 and Tab 3. The menu item is still there.
http://s904.photobucket.com/user/fookywooky/media/tab5_zps285c8314.png.html
Please help. Thanks in advance.
In order to accurately determine when to show the Fragment menu, your Activity needs some indication as to which Fragment is visible and current. You can accomplish this with the setMenuVisibility() and setUserVisibleHint() methods. In your OnTabChanged() callback, set the menu visibility and user visible hint to false in the previously selected Fragment and true in the currently selected Fragment.

Categories

Resources