I have an application which has a main activity and several fragments which are navigated to via a navigation drawer.
I use two map fragments in my app, this seems to cause an issue if i go from fragment map A and then back to fragment map B . In frgamnet b i lose control of them map is generally just shows a snapshot of where fragmnet map A last was.
this seem to be a known issue see.
google maps api bug report with issue
My solution as sugested on abouve fourm is to minimive map A before loading map B this causes the issue not to happen as it will not take up the screen space.
public void hideStupidMaps() {
mMapView.getLayoutParams().height = 1;
mMapView.getLayoutParams().width = 1;
mMapView.invalidate();
mMapView.requestLayout();
}
The above method is in my Gmap fragment class. i want to call it from myMain Activity class. in the navagation drawer code. My question is how do i call a frgments method from the main activity. especally when altering that fragment view. i need to inflate the view and it to the above method?
You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. A fragment must always be embedded in an activity and the fragment's lifecycle is directly affected by the host activity's lifecycle.
To return a layout from onCreateView(), you can inflate it from a layout resource defined in XML. To help you do so, onCreateView() provides a LayoutInflater object.
public static class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
Here's how you can replace one fragment with another, and preserve the previous state in the back stack:
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Related
I have added a fragment in another fragment
in this way
Secondfragment secondFragment=new SecondFragment(parmater);
fragmentManager.beginTransaction()
.replace(fragmentContainerView.getId(),
secondFragment, null)
.setReorderingAllowed(true)
.commit();
the firstFragment is containing the fragmentContainerView and it's inside a ViewPager2 with other fragments
after changing the page and return to it again the app is crashes and give me the error
Unable to instantiate fragment , as I mentioned this because the firstFragment have a parameter in constructor .
I use this way in multiple places .
after changing the page the first fragment is been in the onPause state and after I go to the first fragment again its recreate the views and the proplen happen here , it cannot instantiate the second fragment.
I want a way to let it instantiate it again ,or any better idea and thank you in advance .
Suppose I have a navigation drawer which contains three menu item i.e cat1, cat2, and cat3. Whenever a user clicks on this it will open a Fragment which will fetch the data from the web server and parse the JSON data and show into recycler view.
Now my question is.
Do I need to create separate fragments for each menu item of navigation drawer i.e cat1, cat2 and cat3? Or I can use one fragment and pass an argument like this
http://example.com?cat=1 to that fragment and load the recycler view item?
So which procedure should I follow to achieve this goal, separate fragment for each menu item or a single fragment? Thanks.
If you want to fetch data every time you click on a category, it's better to have one fragment and make it call the API. But if you use three fragments, it reduces number of API calls in addition to faster switching between categories. However, there is a trade-off between them. Also in second case, you should care about updating contents that is fetched from API every time.
You should definitely use a single fragment and avoid some boilerplate code. Here is a how you should do it:
public class CategoryFragment extends Fragment {
public static CategoryFragment newInstance(int categoryId) {
CategoryFragment fragment = new CategoryFragment();
Bundle extras = new Bundle();
extras.putInt("categoryId", categoryId);
fragment.setArguments(extras);
return fragment;
}
...
// Determine which category you're on
private int getCategoryId() {
return getArguments().getIntExtra("categoryId", 1);
}
}
And to instantiate your fragment you can simply use:
// Construct a cat2 fragment
CategoryFragment categoryFragment = CategoryFragment.newInstance(2);
You should use only one fragment in this case this is how you can reuse design and code by using just one fragment for each category cat1, cat2, cat3.
You can pass category id to the fragment via a bundle. check this tutorial
Here is my scenario: In my application i have a Main activity, two fragments and a service that runs in background. I attach the fragments to my main activity using this piece of code:
Fragment f1;
f1=new loginfragment();
FragmentTransaction ft=getFragmentManager().beginTransaction();
ft.add(R.id.frame,f1);
ft.commit();
Which is working fine. one of these fragments contains a listview which is attached to an adapter.(i have verified that adapter is correctly attached to the listview and entries can be added to listview without any problems.
In order to be able to inflate a layout inside the listview adapter(which extends BaseAdapter) i created a constructor to feed Context to it.
background service checks a page periodically and sends the results to one of these fragments using an interface that the fragment implements(sending broadcasts didn't work for me).interface is defined like this:
interface resultInterface{
void receive(String s,Context con);
}
fragment implements the interface like this:
#Override
public void receive(String s,Context con){
String elements[]=s.split("<br>");
if(elements.length>1) {
if(elements[0].equals("REQUEST")) {
init_notification("REQUEST",detect(elements[1],elements[2]));// a function that shows a notification
item i = new item(elements[1], elements[2]);
orders.add(i);
adapter = new listview_adapter(orders,c);
list.setAdapter(adapter);}
}
}
orders is an Arraylist and c is the context that is being passed to the listview adapter. service calls this interface method like this:
resultInterface resultinterface=new servefragment();
resulstinterface.receive(s,this);
upon receiving data (which results in calling the interface method) the fragment method is supposed to split the data and add entries to the listview.(i have verified that data is being correctly passed to the interface method.
BUT, the view that is being shown as listview entries is not correct( look corrupted somehow). Here is how it is supposed to look(using dummy data):Like this but here is how they are actually added(1 item is received from server which is correct but the layout is not): Like this
If you need more information just comment and i'll add them
My guess is that the Context object your service is passing to you has a different theme than you're expecting. This can cause text colors, button colors, etc to all change.
In order to be able to inflate a layout inside the listview adapter(which extends BaseAdapter) i created a constructor to feed Context to it.
Unless you need the Context instance somewhere other than inside getView(), you don't have to pass a Context via a constructor. Here's the full signature of the getView() method:
public View getView(int position, View convertView, ViewGroup parent)
The parent argument is guaranteed to be non-null, and all View instances have a getContext() method, so you can always retrieve a Context by writing parent.getContext(). Additionally, this will be your Activity (as opposed to something like your Application), which has the added benefit of having the correct theme.
So delete all of the code that passes the Context into your adapter and just use parent.getContext() instead, and I bet the problem goes away.
I've been doing it like this for a while, is it the right way?
Activity:
public void toSettings(){
Fragment_Settings frag = new Fragment_Settings();
fm.beginTransaction()
.replace(R.id.mainContainer, frag)
.addToBackStack(null)
.commit();
}
In some listener in another fragment:
((Activity_Main)getActivity()).toSettings();
You don't need .addToBackStack(null) Just delete that piece and your fragment will not be added to backstack. I would also suggest adding a TAG to the replace method just in case you want to retrieve the fragment later. Something like this .replace(R.id.mainContainer, frag, TAG).
It seems correct but i have some suggestions.
If you wanna back previous fragment from Fragment_Settings use add method instead of replace and addToBackStack("tag of Fragment_Settings") instead of addToBackStack(null).
newInstance pattern is more preferred than Fragment_Settings frag = new Fragment_Settings();. You can see some explanations about that.
http://www.androiddesignpatterns.com/2012/05/using-newinstance-to-instantiate.html
Creating a Fragment: constructor vs newInstance()
To avoid code repetition when navigating between fragments you can use a manager class provides organizing add, replace or pop processes.
Here is my navigation manager class.
So currently I have a application with different activities, and I use buttons to navigate between activities. I later decided that I should add the navigation drawer and use fragments instead. So one of my fragments has a bunch of fields that the user fills out that I need to pass onto the next fragment. So my question is, Do I keep all the work in activities and call the activity from the fragment? Or do I just include all he java in my activity in the java for the fragment? For the most part I am taking the fields from the first fragment, and I'd like to pass the values to the next fragment so it can handle some calculations.
final EditText FinalPriceText = (EditText) v.findViewById(R.id.editTextPrice);
final EditText TradeInPriceText = (EditText) v.findViewById(R.id.editTextTrade);
i.putExtra("FinalAutoPrice", FinalAutoPriceText.getText().toString());
i.putExtra("TradeInPrice", TradeInPriceText.getText().toString());
startActivity(i);
As far as calculations go, if you are going to use them a lot and they have nothing to do with the activity or android lifecycle I would separate them out into a different class and then you can call them from anywhere.
If they do rely on the activity you could still separate them out but pass a reference to the activity when doing your calculations. You can get the parent activity by calling this.getActivity() from any fragment
You can cast this.getActivity() to whatever the parent activity is and you can call the methods from that object as well. This works fine but your fragment will only work with the activity you specify and it can get sloppy if you are not careful.
Otherwise put them in the fragment where you need them. I would consider this least recommended if you need to use calculations anywhere else in the app. Duplicate code is just asking for bugs in the future.
As far as passing data, create a static instance method in fragment2 and pass it what you need there.
For example
public Fragment2 extends Fragment {
public static fragment2 newInstance(MyData myDataIPass) {
Fragment2 fragment = new Fragment2();
Bundle args = new Bundle();
args.putInt("someInt", myDataIPass.someInt);
fragment.setArguments(args);
return fragment;
}
}
Call this new instance method when creating your fragment transaction like this
FragmentManager fm = getActivity().getFragmentManager();
fm.beginTransaction()
.replace(R.id.container, Fragment2.newInstance(MyData myDataIPass))
.commit();
Well, you have mainly two options here:
use Intent.putExtra() with fragments. Just like Activities, you
can use this method with Fragments as well. See the following links
for the implementation in Fragments
this
this
The other option is to use SharedPreferences and store data as key value pairs from one fragment, and can be accessed from any other activity/fragments. See this nice tutorial to understand better!
You have a special callback in Fragment to get Activity.
It is called:
#Override
public void onAttach(Context context) {
super.onAttach(context);
YourActivity activity = (YourActivity) context;
}