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.
Related
I have an activity which calls several fragments. In one of those fragments I am trying to create a dialog spinner programmatically and add it to the menu option (in toolbar). I manage to make it work (atleast the view is showing), but the onItemSelected it is not getting called.
My code:
public class NewsFeed extends Fragment {
private static final String TAG = "tag";
private String tag;
private ArrayAdapter<New> newsadapter;
private ArrayAdapter<Tag> tagsadapter;
private Spinner spinner;
public NewsFeed() {
setHasOptionsMenu(true);
}
public static NewsFeed newInstance(String tag) {
NewsFeed fragment = new NewsFeed();
Bundle args = new Bundle();
args.putString(TAG, tag);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
tag = getArguments().getString(TAG);
}
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getActivity().setTitle(tag);
NavigationView activitynav = (NavigationView) getActivity().findViewById(R.id.nav_view);
BottomNavigationView activitybuttomnav = (BottomNavigationView) getActivity().findViewById(R.id.navigation);
activitynav.setCheckedItem(R.id.nav_news);
activitybuttomnav.getMenu().getItem(1).setChecked(true);
View v = inflater.inflate(R.layout.fragment_news_feed, container, false);
//Spinner related code
tagsadapter = new TagsAdapter(getActivity(), android.R.layout.simple_spinner_item, (ArrayList<Tag>) ApplicationData.tags);
spinner = new Spinner(getActivity(), Spinner.MODE_DIALOG);
tagsadapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setPrompt("Filtrar por categoria:");
spinner.setAdapter(tagsadapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
newsadapter = new NewsAdapter(getActivity().getApplicationContext(), 0, (ArrayList<New>) ApplicationData.news);
ListView listview = (ListView) v.findViewById(R.id.listview);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
NewsDisplay nd = NewsDisplay.newInstance(tag, ApplicationData.news.get(position).getNewsUrl());
ft.addToBackStack(null);
ft.replace(R.id.fragmentcontent, nd).commit();
}
});
listview.setAdapter(newsadapter);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.filter_category) {
//For showing the spinner
spinner.performClick();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Already tried:
To make NewsFeed implementing OnItemSelectedListener.
To create the OnItemSelectedListener object inside SetOnItemSelectedListener.
Could you give me some help? It might have to do with this being a fragment and the toolbar is in the activity.
Spinner that was created dynamically (private val popupSpinner: Spinner by lazy { Spinner(this, Spinner.MODE_DIALOG) }), needs to have an assigned parent view. If it does not have it, the OnItemSelected is never called for some reason.
I wrote this hack to alleviate the problem. Added to parent view and hid it. Be sure not to run this in onResume() method and similar ones.
findViewById<ViewGroup>(android.R.id.content).addView(popupSpinner)
popupSpinner.visibility = View.INVISIBLE
PS. Some people might think that this question does not have an answer. But in the comments the author himself found a solution.
I'm using this library in a fragment, but when I run the app the SwipeMenuListView is not showing its contents, here on stack I found some guys using the listview inside the onCreateView method, I tried that but it didn't work
public class AutorizadasFragment extends Fragment {
private SwipeMenuListView listView;
private CustomArrayAdapter adapter;
private List<String> data;
public AutorizadasFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_autorizadas, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
data = new ArrayList<String>();
data.add("Teste 1");
data.add("Teste 2");
data.add("Teste 3");
data.add("Teste 4");
data.add("Teste 5");
listView = (SwipeMenuListView) getActivity().findViewById(R.id.list);
adapter = new CustomArrayAdapter(getActivity(), data);
listView.setAdapter(adapter);
SwipeMenuCreator creator = new SwipeMenuCreator() {
#Override
public void create(SwipeMenu menu) {
// create "open" item
SwipeMenuItem openItem = new SwipeMenuItem(
getActivity());
// set item background
openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
0xCE)));
// set item width
openItem.setWidth(90);
// set item title
openItem.setTitle("Open");
// set item title fontsize
openItem.setTitleSize(18);
// set item title font color
openItem.setTitleColor(Color.BLACK);
// add to menu
menu.addMenuItem(openItem);
// create "delete" item
SwipeMenuItem deleteItem = new SwipeMenuItem(
getActivity());
// set item background
deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
0x3F, 0x25)));
// set item width
deleteItem.setWidth(90);
// set a icon
deleteItem.setIcon(R.drawable.ic_exit);
// add to menu
menu.addMenuItem(deleteItem);
}
};
listView.setMenuCreator(creator);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Auto-generated method stub
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main, menu);
}
}
XML:
<LinearLayout
style="#style/FormRegister"
android:orientation="vertical"
android:weightSum="1"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.baoyz.swipemenulistview.SwipeMenuListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
</LinearLayout>
You can hold a reference to your root view by adding a private attribute
e.g.
private View rootView = null;
and change following line in onCreateView:
View rootView = inflater.inflate(R.layout.fragment_autorizadas, container, false);
to
rootView = inflater.inflate(R.layout.fragment_autorizadas, container, false);
Then you do not need to use "getActivity().findViewById(R.id.list);"
(it would become "rootView.findViewById(R.id.list);")
I am proposing this because i am not sure the view created in onCreateView is actually added to your activities root view when onActivityCreated() is called.
An alternative would be overridding onViewCreated. The view returned by onCreateView is passed to onViewCreated
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
listView = (SwipeMenuListView) view.findViewById(R.id.list);
}
I have 3 classes, as follow:
Drawer.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.action_center);
CustomAdapter adapter = new CustomAdapter(this, savedInstanceState);
mDrawerList.setAdapter(adapter);
}
Where the drawer is implemented. I have read that I should implement
adapter.notifyDataSetChanged();
Inside of
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
mMenuAdapter.notifyDataSetChanged();
menu.findItem(R.id.action_websearch).setVisible(true);
return super.onPrepareOptionsMenu(menu);
}
CustomAdapter.java:
Where the custom adapter is implemented.
PlanetFragment.java:
public class PlanetFragment extends Fragment {
ListView lv;
public PlanetFragment() {
// Empty constructor required for fragment subclasses
}
//#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
final Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_planet, container, false);
lv = (ListView) rootView.findViewById(R.id.list);
lv.setAdapter(SecondCustomAdapter...);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
/***I want to refresh the drawer when an item on the fragment is
clicked, but I just can't figure out a way to do it...***/
}
}
}
Can you help me here please?
Thank you!
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);
}
I have a fragment which has a menu with one item. The problem is on every screen orientation change this item is doubled. So there is 2 (the same) items after first screen change, 3 items after second change and so on...
public class ManageLinksFragment extends Fragment {
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;
DBHttpLinks db;
long itemPosition;
SimpleCursorAdapter adapter;
ListView lv;
Listener mListener;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setRetainInstance(true);
setHasOptionsMenu(true);
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.chooseonelinkfragment, container, false);
lv = (ListView) v.findViewById(R.id.listView1);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_links, menu);
super.onCreateOptionsMenu(menu,inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addlinks:
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
// AddNewRecordFragment is a class name!
AddHttpLinksFragment fragment2 = new AddHttpLinksFragment();
fragmentTransaction.replace(R.id.fragment_left, fragment2, "addlinksF");
fragmentTransaction.addToBackStack("chooselinksF");
fragmentTransaction.commit();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.context_menu_manage_links, menu);
}
}
Try moving :
setHasOptionsMenu(true);
setRetainInstance(true);
to your fragment onCreate,
also, make sure you are not adding your fragment in Activity.onCreate, even if it already exists.