Android: switch to a new fragment inside a fragment? - java

I have an Android application with a MainActivity and I do this to create navigational tabs in onCreate:
ActionBar myActionBar = getActionBar();
myActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab = myActionBar.newTab().setText("FirstTab").setIcon(R.drawable.first_tab)
.setTabListener(new TabListener<FirstTabFragment>(this, "FirstTab",
FirstTabFragment.class));
... more tabs ...
The TabListener, I use this from developer.android.com:
http://developer.android.com/reference/android/app/ActionBar.html#newTab():
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
...
public TabListener(Activity activity, String tag, Class<T> clz) { ... }
}
So if a user clicks on the first tab, my fragment FirstTabFragment is called and executes onCreateView.
My problem is, if a user now clicks a button I do the following and I do not know how to switch to the next fragment:
private OnClickListener firstTabListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (v == button1) {
Intent intent = new Intent(???, MyDetailsFragment.class);
startActivity(intent);
} else if (...) {
...
}
}
};
The MyDetailsFragmentshould show details to the selected item (button click), so I want to drill down to the details fragment and want to give some extra data to the new fragment, so the detail fragment knows which details of which selected item it should display.
The selected tab should not change and the back button should go back to the FirstTabFragment page.
I think I should start a new fragment, but it is not possible, the name of the method startActivity tells me that I start a new activity and not a fragment. So, I have to use the MainActivity and put into there the new fragment?
(I do not use the android-support-v4.jar library, because I only target Android 4 devices)
How can I solve this problem? Any ideas?

From the fragment, call a method on the hosting activity, telling it about the button click event. The activity can then do whatever is appropriate.
Personally, I think that totally replacing the contents of a tab is inappropriate in the vast majority of cases, but you are certainly welcome to do it.

Related

Too many operations slowing down main thread which is causing delay in loading next acitivty

Apparently I have a scenario where my launcher activity is splash screen which contains a handler class to show animation on start.
handler.postDelayed(new Runnable() {
#Override
public void run() {
//animation coder inside
}, 5);
After it is launched the app then navigates to next activity i.e. Home Activity. This activity is basically a fragment loader where I have a custom top bar, frame layout (to load fragment in it) and BottomAppBar. Now on main method I'm intialising all the ids and calling two methods i.e. loadFrag() which loads default fragment to display when home activity is first loaded and clicklisteners() which contains click listener implementation of image views and bottom navigation view included in top and bottom bar.
public void loadFrag() {
HomeFrag = new HomeFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, HomeFrag,
HomeFrag.getClass().getSimpleName()).addToBackStack("fragment").commit();
}
public void clickListeners() {
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#SuppressLint("NonConstantResourceId")
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
/* when user opens home fragment, title and back button will be set to gone
in order to display his location on home */
case R.id.homePage:
Fragment fragment = new HomeFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment,
fragment.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.VISIBLE);
tv_location.setVisibility(View.VISIBLE);
iv_edit.setVisibility(View.VISIBLE);
tv_title.setVisibility(View.GONE);
iv_back.setVisibility(View.GONE);
currentFragment = fragment;
break;
/* when user opens wallet fragment, location and edit location icon will be set to gone
in order to display tab title and back icon inside wallet fragment */
case R.id.wallet:
Fragment fragment1 = new WalletFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment1,
fragment1.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.GONE);
tv_location.setVisibility(View.GONE);
iv_edit.setVisibility(View.GONE);
tv_title.setVisibility(View.VISIBLE);
iv_back.setVisibility(View.VISIBLE);
tv_title.setText("Wallet");
currentFragment = fragment1;
break;
/* when user opens myorders fragment, location and edit location icon will be set to gone
in order to display tab title and back icon inside myorders fragment */
case R.id.myorders:
Fragment fragment3 = new MilkCheeseAndYogurtFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment3,
fragment3.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.GONE);
tv_location.setVisibility(View.GONE);
iv_edit.setVisibility(View.GONE);
tv_title.setVisibility(View.VISIBLE);
iv_back.setVisibility(View.VISIBLE);
tv_title.setText("My Orders");
currentFragment = fragment3;
break;
/* when user opens search fragment, location and edit location icon will be set to gone
in order to display tab title and back icon inside search fragment */
case R.id.search:
Fragment fragment4 = new MilkAndMilkPowderFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, fragment4,
fragment4.getClass().getSimpleName()).commit();
iv_location.setVisibility(View.GONE);
tv_location.setVisibility(View.GONE);
iv_edit.setVisibility(View.GONE);
tv_title.setVisibility(View.VISIBLE);
iv_back.setVisibility(View.VISIBLE);
tv_title.setText("Search");
currentFragment = fragment4;
break;
}
return true;
}
});
Now this all is happening on a single thread which is displaying home fragment after a delay of 2-6 seconds approximately on cold start. I have read about AsyncTask and Threads too but I'm unable to find any proper tutorial or code to take hint on how to implement it. If there's any approach better than that please let me know. Ask more if my question is still not clear.

How to avoid fragment superposition

I'm trying to display a list, using a ListFragment and a custom adapter. Each row includes a TextView and button. It looks like this :
When a button is clicked, I want the element of the list to change. In order to do this, I want to replace the existing ListFragment with another. My problem is that the second fragment is added over the first one, like this :
Here is the code that is executed when I click on a button, in the custom ArrayAdapter :
public void onClick(View view) {
//Some unrelated stuff
//I want to replace the old ListGeneratedFragment by a new one
ListGeneratedFragment fragment = new ListGeneratedFragment();
((MainActivity)getContext())
.getSupportFragmentManager()
.beginTransaction()
.replace(R.id.main_list_meals, fragment)
.commit();
}
});
I've already used the same technique in other parts of my code, and it works perfectly. I don't understand why the old fragment isn't replaced here.

Call a Method from another Method Android

I am not sure this workaround is the correct way to achieve my goal of having a prompt text in a spinner. What happens with this application is the spinner navigates to another Activity via an Intent and when the user navigates back to the Main Activity with the spinner they have two ways back. One with a Button and a click event the other by clicking the device BACK button. I am trying to call the code in the click event from the method that manages the device BACK button
I do not know how to call the click event from the device BACK button Method
#Override
public void onBackPressed() {
Toast.makeText(getApplicationContext(),"Use BACK BUTTON\n\n"+"On the Screen",Toast.LENGTH_LONG).show();
// I want to call goBack(View view) from here
// +++++++++++++++++++++++++++++++++++++++++++
}
public void goBack(View view){
Intent i = new Intent( PageTwo.this, MainActivity.class );
startActivity( i );
}
The reason I use this Intent to navigate BACK to the Main Activity is it reloads the variables in the Spinner
It looks like goBack(View) is most likely from an onClick setup in your layout XML. Since you aren't using the view, just pass null:
#Override public void onBackPressed() {
goBack(null);
}
I don't know if I get you right, if you just want to go back to the activity which started another activity, you can just call finish() method of Activity class:
#Override
public void onBackPressed() {
finish();
}
finish() reference

How do i push new Fragment onto tabFragment?

I have a tabbed app with four Fragments. To handle them i extend FragmentPagerAdapter and use a FragmentManager, mFragmentManager.
In one of these Fragments i need to press a button and display another Fragment(but back should of course go back to the old one).
Now i tried using an interface where this method is called when the user presses that button:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
......
switch(position){
case 0:
if(mFragmentAtHome ==null)
{
mFragmentAtHome = HomeScreenFragment.newInstance(new HomeScreenFragmentListener()
{
public void onSwitchToCreateCity() {
mFragmentOnHome = All_media.newInstance(aml);
mFragmentManager.beginTransaction().add(mFragmentOnHome,"allMfrag").commit();
notifyDataSetChanged();
//Lets see what the manager looks like
System.out.println("mFragmentManager:");
System.out.println(mFragmentManager.getFragments().toString());
}
});
}
return mFragmentAtHome;
case1:...
But somehow my fragment is not displayed. Still logcat tells me it is on the mFragmentManager:
mFragmentManager:
[HomeScreenFragment{41798e80 #0 id=0x7f050028 android:switcher:2131034152:0},
MyTripsFragment{4170d5d0 #1 id=0x7f050028 android:switcher:2131034152:1},
All_media{418f5f50 #2 allMfrag}]
But it doesn't have an id, or a android:switcher something.
What can i do?
Thanks!

How to populate listview adapter from outside Activity in a TabActivity

I have the following problem.
I am in a tabActivity with 2 tabs. Every tab will launch the same activity, but there is a onTabChangeListener.
In this tabchange listener i need to set up the listview adapter that is different for each activity.
So i will have two different lists, and i want to change their adapter from TabActivity, from this onTabchangeListener, but i get the following error: system services not available to activities before oncreate()
The code for tabs is:
host = getTabHost();
host.addTab(host.newTabSpec(TAG_AVAILABLE).setIndicator("First Tab")
.setContent(new Intent(this, MyActivity.class)));
host.addTab(host.newTabSpec(TAG_DOWNLOAD).setIndicator("Second Tab ")
.setContent(new Intent(this, MyActivity.class)));
host.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
#Override
public void onTabChanged(String s) {
MyActivity myActivity = new MyActivity();
int i = getTabHost().getCurrentTab();
if (i == FIRST_TAB) {
setAdapterForMyActivity(firstAdapter);
}
}
if (i == SECOND_TAB) {
setAdapterForMyActivity(secondAdapter);
}
}
}
});
}
The main question is how to set adapter of an listView which is in an Activity from TabActivity.
Thank you very much.
If you want to pass an Adapter to a child activity, you'll need a global shared object of some kind. One option would be to pass the adapter to an Application object in the parent TabActivity and then retrieve that in the child activity.

Categories

Resources