Im having a issue I dont know how to resolve.
I have a fragment with a editText and a button.
The button launches a fragment map like this:
public void onClick(View view) {
//Fragment fragment = null;
switch (view.getId()) {
case R.id.SearchButton:
Home activity = (Home) getActivity();
if(activity != null)activity.openMapFragment();
break;
}
and the function openMapFragment():
public void openMapFragment(){
Fragment fragment = new gMapFragment();
replaceFragment(fragment);
}
How would i do to send the text inserted on editText field as a address to look for on map fragment?
You should use bundle to pass data to a fragment :
public void openMapFragment(String args){
Fragment fragment = new gMapFragment();
Bundle bundle = new Bundle();
bundle.putString("foo", args);
fragment.setArguments(bundle);
replaceFragment(fragment);
}
And to retrieve data :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//...
String foo = getArguments() != null ? getArguments().getString("foo") : "";
//...
}
Related
Lately i've been stuck! I have one Activity (not my MainActivity, I mean, it is not where I created this Fragment), and I need to pass some data. I've already tried to pass using Bundle, using getter, but the same issue appears: "Attempt to invoke virtual method {...} on a null object." at the line where I call the Bundle in the Fragment. I am new at this, so I'm sorry if this is a simple question and I didn't understand. Below the relevant parts of my code:
On Activity (not the main activity):
public void save(){
myGoal = spinnerGoals.getSelectedItem().toString();
Bundle bundle = new Bundle();
bundle.putString("goal", myGoal);
GoalFragment goalFragment = new GoalFragment();
goalFragment.setArguments(bundle);
}
On Fragment (where I want to put this 'goal')
private TextView goal;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate( R.layout.fragment_goal, container, false);
goal = view.findViewById(R.id.myGoalText);
Bundle bundle = getArguments();
if (bundle != null) {
final String myGoal = bundle.getString("goal");
goal.setText(myGoal);
}
return view;
}
On MainActivity (where I created the Fragments):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment() )
.commit();
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.nav_home:
selectedFragment = new HomeFragment();
break;
case R.id.nav_goal:
selectedFragment = new GoalFragment();
break;
case R.id.nav_info:
selectedFragment = new InfoFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, selectedFragment)
.commit();
return true;
}
};
Please, I've lost much time trying to solve this by myself hahaha. If anyone can help me, i'd appreciate that!
Create a method in Fragment which you want to receive data, then invoke the method in Activity.
Write this code in Activity :
Bundle bundle = new Bundle();
bundle.putString("goal", myGoal);
fragmentObj.sendData(bundle);
write code in Fragment:
public void sendData(Bundle bundle){
String myGoal = bundle.getString("goal");
}
If the Activity(not main activity) was created from your fragment, you could use
startActivityForResult()
method to receive data after the activity is ended, read about it more here
If that is not the case, you need to persist (in storage) the data using Preferences or Room Database
This is the answer that I got from other topic and applied it to my codes:
From Activity you send data with intent as:
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
and in Fragment onCreateView method:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
return inflater.inflate(R.layout.fragment, container, false);
}
These are the codes that I applied, it is not working somehow. The fragment is already opened at the start.
public void onInfoWindowClick(Marker marker) {
if (tag.equals("Click to show all routes in this point")) {
Bundle bundle = new Bundle();
bundle.putString("route1", "Divisoria - San Juan");
// set Fragmentclass Arguments
hideShowFragment fragobj = new hideShowFragment();
fragobj.setArguments(bundle);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
Fragment intersectionFragment = manager.findFragmentById(R.id.fragmentContainer2);
ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
ft.add(R.id.fragmentContainer2, fragobj);
ft.show(intersectionFragment);
ft.commit();
}
}
The codes in my onCreateView method:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_hide_show, container, false);
if (!routes.equals(none)) {
routes = getArguments().getString("route1");
} else {
routes = "Food";
}
return view;
}
What I want to happen is that the fragment will always update to what marker Tag that I click on the map. In other words, pass the string to the fragment (that is opened) and update it.
I do not want to use startActivityForResult because I can't move around the map if I don't use fragments. Is there a way to send result from activity to fragment that is already opened and running? If none, then how can I make the fragment not running from the start (using supportFragmentManager)? I only know is to hide it
If you have running Fragment and want to pass some data to it, you should create some way to communicate. For that purposes, you can use Observer pattern.
First of all create interface inside Activity if you want to pass data to Fragment:
public interface OnInfoClickedListener {
void onInfoClicked(String info);
}
Implement this interface inside Fragment:
#Override
public void onInfoClicked(String info) {
infoTextView.setText(info);
}
Now, inside your Activity, create variable to store this interface implementation:
private OnInfoClickedListener listener;
And when instantiating Fragment, save instance of it to variable:
InfoFragment fragment = InfoFragment.newInstance();
listener = fragment;
And when needed just provide data through this interface:
listener.onInfoClicked("Info - " + UUID.randomUUID());
I am new to android and I am trying to call my MapFragment from adapter after on click using intent below is my code
Below is adapter code:
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
final BusInfo info = getItem(position);
View view = LayoutInflater.from(context).inflate(R.layout.bus_only_list,null);
TextView busname;
busname = (TextView) view.findViewById(R.id.busname);
busname.setText(info.name);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pref = context.getSharedPreferences("busInfo",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString("bus_name",info.name);
editor.commit();
Intent intent = new Intent(context, MapsFragment.class);
intent.putExtra("name",info.name);
context.startActivity(intent);>
}
});
return view;
}
I want to pass to mapfragment using intent but it redirect to MainActivity instead of MapFragment. How can I stop transferring to MainActivity?
Thank you.
A common pattern to passing a value to a Fragment is using newInstance method. In this method you can set Argument to fragment as a means to send the value.
First, create the newInstance method:
public class YourFragment extends Fragment {
...
// Creates a new fragment with bus_name
public static YourFragment newInstance(String busName) {
YourFragment yourFragment = new YourFragment();
Bundle args = new Bundle();
args.putString("bus_name", busName);
yourFragment.setArguments(args);
return yourFragment;
}
...
}
Then you can get the value in onCreate:
public class YourFragment extends Fragment {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the value from arguments
String busName = getArguments().getString("bus_name", "");
}
...
}
You can set the value to the Fragment from your activity with:
FragmentTransaction fragTransaction = getSupportFragmentManager().beginTransaction();
YourFragment yourFragment = YourFragment.newInstance("bus_name_value");
fragTransaction.replace(R.id.fragment_place_holder, yourFragment);
fragTransaction.commit();
You can use the above codes to send the value in Fragment initialization.
If you want to set the value to the already instantiated fragment, you can create a method then invoke the method to set the value:
public class YourFragment extends Fragment {
...
public setBusName(String busName) {
// set the bus name to your fragment.
}
...
}
Now, In the activity, you can invoke it with:
// R.id.yourFragment is the id of fragment in xml
YourFragment yourFragment = (YourFragment) getSupportFragmentManager()
.findFragmentById(R.id.yourFragment);
yourFragment.setBusName("bus_name_value");
You cannot pass an intent to a Fragment. Try using a Bundle instead.
Bundle bundle = new Bundle();
bundle.putString("name", info.name);
mapFragment.setArguments(bundle)
In your Fragment (MapsFragment) get the Bundle like this:
Bundle bundle = this.getArguments();
if(bundle != null){
String infoName = bundle.getString("name");
}
As guys mentioned before:
1. Use callback or just casting on your context (your activity must handle changing fragments itself).
2. To change fragments use activity's FragmentManager - intent is used to start another activity.
Fragments Documentation
I have see this question asked here more than one time but I can't figure it out how to solve for my case.
I have an app that the user does this:
1 - Open the navigationDrawer and selects one option (a fragment is created) (I'm here selecting the second option);
public void selectItem(int position) {
Fragment fragment = null;
switch (position) {
case FRAGMENT_OPTION1:
...
break;
case FRAGMENT_OPTION2:
fragment = ControlPanelFragment.newInstance();
break;
...
case FRAGMENT_OPTIONN:
...
return;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_container, fragment).commitAllowingStateLoss();
}
}
2 - The selected option (ControlPanelFragment) gets loaded:
2.1 - Control panel has tabs and an iconpager. For each pager page and for each tab a new fragment is created. I have 3 tabs and 3 pages so 9 fragments are created;
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
currentControlPanelOption = savedInstanceState.getInt("currentControlPanelOption", currentControlPanelOption);
currentControlPanelTab = savedInstanceState.getInt("currentControlPanelTab", currentControlPanelTab);
}
setControlPanelTabs();
setIconPager();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentControlPanelOption", pager.getCurrentItem());
outState.putInt("currentControlPanelTab", mTabHost.getCurrentTab());
}
3 - In the setIconPager(); I have this code:
pager = (ViewPager) view.findViewById(R.id.pager);
cPanelPagerAdapter = new ControlPanelPagerAdapter(getChildFragmentManager());
pager.setOffscreenPageLimit(2);
pager.setAdapter(cPanelPagerAdapter);
where ControlPanelPagerAdapter has this code:
public Fragment getItem(int index) {
Fragment fragment;
switch (index) {
case 1:
fragment = FragmentA.newInstance();
break;
case 2:
fragment = FragmentB.newInstance();
break;
case 3:
fragment = FragmentC.newInstance();
break;
default:
fragment = null;
break;
}
...
return fragment;
}
4 - FragmentA, FragmentB and FragmentC have almost the same code:
public static FragmentA newInstance() {
return new FragmentA();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_placeholder, container, false);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState == null) {
fragmentA_Data = new FragmentADetail[3];
createTabInstance(0);
} else {
fragmentA_Data = (FragmentADetail[]) savedInstanceState.getSerializable("Data");
return;
}
}
private void createTabInstance(int tab) {
new FragmentADetail();
fragment = FragmentADetail.newInstance(tab);
Bundle args = new Bundle();
args.putInt("tab", tab);
fragment.setArguments(args);
fragmentA_Data[tab] = fragment;
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_placeholder, fragmentA_Data[tab]);
fragmentTransaction.commitAllowingStateLoss();
}
public void getTabData(int tab) {
if (fragmentA_Data[tab] == null) {
createStoreTimePeriodInstance(tab);
} else {
if (fragmentA_Data[tab].getArguments() == null) {
Bundle args = new Bundle();
args.putInt("tab", tab);
fragmentA_Data[tab].setArguments(args);
}
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_placeholder, fragmentA_Data[tab]);
fragmentTransaction.commitAllowingStateLoss();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("data", fragmentA_Data);
}
5 - Finally, FragmentADetail has this code:
public static FragmentADetail newInstance(int tab) {
selectedTab = tab;
return new FragmentADetail();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.details_fragment, container, false);
...
if (savedInstanceState != null) {
selectedTab = savedInstanceState.getInt("selectedTab");
}
...
}
public void getTabData(int tab) {
//This is where I'm getting the data that populates the layout
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("selectedTab", selectedTab);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
getTabData(args.getInt("tab"));
}
}
Now, imagine I'm on FragmentA with the third tab selected. If I rotate the screen I have this sequence of events:
ControlPanelFragment onSaveInstanceState saves the current tab and current fragment
FragmentA onSaveInstanceState saves the tabs fragments for the pager
navigationDrawer second option gets again called fragment = ControlPanelFragment.newInstance();
ControlPanelFragment onViewCreated is called and I can get the saved data information and a new pager and tabs are created
FragmentA onViewCreated is called and I can extract the saved data
FragmentADetail onActivityCreated gets the saved data and loads the data correctelly (at least I think)
And from now a second set of methods is called the second time and the data that was previously saved is reseted and so it now displays wrong data
ControlPanelFragment onSaveInstanceState but now the savedInstanceState is null
ControlPanelPagerAdapter getItem is called instantiating the 3 fragments
FragmentA onSaveInstanceState its now called but savedInstanceState is null
FragmentADetail onActivityCreated is called but now the tab = 0
Can someone explain-me how can I stop steps 7 to 10 from happening?
I figure out what was my problem.
When I was doing:
case FRAGMENT_OPTION2:
fragment = ControlPanelFragment.newInstance();
break;
I was creating a fragment and when I rotated the screen selectItem(int position) was again called so a new instance of the same object was created thus the steps 7 and following. The solution was to check if the fragment was already created and use him instead of creating a new one.
I've saved the initial fragment with a tag and them looked for that tag. If the tag existed, use that fragment otherwise create a new one.
public void selectItem(int position) {
Fragment fragment = null;
switch (position) {
case FRAGMENT_OPTION1:
...
break;
case FRAGMENT_OPTION2:
fragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(position));
if (fragment == null) {
fragment = ControlPanelFragment.newInstance();
}
break;
...
case FRAGMENT_OPTIONN:
...
return;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_container, fragment,
String.valueOf(position)).commitAllowingStateLoss();
}
}
I have an activity where the user press a button and then is send to a fragment, but I wish to pass an extra for the use of the fragment:
activity A(where is the button):
public OnClickListener publish = new OnClickListener(){
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(),ActivityB.class);
intent.putExtra("friendIdRowID", rowID);
startActivity(intent);
}
};
Activity B is loading the fragment(where I wish to retrieve the extra "friendIdRowID"),
the fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_main2, container, false);
Bundle extras = getActivity().getIntent().getExtras();
if (extras != null)
{
String myString = extras.getString("friendIdRowID");
}
}
But it is not working, what can I do to pass and retrieve the extra? thanks.
You need to use the setArguments() method of Fragment to pass information into your fragment. In the activity that creates the fragment, do something like this:
YourFragment f = new YourFragment();
Bundle args = new Bundle();
args.putString("friendIDRowID", getIntent().getExtras().getString("friendIDRowID"));
f.setArguments(args);
transaction.add(R.id.fragment_container, f, "tag").commit();
Then, override the onCreate() method of your Fragment and do the following:
Bundle args = getArguments();
String myString = args.getString("friendIdRowID");
Like extras for an Activity, you can add as many things to your arguments bundle as you wish. Hope this helps!