Android Spinner onItemSelected not being called inside Fragment - android

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.

Related

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 do I link child fragments to the MainActivity?

I'm building a very simple NBA App since I'm new to this.
The MainActivity has a ListView with two items. Western teams and Eastern Teams. When the user taps on an item, it shows the teams of that conference. These teams are stored as array items in the strings.xml file.
Here is the MainActivity:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#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);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
ArrayAdapter<String> mConferenceAdapter;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String[] conferenceArray = {
"Western Conference",
"Eastern Conference"
};
List<String> conferenceList = new ArrayList<String>(Arrays.asList(conferenceArray));
mConferenceAdapter =
new ArrayAdapter<String>(
getActivity(), // The current context (this activity)
R.layout.list_item_conferences, // The name of the layout ID.
R.id.list_item_conference_textview, // The ID of the textview to populate.
conferenceList);
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Get a reference to the ListView, and attach this adapter to it.
ListView listView = (ListView) rootView.findViewById(R.id.listview_conferences);
listView.setAdapter(mConferenceAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
String forecast = mConferenceAdapter.getItem(position);
Intent intent = new Intent(getActivity(), WesternConference.class)
.putExtra(Intent.EXTRA_TEXT, forecast);
startActivity(intent);
}
});
return rootView;
}
}
The issue I have now is that no matter which selection I choose it only shows the Western teams.
This is a snippet from WestConference.java:
public static class PlaceholderFragment extends Fragment {
ArrayAdapter<String> mConferenceAdapter;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Create some dummy data for the ListView. Here's a sample weekly forecast
String[] teams = getResources().getStringArray(R.array.westTeams);
List<String> conferenceList = new ArrayList<String>(Arrays.asList(teams));
// Now that we have some dummy forecast data, create an ArrayAdapter.
// The ArrayAdapter will take data from a source (like our dummy forecast) and
// use it to populate the ListView it's attached to.
mConferenceAdapter =
new ArrayAdapter<String>(
getActivity(), // The current context (this activity)
R.layout.list_item_conferences, // The name of the layout ID.
R.id.list_item_conference_textview, // The ID of the textview to populate.
conferenceList);
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Get a reference to the ListView, and attach this adapter to it.
ListView listView = (ListView) rootView.findViewById(R.id.listview_conferences);
listView.setAdapter(mConferenceAdapter);
return rootView;
}
}
How can I make it to where if I click West, it loads those teams, and if I click East, it loads the eastern teams?

Refresh DrawerLayout from a Fragment

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!

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);
}

Android: access activity spinner from fragment

I have a main activity which consists of spinner + 3 fragments (tabs). I want to access spinner value from fragment. So I wrote this code into onActivityCreated inside my fragment:
final Spinner spinner = (Spinner) getView().findViewById(R.id.spinnerOblasti);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
/*TextView[] vystrahy = new TextView[1];
vystrahy[0] = (TextView) getView().findViewById(R.id.txtVystrahy);
(new htmlParser(vystrahy, 0) ).execute(new Integer[]{spinner.getSelectedItemPosition()});*/
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
but when I run my application spinner throws nullpointerexception. Any ideas on how to access it from fragment?
Here is my onCreateView which I believe is causing problem but I dont know how to fix it:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tab1, container, false);
return rootView;
}
Thanks in forward
Doesn't work like that, what do you mean for spinner value? If you want to access to the spinner object you have to setup an interface which will be implemented by your activity and then in onActivityCreated you can call the method of that interface to do something. For example:
public class MyClass implements MyInterface {
public interface MyInterface {
void doSomethingWithSpinner();
}
public void doSomethingWithSpinner() {
mySpinner.setVisibility(View.VISIBLE);
}
}
And your onActivityCreated:
if(getActivity() instanceof MyInterface) {
((MyInterface)getActivity()).doSomethingWithSpinner();
}

Categories

Resources