This question already has answers here:
Start a fragment via Intent within a Fragment
(5 answers)
Closed 6 years ago.
i want to replace activity to a fragment, this code is not working.
Intent intent = new Intent(Activity.this, Fragment.class);
startActivity(intent);
finish();
You cannot switch from an Activity to Fragment, because a Fragment does not have its own existence without an Activity. i.e. a Fragment works inside an Activity.
Basically, Fragments are mainly used to create multi-pane screens.
Inside an Activity if you can replace Fragments (associated with the Activity) as mentioned in the above code examples to change the UI.
Try like this in your activity
#Override
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
} else {
getSupportFragmentManager().popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
transaction.replace(R.id.flContent, fragment);
transaction.commitAllowingStateLoss();
getSupportFragmentManager().executePendingTransactions();
}
and use like this
YourFragment mYourFrag = new YourFragment ();
replaceFragment(mYourFrag , false);
Create a Fragmen class like
public class FragmentName extends android.support.v4.app.Fragment {}
And then you are able to cast a activity to view like:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View returner = null;
Intent intent = new Intent([CONTEXT],[CLASSNAME.class]);
Bundle args = this.getArguments();
final Window w = [LocalActivityManager].startActivity("Title", intent);
final View wd = w != null ? w.getDecorView() : null;
if (wd != null) {
ViewParent parent = wd.getParent();
if(parent != null) {
ViewGroup v = (ViewGroup)parent;
v.removeView(wd);
}
wd.setVisibility(View.VISIBLE);
wd.setFocusableInTouchMode(true);
if(wd instanceof ViewGroup) {
((ViewGroup) wd).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
}
}
returner = wd;
return returner;
}
Related
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 a ProfileFragment class which contains two setters:
public void setPseudo(String pseudo){
textPseudo.setText(pseudo);
}
public void setEmail(String email){
textEmail.setText(email);
}
And in my Activity I would like to call these functions:
user = new ProfileFragment();
if (intent != null) {
user.setPseudo(intent.getStringExtra(USER_PSEUDO));
user.setEmail(intent.getStringExtra(USER_EMAIL));
}
It says "can't resolve method...".
Does it mean I can't do this?
Are you sure you don't have a Profile class with setters? Not a Fragment?
Fragments generally don't use setters, they use arguments.
Reason being: If you call setEmail, and then you called to some view setText within the new Fragment, you get a NullPointerException because that TextView was never initialized
Fragment profileFragment = new ProfileFragment();
Bundle args = new Bundle();
if (intent != null) {
args.putAll(intent.getExtras());
}
profileFragment.setArguments(args);
// Show new Fragment
getSupportFragmentManager()
.replace(R.id.content, profileFragment)
.commit();
And inside your Fragment's onCreateView, you can now use this, for example
final Bundle args = getArguments();
String pseudo = "";
if (args != null) {
pseudo = args.getString(YourActivity.USER_PSEUDO);
}
textPseudo.setText(pseudo);
I am trying to pass an object Fragment -> Activity -> Fragment.
My 2nd Fragment says my object is null when getting arguments:
Fragment A: (Sending Object, communicator is interface to Main Activity)
meetsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Meet meet = new Meet();
meet = meetList.get(position); // meet is not null here
communicator.changeToolbarTitle(meet.getName());
****** Sends Meet object to main activity ********
communicator.sendMeetToMeetProfile(meet);
}
});
Main Activity:
#Override
public void sendMeetToMeetProfile(Meet meet) {
MeetAthletesListContainer meetAthletesListContainer = new MeetAthletesListContainer();
***** Fragment is not replaced just called *******
MeetAthletesMales meetAthletesMales = new MeetAthletesMales();
MeetAthletesFemales meetAthletesFemales = new MeetAthletesFemales();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Bundle bundleMales = new Bundle();
bundleMales.putParcelable("meetAthletesMales", meet);
meetAthletesMales.setArguments(bundleMales);
Bundle bundleFemales = new Bundle();
bundleFemales.putParcelable("meetAthletesFemales", meet);
meetAthletesFemales.setArguments(bundleFemales);
******* Replaces current fragment with container that contains above (2) fragments *******
transaction.replace(R.id.frameLayout, meetAthletesListContainer, "meetAthletesListContainer");
transaction.addToBackStack(null);
transaction.commit();
}
Fragment B: (Fragment is contained inside another fragment)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_meet_athletes_males, container, false);
Log.e("", "Fragment onCreateView Called!");
initializeVar();
*****Says this meet object is null*****
meet = getArguments().getParcelable("meetAthletesMales");
}
I am replacing a fragment with another but passing the object to a fragment which is inside another fragment(meet_container_fragment). So my object is being sent directly to the fragment. I got this working in another instance where I actually replace the fragment but I want to replace the FRAGMENT CONTAINER, not the actual fragment B
Try this
MeetAthletesListContainer meetAthletesListContainer = new MeetAthletesListContainer();
***** Fragment is not replaced just called *******
MeetAthletesMales meetAthletesMales = new MeetAthletesMales();
MeetAthletesFemales meetAthletesFemales = new MeetAthletesFemales();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Bundle bundle = new Bundle();
bundle.putParcelable("meetAthletesMales", meet);
bundle.putParcelable("meetAthletesFemales", meet);
meetAthletesFemales.setArguments(bundle);
******* Replaces current fragment with container that contains above (2) fragments *******
transaction.replace(R.id.frameLayout, meetAthletesListContainer, "meetAthletesListContainer");
transaction.addToBackStack(null);
transaction.commit();
Try this,
main activity
FragmentB fragmentb = FragmentB.newInstance(appContext,meet);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.contentContainer, fragmentb , tag);
Fragment B
public static FragmentB newInstance(AppContext appContext, Meet meet) {
FragmentB fragment = new FragmentB();
Bundle args = new Bundle();
args.putSerializable(ARG_APP_CONTEXT, appContext);
args.putString(ARG_MEET_NAME, meet.name);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
appContext = (AppContext) getArguments().get(ARG_APP_CONTEXT);
name= getArguments().getString(ARG_MEET_NAME);
}
}
also make Meet implements Serializable
I'am trying to make a app with a flexible UI.
I already implemented for handset devices (I have one activity and multiple fragments), and what I done was: The main fragment is a dashboard, and when I click in one button of it, he dashboard is replaced by a new fragment ( the clicked feature). Here is the code:
Dashboard fragment:
public class DashboardFragment extends Fragment {
GridView gridView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.activity_dashboard, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
gridView=(GridView)getView().findViewById(R.id.dashboard_grid);
gridView.setAdapter(new ImageAdapter(getActivity()));
gridView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment fragment = null ;
switch (position) {
case 0:
fragment = new TestFragment();
break;
case 1 :
fragment = new TestFragment();
break;
case 2 :
fragment = new TestFragment();
break;
case 3 :
fragment = new TestFragment();
break;
case 4 :
fragment = new TestFragment();
break;
}
transaction.replace(R.id.container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
}
}
and my Main Activity:
public class MainActivity extends FragmentActivity{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.container) != null) {
if (savedInstanceState != null) {
return;
}
// Create an instance of ExampleFragment
DashboardFragment firstFragment = new DashboardFragment();
firstFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().add(R.id.container, firstFragment).commit();
}
}
}
Now, what I want is to adapt this code and use a layout for tablets, with the dashboard on the left and the choosen fragment on the right, like this:
What could I do? I already tried to adapt this example, but I can't because they only update the fragment, they don't replace it.
Check this great article about multi-pane development.
It also includes an example (Sections 10 and 11)
Basically you can check whether there is a fragment element for your "Fragment B" in the current layout. If yes, you just update its content, if no, then start an activity which has it in its layout, or replace one in the current layout.
DetailFragment fragment = (DetailFragment) getFragmentManager().findFragmentById(R.id.detail_frag);
if (fragment==null || ! fragment.isInLayout()) {
// start new Activity or replace
}
else {
fragment.update(...);
}
I am using ActionBarSherlock's action bar tabs in my application with each tab populated by a single fragment inside a SherlockActivity Tabs.
One of my Tabs contains a fragment, FragmentHome, with a list of news articles. When an article is selected, FragmentHome is replaced by another fragment, FragmentNews.
FragmentNews just contains a webview to load the selected article. The article is loaded fine. I override the onBackPressed in my activity so that FragmentHome is reattached and FragmentNews is removed.
While there are no errors, the webview inside FragmentHome is never removed from the view and overlaps with other fragments. (See screenshots)
Its weird because the same code works for a another SherlockFragment with ListView in it but is messed up when using a WebView. Here is the code to replace FragmentHome with FragmentNews initially:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
listNews.setItemChecked(position, true);
Bundle bundle = new Bundle();
bundle.putStringArray("NEWS",
new String[] {
mNews.newsFeed.get(position).getTitle(),
mNews.newsFeed.get(position).getLink()
.toExternalForm() });
FragmentTransaction ft = getSherlockActivity()
.getSupportFragmentManager().beginTransaction();
Fragment frag = SherlockFragment.instantiate(getSherlockActivity(),
FragmentNews.class.getName(), bundle);
ft.detach(getSherlockActivity().getSupportFragmentManager()
.findFragmentById(getId()));
ft.add(android.R.id.content, frag, Tabs.FRAG_NEWS);
ft.commit();
}
Overriden onBackPressed in Tabs:
#Override
public void onBackPressed() {
Fragment frag = getSupportFragmentManager().findFragmentByTag(
FRAG_DETAILS);
if (frag != null && frag.isVisible()) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.remove(frag);
Fragment mFragment = getSupportFragmentManager().findFragmentByTag(
TAB_PORTFOLIO);
if (mFragment == null) {
mFragment = SherlockFragment.instantiate(this,
FragmentPortfolioList.class.getName(), null);
ft.add(android.R.id.content, mFragment, TAB_PORTFOLIO);
} else {
ft.attach(mFragment);
}
ft.commit();
} else {
frag = getSupportFragmentManager().findFragmentByTag(FRAG_NEWS);
if (frag != null && !frag.isDetached()) {
Log.e("onBackPressed", "for " + frag.getTag());
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.remove(frag);
Fragment mFragment = getSupportFragmentManager()
.findFragmentByTag(TAB_HOME);
if (mFragment == null) {
mFragment = SherlockFragment.instantiate(this,
FragmentHome.class.getName(), null);
ft.add(android.R.id.content, mFragment, TAB_HOME);
} else {
ft.attach(mFragment);
}
ft.commit();
} else {
Log.e("onBackPressed", "inside else");
super.onBackPressed();
}
}
}
Snippet from FragmentNews
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
arr = getArguments().getStringArray("NEWS");
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_news, container);
newsView = (WebView) view.findViewById(R.id.news_WV_Brief);
newsView.getSettings()
.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
newsView.getSettings().setGeolocationEnabled(false);
newsView.getSettings().setAllowFileAccess(false);
newsView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.e("override", url);
return true;
}
});
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onResume() {
super.onResume();
newsView.loadUrl(arr[1]);
}
I have seen posts talking about FlashPlayer causing issues because of SurfaceView cutting a hole but I am just displaying simple webpages without any videos. Help highly appreciated.
I figured out the problem while going over the source code of WebViewFragment. I realized there isn't much going on other than pause/resume of webview.
I had two serious errors in my code:
I never returned the inflated view in onCreatView in
FragmentNews. I was returning super.onCreateView(inflater,
container, savedInstanceState).
I forgot to set attachToRoot to false in onCreateView when
inflating the XML layout - View view =
inflater.inflate(R.layout.fragment_news, container, **false**)
Therefore, the inflated view was just standing on its own without being attached to the fragment. When the fragment was replaced, it resulted in a mashed up display because the inflated layout containing the WebView was never removed. Unfortunately, this complied without errors.