I would like to know if anyone knows a way to achieve both forward and backward navigation with Fragments?
I would like to start with a single Fragment, when I press the next button a new Fragment must be created, when I push the back button, the previous Fragment must be shown. My code does this and it saves any changes I have made to any previous Fragments as they are saved in the back stack, however, I want the same to be true of forward navigation, is there any way in which I can achieve this?
So to be more exact, I want to for example create 10 Fragments all with a single text box in which I can enter some data, each time I enter data and press the next button it must navigate to the next Fragment, have an empty text box and save the previous Fragment plus data entered to the back stack (this it currently does). So when I get to Fragment 10, I want to be able to go back to Fragment 1 and then back to Fragment 10 but as I navigate forward again, the data I originally entered must still be there. Then when I navigate to Fragment 11 it must be an empty text box. So it must be a forward and backward navigation system of sorts.
The code below generates Fragments dynamically from code and adds Views to it dynamically as well (at run time). This is the code I currently have working for going backwards.
public class MainActivity extends Activity
{
int mStackLevel = 0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button IntegratedBiometricsButton = (Button) findViewById(R.id.integrated_biometrics_button);
IntegratedBiometricsButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent IBIntent = new Intent(MainActivity.this, SimpleScanActivity.class);
startActivity(IBIntent);
}
});
// Watch for button clicks.
Button button = (Button) findViewById(R.id.new_fragment);
button.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
addFragmentToStack();
}
});
button = (Button) findViewById(R.id.delete_fragment);
button.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
getFragmentManager().popBackStack();
if(mStackLevel > 0){mStackLevel--;}
}
});
if (savedInstanceState == null)
{
// Do first time initialization -- add initial fragment.
Fragment newFragment = CountingFragment.newInstance(mStackLevel);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();
} else
{
mStackLevel = savedInstanceState.getInt("level");
}
}
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putInt("level", mStackLevel);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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);
}
void addFragmentToStack()
{
mStackLevel++;
// Instantiate a new fragment.
Fragment newFragment = CountingFragment.newInstance(mStackLevel);
// Add the fragment to the activity, pushing this transaction
// on to the back stack.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, newFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
public static class CountingFragment extends Fragment
{
int mNum;
/**
* Create a new instance of CountingFragment, providing "num"
* as an argument.
*/
static CountingFragment newInstance(int num)
{
CountingFragment f = new CountingFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
/**
* The Fragment's UI is just a simple text view showing its
* instance number.
*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
int ID = 0;
View v = inflater.inflate(R.layout.fragment_layout, container, false);
LinearLayout fragmentLayout = (LinearLayout) v.findViewById(R.id.infoLayout);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
TextView tv = new TextView(container.getContext());
tv.setId(ID);
ID++;
tv.setTextSize(16);
tv.setText("Fragment #" + mNum);
tv.setGravity(Gravity.CENTER);
tv.setLayoutParams(lp);
fragmentLayout.addView(tv);
EditText et = new EditText(container.getContext());
et.setId(ID);
ID++;
et.setHint("Text");
et.setGravity(Gravity.CENTER);
et.setInputType(InputType.TYPE_CLASS_NUMBER);
et.setLayoutParams(lp);
fragmentLayout.addView(et);
CheckBox cb = new CheckBox(container.getContext());
cb.setId(ID);
cb.setChecked(false);
cb.setGravity(Gravity.LEFT);
cb.setLayoutParams(lp);
fragmentLayout.addView(cb);
cb.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(((CheckBox) v).isChecked())
{
Toast.makeText(v.getContext(), "Yo", Toast.LENGTH_LONG).show();
}
}
});
ID++;
ImageView iv = new ImageView(container.getContext());
iv.setId(ID);
iv.setImageResource(R.drawable.output);
iv.setLayoutParams(lp);
fragmentLayout.addView(iv);
iv.setOnLongClickListener(new View.OnLongClickListener()
{
public boolean onLongClick(View v)
{
Toast.makeText(v.getContext(), "It works", Toast.LENGTH_LONG).show();
return true;
}
});
ID++;
//View tv = v.findViewById(R.id.text);
//((TextView) tv).setText("Fragment #" + mNum);
//tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
return v;
}
}
}
Related
I have a tab fragments app. The problem is when I go into an activity inside my app and want going back to my tabs layout it returns without the tabs row layout. I can see only the specific fragment page without the row above (the tab's row) that makes me able to navigate between the tabs.
Do you know what can I do to solve it? How can I see the tab's row too?
Thanks for any help,
This is the first tab that I want to see back from the activity:
public class Tab1MyProfile extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tab1_my_profile, container, false);
return rootView;
}
}
This is the activity that contains code to go back to the fragment tab:
public class GameLive extends AppCompatActivity implements RecognitionListener {
private Intent intent;
private Button mStopButton;
public void stopGame (View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to finish the game?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Tab1MyProfile fragment = new Tab1MyProfile();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_live);
mStopButton = (Button) findViewById(R.id.btnEndGame);
mStopButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
stopGame(view);
}
});
}
}
And this is the activity that contains all the tab's fragment:
public class StartActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#TargetApi(Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_start, 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 {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Tab1MyProfile tab1=new Tab1MyProfile();
return tab1;
case 1:
Tab2StartGame tab2=new Tab2StartGame();
return tab2;
case 2:
Tab3StatsArea tab3=new Tab3StatsArea();
return tab3;
case 3:
Tab4Settings tab4=new Tab4Settings();
return tab4;
}
return null;
}
#Override
public int getCount() {
// Show 4 total pages.
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "My profile";
case 1:
return "Start Game";
case 2:
return "Stats Area";
case 3:
return "Settings";
}
return null;
}
}
}
Thank again!
What if you replace everything inside the onClick method of the DialogInterface.OnClickListener with GameLive.this.finish();. This will close the GameLive activity on click and return you to the previous activity, which should be the one that contains the missing navigation bar.
Though it seems an easy problem, I've been stuck for quite a few hours. If anyone can help my out providing some code it'd be great. So there it goes my question.
There's a MainActivity which has an ActionBar with two buttons. Each button starts a ListFragment when it's clicked. Then each item of each ListFragment starts another fragment (that's what I'm not able to achieve). Here is the code for the MainActivity:
public class MainActivity extends Activity implements
DataListFragment.DataListSelectionListener {
private final String TAG = "MainActivity";
// Reference the buttons in the ActionBar
private Button actionBarData;
private Button actionBarElu;
private Button actionBarOptions;
// Reference the ListFragments
DataListFragment dataListFragment;
EluListFragment eluListFragment;
// Reference the fragments related to the listItems
SectionTypeFragment sectionTypeFragment;
SectionDimensionsFragment sectionDimensionsFragment;
MaterialsFragment materialsFragment;
ReinforcementFragment reinforcementFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Inflate the custom layout for the ActionBar
final ViewGroup actionBarLayout = (ViewGroup) getLayoutInflater().inflate(
R.layout.action_bar,
null);
// Set the custom ActionBar
final ActionBar actionBar = getActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(actionBarLayout);
// ActionBar Customization with buttons
final int actionBarColor = getResources().getColor(R.color.blue_2);
actionBar.setBackgroundDrawable(new ColorDrawable(actionBarColor));
actionBarData = (Button) findViewById(R.id.action_bar_data);
actionBarData.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
Log.i(TAG, "DATA button clicked.");
clickActionBarButton(v);
}
});
actionBarElu = (Button) findViewById(R.id.action_bar_elu);
actionBarElu.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "ELU button clicked.");
clickActionBarButton(v);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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_bar_data) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void clickActionBarButton(View v){
// Get a reference to the FragmentManager
FragmentManager fragmentManager = getFragmentManager();
// Begin a new FragmentTransaction
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Create the fragment depending on the button pressed
if(v == actionBarData){
// If there is no FeedFragment instance, then create one
if(sectionTypeFragment == null)
dataListFragment = new DataListFragment();
// Replace the main_frame_layout with the sectionTypeFragment
fragmentTransaction.replace(R.id.main_frame_layoout, dataListFragment);
}else if(v == actionBarElu){
// If there is no FeedFragment instance, then create one
if(sectionTypeFragment == null)
eluListFragment = new EluListFragment();
// Replace the main_frame_layout with the sectionTypeFragment
fragmentTransaction.replace(R.id.main_frame_layout, eluListFragment);
}
// Commit the FragmentTransaction
fragmentTransaction.commit();
}
// Called when the user selects an item in the DataListFragment
public void onDataListSelection(int index){
// Get a reference to the FragmentManager
FragmentManager fragmentManager = getFragmentManager();
// Begin a new FragmentTransaction
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Add the fragment related to the selected item in the List
switch (index){
case 0:
// If there is no SectionTypeFragment instance, then create one
if(sectionTypeFragment == null)
sectionTypeFragment = new SectionTypeFragment();
// Replace the main_frame_layout with the sectionTypeFragment
fragmentTransaction.replace(R.id.main_frame_layout, sectionTypeFragment);
// Add this FragmentTransaction to the backstack
fragmentTransaction.addToBackStack(null);
break;
case 1:
...
}
// Commit the FragmentTransaction
fragmentTransaction.commit();
}
}
Here is the code for one of the ListFragments (DataListFragment):
public class DataListFragment extends ListFragment {
private static final String TAG = "DataFragment";
// List items
private String[] listItems;
private DataListSelectionListener mListener = null;
// Callback interface that allows this Fragment to notify the MainActivity when
// user clicks on a DataList Item
public interface DataListSelectionListener {
public void onDataListSelection(int index);
}
// Called when the user selects an item from the DataList
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Indicates the selected item has been checked
getListView().setItemChecked(position, true);
// Inform the MainActivity that an item has been selected
mListener.onDataListSelection(position);
}
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// Get the the items to show in the List from the strings.xml
listItems = getResources().getStringArray(R.array.data_list_array);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, listItems);
setListAdapter(adapter);
}
}
Here is the exception:
03-12 14:39:38.681 29515-29515/com.tari.rcsec E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3459)
at android.view.ViewGroup.addView(ViewGroup.java:3330)
at android.view.ViewGroup.addView(ViewGroup.java:3275)
at android.view.ViewGroup.addView(ViewGroup.java:3251)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:840)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
at android.app.BackStackRecord.run(BackStackRecord.java:635)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5022)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1032)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:790)
at dalvik.system.NativeStart.main(Native Method)
public class MyActivity extends Activity implements ButtonFragement.OnFragmentInteractionListener, TextFragment.OnFragmentInteractionListener,Communicator {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
ButtonFragement btnfrg=new ButtonFragement();
TextFragment txtfrg= new TextFragment();
FragmentManager fm=getFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
ft.add(R.id.my_activity,btnfrg,"Fragment");
ft.add(R.id.my_activity,txtfrg,"Second Fragment");
ft.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.my, 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);
}
#Override
public void onFragmentInteraction(Uri uri) {
}
#Override
public void respond(String data) {
FragmentManager fm=getFragmentManager();
TextFragment f1= (TextFragment) fm.findFragmentById(R.id.textfrg);
f1.changeText(data);
}
}
This is my main_Activity code, here i am trying to send a data over the fragment but it gives me error at f1.changeText(data).Basic structure of my project is , on main Activity , i created two fragment. One with button and another with text. I want to show how many times the button was clicked on second fragment using a communicator interface. Here in "data" counter shows a how many times button was clicked but i am not able to transfer it over second fragment.
Complete Code for the Program---
public interface Communicator {
public void respond(String data);
}
In TextFragment class i added this method----
public void changeText(String data)
{
txt.setText(data);
}
In ButtonFragment class i added and modified following method
public class ButtonFragement extends Fragment implements View.OnClickListener{
int counter=0;
private OnFragmentInteractionListener mListener;
Button btn;
Communicator comm;
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
comm= (Communicator) getActivity();
btn= (Button) getActivity().findViewById(R.id.button);
btn.setOnClickListener(this);
}
#Override
public void onClick(View view) {
counter++;
// comm.respond("The button was clicked "+counter+" times");
comm.respond("hi");
}
Here, i just added which i added in my program. My program get crash at...MainActiviy f1.changeText(data);
But why i am not getting it.Can anyone Help me fixed this bug?
Bundle bundle = new Bundle();
bundle.putString("key", value);
// set Fragmentclass Arguments
YourFragment ff= new YourFragment ();
ff.setArguments(bundle);
transaction.add(R.id.my_activity, ff);
Using Bundle
From Activity:
Bundle bundle = new Bundle();
bundle.putString("message", "Hello!");
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();
Fragment:
Reading the value in the fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
String myValue = this.getArguments().getString("message");
...
...
}
You have no fragment with id R.id.textfrg.
You are for some reason adding two fragments with id R.id.my_activity. One with tag "Fragment" and another with tag "Second Fragment".
So you are getting error.
Your idea is rigth.
This may be helpfull
TextFragment f1= (TextFragment) fm.findFragmentByTag("Second Fragment");
DO this way:
On Activity Side.
Fragment fragment = new GridTemplate();
Bundle bundle = new Bundle();
bundle.putInt("index",your value);
fragment.setArguments(bundle);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
here R.id.frame_container is a frame Layout or Relative Layout In which you have to add the fragment.
On Fragment Side.
int index = getArguments().getInt("index");
hope this wil solve your problem. Thanks
I right understanding that it is impossible to simultaneously perform the animation of the fragment and view.
I try to run view animation and fragment at the same time
private void startAnim(){
mShowDarkOverlay = ObjectAnimator.ofFloat(mBackDarkOverlay, "alpha", 0f, 1f);
mShowDarkOverlay.setDuration(100);
mShowDarkOverlay.setStartDelay(0);
mShowDarkOverlay.start();
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(android.R.anim.fade_in,R.anim.paddle_fade_out)
.replace(R.id.fragment_container, new MyFragment())
.commit();
}
But I only see the animation fragment.
I understand that the animation on the view runs in the main thread, and when it starts the animation of the fragments, the animation view is interrupted.
Is that right? Cannot be performed immediately animation view and fragment ?
UPDATE
I created test project. github
Open application - press button(add item) in action bar (waiting 3 seconds)- click button "2".
And we see the result. Animation View does not begin until you create the fragment.
Fragment blocks the main thread?
In my case the fragment need 2-3 seconds to be created.
I want to change the background and at the same time to change the fragment. Is this possible?
public class FragmentCustomAnimationSupport extends FragmentActivity {
int mStackLevel = 1;
private TextView mTestAnimationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_stack);
mTestAnimationView = (TextView) findViewById(R.id.title);
// Watch for button clicks.
Button button = (Button)findViewById(R.id.new_fragment);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
addFragmentToStack();
}
});
if (savedInstanceState == null) {
// Do first time initialization -- add initial fragment.
Fragment newFragment = CountingFragment.newInstance(mStackLevel);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();
} else {
mStackLevel = savedInstanceState.getInt("level");
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("level", mStackLevel);
}
void addFragmentToStack() {
mStackLevel++;
Animator animator = ObjectAnimator.ofFloat(mTestAnimationView, "alpha", 0f, 1f);
animator.setDuration(300);
animator.start();
// Instantiate a new fragment.
Fragment newFragment = CountingFragment.newInstance(mStackLevel);
// Add the fragment to the activity, pushing this transaction
// on to the back stack.
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.fragment_slide_left_enter,
R.anim.fragment_slide_left_exit,
R.anim.fragment_slide_right_enter,
R.anim.fragment_slide_right_exit);
ft.replace(R.id.simple_fragment, newFragment);
ft.addToBackStack(null);
ft.commit();
}
public static class CountingFragment extends Fragment {
int mNum;
/**
* Create a new instance of CountingFragment, providing "num"
* as an argument.
*/
static CountingFragment newInstance(int num) {
CountingFragment f = new CountingFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
/**
* The Fragment's UI is just a simple text view showing its
* instance number.
*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.hello_world, container, false);
View tv = v.findViewById(R.id.text);
((TextView)tv).setText("Fragment #" + mNum);
tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
return v;
}
}
}
I tried in SupportV4Demo, code above, animation of view and fragment played together. mTestAnimationView was a textView layouted above the fragment container(R.id.simple_fragment).
Hi i have a listview sidebar and i am displaying fragments based on user selection in listview.
This is how i am replacing fragments
public void switchFragment(Fragment fragment, boolean addBackStack) {
try {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content, fragment);
currentFragment = fragment;
//if (addBackStack)
ft.addToBackStack(null);
ft.commit();
} catch (Exception e) {
}
}
This is my sample fragment code.Now when i replace fragments i am saving instance state in onpause and restoring it in onresume but it only works when i press back button. When i manually navigate back to fragment from listview ,fragment state is not restored.Why?
public class Fragment1 extends BaseFragment {
int currentFragmentInd = 1;
private Button startButton;
private Button endButton;
private long savedStartTime;
private TextView setStartText;
private TextView setEndText;
private String starttime;
private String endtime;
public int getIndex() {
MyApplication.getApplication().setCurrentChild(0);
MyApplication.getApplication().setCurrentGroup(0);
return currentFragmentInd;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState !=null)
{
}
}
#Override
public void onResume() {
super.onResume();
setStartText= (TextView)getActivity().findViewById(R.id.MAtextView2);
setEndText= (TextView)getActivity().findViewById(R.id.MAtextView3);
setEndText.setText(endtime);
setStartText.setText(starttime);
}
#Override
public void onPause() {
super.onPause();
setStartText= (TextView)getActivity().findViewById(R.id.MAtextView2);
setEndText= (TextView)getActivity().findViewById(R.id.MAtextView3);
starttime=setStartText.getText().toString();
endtime=setEndText.getText().toString();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
FrameLayout frameLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.layout1, null, false);
((MainActivity) getActivity()).openList(0, 0);
if (savedInstanceState == null) {
}
startButton= (Button) contentView.findViewById(R.id.button);
endButton= (Button) contentView.findViewById(R.id.button2);
endButton.setEnabled(false);
setStartText= (TextView)contentView.findViewById(R.id.MAtextView2);
setEndText= (TextView)contentView.findViewById(R.id.MAtextView3);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Time now = new Time();
now.setToNow();
}
});
endButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Time now = new Time();
now.setToNow();
setEndText.setText(now.hour+" : "+now.minute);
}
});
return contentView;
}
}
Late replay but might help somebody else.
This happens because when you click a listview item you create a new inctance of that fragment.
"I assume the fragment you send to switchFragment(Fragment fragment), is created using a 'new' keyword."
Therefore this new instance of a fragment doesnt hold your old data.
This is how I solved this. There are probably better ways, but since nobody replied, I will give my solution.
When you replace the fragment (ft.replace, fragment), give a string reference to that transaction: -ft.replace(R.id.content, fragment, "FRAGMENT_NAME");
When you add the fragment to the backstack with addToBackStack(null); put the name of your fragment where you have null.: -ft.addToBackStack("FRAGMENT_NAME");
Create a method which tells you if that fragment has already been created, and therefore exists in the back stack.:
public boolean isTagInBackStack(String tag){
Log.i(TAG, "isTagInBackStack() Start");
int x;
boolean toReturn = false;
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
Log.i(TAG, "backStackCount = " + backStackCount);
for (x = 0; x < backStackCount; x++){
Log.i(TAG, "Iter = " + x +" "+ getSupportFragmentManager().getBackStackEntryAt(x).getName());
if (tag == getSupportFragmentManager().getBackStackEntryAt(x).getName()){
toReturn = true;
}
}
Log.i(TAG, "isTagInBackStack() End, toReturn = " + toReturn);
return toReturn;
}
Now before you create a new instance of that fragment check in the backstack if a backstack item named "FRAGMENT_NAME" exists.
if it exists, use that item (fragment) instead of creating a new one.
if (isTagInBackStack("FRAGMENT_NAME")){
Log.i(TAG, "Tag is in BackStack!!!! frag is = " + getSupportFragmentManager().findFragmentByTag("FRAGMENT_NAME"));
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.main_activity_container, getSupportFragmentManager().findFragmentByTag("FRAGMENT_NAME"));
transaction.addToBackStack("FRAGMENT_NAME");
transaction.commit();
}else{
Create the fragment (this happens the first time.
}