I have showing list of items which is displayed in grid and the data is coming from webservice . And when i click on the item it takes to the new screen but when coming from this screen to the screen having Grid the layout is recreated but i want to save the instance like activity so that the screen is not created again. what i can do to achieve this ?
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mfragmentManager = getActivity().getSupportFragmentManager();
mhandler=new Handler(this);
mLvAllDeals = (GridView) mview.findViewById(R.id.xLvAllDeals);
mLvAllDeals.setCacheColorHint(0);
mLvAllDeals.setOnItemClickListener(this);
new MyDealsAsyncTask().execute();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAlDealName = new ArrayList<AllDealsData>();
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
if(arg0==mLvAllDeals)
{
position = arg2;
AllDealsData bean;
bean = mAlDealName.get(position);
Fragment frag = getFragmentManager().findFragmentById(R.id.inner_content2);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
if (!frag.getTag().equals("dealsinfo"))
{
Bundle args = new Bundle();
args.putString("dealid", bean.getId());
mdealinfo.setArguments(args);
ft.replace(R.id.inner_content2, mdealinfo, "dealsinfo");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
}
}
}
When performing transactions in fragments, onCreateView() and onActvityCreated() will be called again but it wont be called onCreate() method. So maintain data in onCreate() method. If data is already loaded, set directly to adapter as well as loading webservices data manage it using some extra flag.
For more information on fragment life cycle refer this link
Related
I'm currently trying to programmatically add a fragment which has a view that I need to initializate immediately after the fragment is created. I tried to use FragmentManager.executePendingTransactions() right after FragmentTransition.commit(), but it doesn't work as it supposed to. I've made a research and found this, so I realized that FragmentManager.executePendingTransactions() doesn't work from onCreate() and then put code to onStart(), but it still doesn't work. Although in my case it's called from onItemClickListener(), I don't think it makes any difference. Here's my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.vk_music_list);
musicProgressBar = new MusicProgressBar();
listView = (ListView) findViewById(R.id.listView);
}
#Override
protected void onStart() {
super.onStart();
listView.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String audioUrl = ((VKApiAudio) parent.getAdapter().getItem(position)).url;
serviceIntent.putExtra("audioUrl", audioUrl);
//Inflate music progress bar
fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragment = fragmentManager.findFragmentById(R.id.musicBarContainer);
if(fragment == null) {
fragmentTransaction.add(R.id.musicBarContainer, musicProgressBar)
.setTransition(R.anim.move_from_the_bottom)
.commit();
}
//This guy doesn't work
fragmentManager.executePendingTransactions();
//Never get into this, because fragment is always == null
if(fragment != null) {
SeekBar seekBar = (SeekBar) fragment.getView().findViewById(R.id.progressBar);
seekBar.setMax(((VKApiAudio) parent.getAdapter().getItem(position)).duration);
}
startService(serviceIntent);
}
Alright, I finally found out what the issue is. The reason of the problem is that neither fragmentTransaction.commit() nor fragmentManager.executePendingTransactions() change reference that is stored in fragment variable. Therefore, after executePendingTransactions() I need to call findFragmentById() again, so reference that it stores will refer to the created fragment. Here's a working code:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String audioUrl = ((VKApiAudio) parent.getAdapter().getItem(position)).url;
serviceIntent.putExtra("audioUrl", audioUrl);
//Inflate music progress bar
fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragment = fragmentManager.findFragmentById(R.id.musicBarContainer);
if(fragment == null) {
fragmentTransaction.add(R.id.musicBarContainer, musicProgressBar)
.commit();
}
//Force to create fragment without scheduling so it's not necessarily to wait until it get scheduled
fragmentManager.executePendingTransactions();
//This is what I needed
fragment = fragmentManager.findFragmentById(R.id.musicBarContainer);
//Set song duration as a seekBar's maximum
if (fragment != null) {
SeekBar seekBar = (SeekBar) fragment.getView().findViewById(R.id.progressBar);
seekBar.setMax(((VKApiAudio) parent.getAdapter().getItem(position)).duration);
}
startService(serviceIntent);
}
I hope it will be helpful for somebody.
I'm trying to figure out how to save user inputted data on a fragment if they leave it and come back. I have one Activity that several Fragments work off of. All the examples I find are saving the state when leaving the Fragment and Activity. I'm never leaving the Activity; therefore onSaveInstanceState within the Fragment is never called. onPause is called, but I'm unable to figure out how to save the state within there.
This app displays a list of tickets. When the user taps a ticket, it grabs preliminary information from the local DB for read only fields and allows the user to input the ticket information before submitting. I'm trying to allow a user to tap on a ticket, enter data, leave and come back to that ticket without losing information entered.
Out of all the examples I've studied on this, it seems to me I can use Fragmenttransaction to save the Fragment's ID. Below is the main Activity that all fragments are attached to:
public class Activity_Main extends Activity
implements Fragment_OpenTickets.INT_OnOpenTicketSelectedListener,
Fragment_SubTickets.INT_OnSubTicketSelectedListener,
Fragment_Ticket.INT_SubmitNewTicket {
DBController dbc;
Fragment fr;
boolean gps_enabled = false;
boolean network_enabled = false;
HashMap<String, String> addInfo;
RadioButton btn_radio_open;
RadioButton btn_radio_submitted;
RadioButton btn_radio_settings;
String ticketDate, ticketTime;
int m, d, y, hr, min;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_radio_open = (RadioButton)findViewById(R.id.radio_open);
btn_radio_submitted = (RadioButton)findViewById(R.id.radio_submitted);
btn_radio_settings = (RadioButton)findViewById(R.id.radio_settings);
dbc = new DBController(this);
if (dbc.checkCredentials() != null) {
fr = new Fragment_OpenTickets();
} else {
fr = new Fragment_Settings();
btn_radio_open.setChecked(false);
btn_radio_submitted.setChecked(false);
btn_radio_settings.setChecked(true);
}
FragmentManager fm = getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_place, fr);
ft.addToBackStack(null); // For back button action.
ft.commit();
// Start scheduler service.
this.startService(new Intent(this, Service_Send.class));
// Start GPS service.
startGPS();
}
/**
* Top menu buttons.
*/
public void selectFrag(View view) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
switch (view.getId()) {
case R.id.radio_open:
//fr = new Fragment_OpenTickets();
ft.replace(R.id.fragment_place, new Fragment_OpenTickets());
ft.addToBackStack(null);
btn_radio_submitted.setChecked(false);
btn_radio_settings.setChecked(false);
ft.commit();
break;
case R.id.radio_submitted:
//fr = new Fragment_SubTickets();
ft.replace(R.id.fragment_place, new Fragment_SubTickets());
ft.addToBackStack(null);
btn_radio_open.setChecked(false);
btn_radio_settings.setChecked(false);
ft.commit();
break;
case R.id.radio_settings:
//fr = new Fragment_Settings();
ft.replace(R.id.fragment_place, new Fragment_Settings());
ft.addToBackStack(null);
btn_radio_open.setChecked(false);
btn_radio_submitted.setChecked(false);
ft.commit();
break;
}
}
/**
* Open ticket selection action.
*/
public void onOpenTicketSelected(HashMap position) {
// Create fragment and give it an argument for the selected ticket.
fr = new Fragment_Ticket();
Bundle args = new Bundle();
args.putSerializable("HashMap", position);
fr.setArguments(args);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_place, fr);
ft.addToBackStack(null); // For back button action.
ft.commit();
}
/**
* Submitted ticket selection action.
*/
public void onSubTicketSelected(HashMap position) {
// Create fragment and give it an argument for the selected ticket.
fr = new Fragment_SubTicket();
Bundle args = new Bundle();
args.putSerializable("HashMap", position);
fr.setArguments(args);
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_place, fr);
fragmentTransaction.addToBackStack(null); // For back button action.
fragmentTransaction.commit();
}
Any help will be very appreciated. If I need to post more code then please let me know. Thank you!
I think you should store ticket info in your Activity when users leave the fragment and get the info back and display it when you come back.
In Activity_Main class, you create 2 methods:
public void saveTicketInfo(TicketInfo info) {
// save info here
}
And:
public TicketInfo getTicketInfo() {
// get info here
}
In your fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
// get ticket info and display it
Activity_Main mainActivity = (Activity_Main)getActivity();
TicketInfo info = mainActivity.getTicketInfo();
if (info != null) {
// handle display info here
}
...
}
#Override
public void onDestroyView() {
TicketInfo info = new TicketInfo();
// get info from view and store in the object
Activity_Main mainActivity = (Activity_Main)getActivity();
mainActivity.saveTicketInfo(info)
super.onDestroyView();
}
I posted a lengthy detailed answer on SO # Passing data between fragments contained in an activity. Search for my answer on it. This is a safe way to pass data from Fragment to Activity. And then you can easily pass that data from Activity to the Fragment's constructor or public method.
I'm trying to display a ListFragment that'll show user comments from within another Fragment. For testing purposes, I'm calling the ListFragment using an "onClick" method from within the parent Fragment. However, I can't seem to get the ListFragment to show, as it has no "show" method. Are there any obvious problems with my code that I can fix?
This is the method called when I click a button to show the ListFragment.
private void showComments(JSONArray comments) {
ListFragment newFragment = CommentsFragment.newInstance(comments);
}
And here is the ListFragment itself.
public class CommentsFragment extends ListFragment {
public static CommentsFragment newInstance(JSONArray passedComments) {
CommentsFragment f = new CommentsFragment();
ArrayList<String> adapter = convertJSON(passedComments);
Bundle args = new Bundle();
args.putStringArrayList("adapter", adapter);
f.setArguments(args);
return f;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle args = new Bundle();
ArrayList<String> commentsArray = args.getStringArrayList("adapter");
ArrayAdapter<String> commentsAdapter = new ArrayAdapter<String>(
getActivity(), R.layout.comments_list,
commentsArray);
setListAdapter(commentsAdapter);
}
You have to commit the ListFragment with a FragmentManager, and also have a layout in the XML that will contain it.
Firstly add a FrameLayout to the XML where you want the ListFragment placed, and afterwards use getChildFragmentManager() to get a FragmentManager, that you can place the ListFragment with.
Try like this
private void showComments(JSONArray comments) {
ListFragment newFragment = CommentsFragment.newInstance(comments);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(android.R.id.content, newFragment);
fragmentTransaction.commit();
}
I have one Activity with two fragments.here i provide one back button in 2nd fragment programatically to goback to 1st fragment.
here my fragment1 code:
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
V = inflater.inflate(R.layout.lm_fragement, container, false);
listview = (ListView)V.findViewById(R.id.listView1);
url="http://victorysites.org/apps/SSPC/homeinfo.php?UDID=12341234";
JsonParsing json=new JsonParsing();
list=json.getData(url);
System.out.println("length :"+list.size());
listview.setAdapter(new MyAdapter(getActivity(),list));
final ProgressDialog waitdialog;
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Bundle data = new Bundle();
data.putString("name",""+arg2);
Fragment f;
f = new PM_Fragment();
f.setArguments(data);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(android.R.id.content, f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
});
Button bt=(Button)V.findViewById(R.id.button1);
bt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Bundle data = new Bundle();
data.putString("name","Venkat");
Fragment f;
f = new PM_Fragment();
f.setArguments(data);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(android.R.id.content, f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
});
return V;
}
}
Here my fragment2 code:
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
f=new PM_Fragment();
V = inflater.inflate(R.layout.pm_fragment, container, false);
Bundle bundle = this.getArguments();
String myInt = bundle.getString("name");
System.out.println("NAME"+myInt);
TextView tv=(TextView)V.findViewById(R.id.portrait_message);
tv.setText(myInt);
Button bt=(Button)V.findViewById(R.id.button1);
bt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
/*Fragment f=new PM_Fragment();
getActivity().getSupportFragmentManager().beginTransaction().remove(f).commit();*/
//getActivity().getFragmentManager().beginTransaction().remove(this).commit();
getFragmentManager().popBackStack();
}
});
return V;
}
}
its working fine,but the problem is it reloads the previous(1st fragment) screen.But i don't want reload the page,i want its working like default back button in emulator.
Anyone can give me an idea. Thanks in advance.
When using fragments in your app, individual FragmentTransaction objects may represent context changes that should be added to the back stack. If you are implementing a master/detail flow on a handset by swapping out fragments, you should ensure that pressing the Back button on a detail screen returns the user to the master screen. To do so, call addToBackStack() before you commit the transaction:
// Works with either the framework FragmentManager or the
// support package FragmentManager (getSupportFragmentManager).
getSupportFragmentManager().beginTransaction()
.add(detailFragment, "detail")
// Add this transaction to the back stack
.addToBackStack()
.commit();
*When there are FragmentTransaction objects on the back stack and the user presses the Back button, the FragmentManager pops the most recent transaction off the back stack and performs the reverse action (such as removing a fragment if the transaction added it).*
Note: You should not add transactions to the back stack when the transaction is for horizontal navigation (such as when switching tabs) or when modifying the content appearance (such as when adjusting filters). For more information, about when Back navigation is appropriate, see the Navigation design guide.
ADDED
If your application updates other user interface elements to reflect the current state of your fragments, such as the action bar, remember to update the UI when you commit the transaction. You should update your user interface after the back stack changes in addition to when you commit the transaction. You can listen for when a FragmentTransaction is reverted by setting up an FragmentManager.OnBackStackChangedListener:
getSupportFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
// Update your UI here.
}
});
Please refer this link for more details
I can store the value in one variable. Now I want pass that variable into a fragment
Using the code below, I am able to load fragments:
public class AndroidListFragmentActivity extends Activity {
Fragment2 f2;
public static String itemname;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.apetiserfragement);
itemname=getIntent().getStringExtra("itemname");
Bundle args=new Bundle();
args.putString("itemname", itemname);
f2=new Fragment2();
f2.setArguments(args);
}
} /* (Here I load fragment using xml page) itemname */
The output is splitted into 2 windows one for extend for listfragment (for listview) and one for fragments.
Fragment2.xml
public class Fragment2 extends Fragment {
String itemname;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
System.out.println(getArguments().getString("itemname"));
return inflater.inflate(R.layout.fragment2, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
}
AndroidListFragmentActivity in this class itemname I want pass Fragment2.class.. please help me
If both fragment are on other activity then can use intent
if on same activity then can do operation on that particular activity
as in this link
see onListItemClick of class TitlesFragment
**
* Helper function to show the details of a selected item, either by
* displaying a fragment in-place in the current UI, or starting a
* whole new activity in which it is displayed.
*/
void showDetails(int index) {
mCurCheckPosition = index;
if (mDualPane) {//<---------------------f on same activity then can do operation on that particular fragment
// We can display everything in-place with fragments, so update
// the list to highlight the selected item and show the data.
getListView().setItemChecked(index, true);
// Check what fragment is currently shown, replace if needed.
DetailsFragment details = (DetailsFragment) //<------------------------see use getFragmentManager
getFragmentManager().findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != index) {
// Make new fragment to show this selection.
details = DetailsFragment.newInstance(index);
// Execute a transaction, replacing any existing fragment
// with this one inside the frame.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, details);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
} else { //<----------If both fragment are on other activity then can use intent
// Otherwise we need to launch a new activity to display
// the dialog fragment with selected text.
Intent intent = new Intent();
intent.setClass(getActivity(), DetailsActivity.class);
intent.putExtra("index", index);
startActivity(intent);
}
See this response here : data sharing between fragments and activity in android