How do I link child fragments to the MainActivity? - android

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?

Related

Android Spinner onItemSelected not being called inside Fragment

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.

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!

Android Fragments Extra Code

I faced up a problem with my Android application. I'm a beginner and I tend to learn on my own. So I am trying to make a MediaPlayer and in order to do that, I need to use Fragments. The problem is not the Fragment itself but that I need to add some extra buttons with onClickListeners by the side of the MediaPlayer and my application is crashing because the fragment_main.xml file has the layout parameters but i cannot use the OnClickListener function in the Fragment(I get an error at findViewById(cannot make static reference to non-static method). Please help me.
public class MainActivity extends Activity {
Button blade;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
/* blade = (Button)findViewById(R.id.fantab);
blade.setOnClickListener(new OnClickListener(){
#Override
//On click function
public void onClick(View view) {
//Create the intent to start another activity
Intent vent = new Intent(MainActivity.this, Ventscreen.class);
startActivity(vent);
finish();
}
});
*/
}
}
#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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends ListFragment {
private static final String[] FROM = { MediaStore.Audio.Media.TITLE };
private static final int[] TO = { android.R.id.text1 };
private CursorAdapter mAdapter;
Button blade;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
return view;
blade = (Button)findViewById(R.id.fantab);
blade.setOnClickListener(new OnClickListener(){
#Override
//On click function
public void onClick(View view) {
//Create the intent to start another activity
Intent vent = new Intent(MainActivity.this, Ventscreen.class);
startActivity(vent);
finish();
}
});
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Context context = getActivity();
int layout = android.R.layout.simple_list_item_1;
Cursor cursor = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,
null,
null,
MediaStore.Audio.Media.TITLE + " ASC");
int flags = 0;
mAdapter = new SimpleCursorAdapter(context, layout, cursor, FROM, TO, flags);
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setListAdapter(mAdapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
mAdapter.notifyDataSetChanged();
}
}
}
It is not just one button, the code above is just for example, there should be five buttons in total.
Thanks.
blade = (Button)findViewById(R.id.fantab);
You're trying to call the findViewById(int) method of the outer Activity. This is not possible, sincer your inner Fragment class is static. What you want to do is call findViewById(int) on the Fragment View:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
blade = (Button) view.findViewById(R.id.fantab);
blade.setOnClickListener(new OnClickListener(){
#Override
//On click function
public void onClick(View view) {
//Create the intent to start another activity
Intent vent = new Intent(getActivity(), Ventscreen.class);
getActivity().startActivity(vent);
getActivity().finish();
}
});
return view;
}
Also, note the placement of the return view; statement.

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

Maintaining proper Activity scope with Android

I am having troubles organizing my Java classes so that the scope of everything I need to access in any given object is available.
For example, I have a MainActivity that has a ListView that I want to attach an onFling gesture listener to in order to remove ListView items when they are swiped off the screen. However, I cannot figure out how to set up the listener so that the Listener has access to my ArrayAdapter and ListView as well as is accessible by the MainActivity for instantiating it onCreate().
What is the correct way to set this up?
public class MainActivity extends FragmentActivity implements onSelectionMade {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
private static View current;
private GestureDetectorCompat mDetector;
#Override
public void doChange(int val){
if(val == onSelectionMade.OK){
// Add contact
current.setBackgroundColor(Color.rgb(60, 242, 102));
}else if(val == onSelectionMade.CANCEL){
current.setBackgroundColor(Color.rgb(237, 47, 47));
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// THIS IS THE LINE WITH THE ERROR BECAUSE MyGestureListener IS NOT IN THE SCOPE OF THE MAIN ACTIVITY
this.mDetector = new GestureDetectorCompat(this, new MyGestureListener());
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();
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 {
ContactAdapter adapter;
ListView view;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
Contact contactList[] = new Contact[]
{
new Contact("Matt", "Hintzke", "2062259311", "matt.hintzke#email.wsu.edu"),
new Contact("John", "Smith", "2062236457", "john#email.com"),
new Contact("Bob", "Harrison", "2064318756", "bob#email.com"),
new Contact("Colleen", "Arnold", "2065553696", "ween#email.com"),
new Contact("Harry", "Larkin", "3608785423", "poop#gmail.com")
};
adapter = new ContactAdapter(getActivity(), R.layout.contact_item , contactList);
view = (ListView) rootView.findViewById(R.id.listView);
view.setAdapter(adapter);
view.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> parentAdapter, View view, int position, long id){
Contact item = (Contact) parentAdapter.getItemAtPosition(position);
current = view;
//adapter.remove(adapter.getItem(position));
DialogFragment dialog = AddContactDialog.newInstance(item);
dialog.show(getActivity().getSupportFragmentManager(), "Add Contact Dialog");
//Toast.makeText(getActivity().getApplicationContext(), item.first, Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
private static final String DEBUG_TAG = "Gestures";
#Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
if(event2.getX() - event1.getX() > 10){
int id = view.pointToPosition((int) event1.getX(), (int) event1.getY());
adapter.remove(adapter.getItem(id));
}
return true;
}
}
}
}
The "correct" way would be, I think, to place object declarations in the "smallest" scope that needs them.
For example, in this case, both the ListView and its GestureDetector should be inside the Fragment. The Activity should not be concerned about them (e.g. fragments should be replaceable -- if you replaced then Fragment with another one that doesn't have a ListView, why would you need the GestureDetector)?
The same goes for the implementor of the OnSelectionMade interface, &c.
Also, the fragment doesn't need to be an inner class of the Activity. I'm not sure why the IDE creates them like this, it leads to confusion :/

Categories

Resources