Android - Blank fragment when returning from backstack - android

I have a view that shows a List of Properties, at the bottom of the screen there's a button that opens a fragment containing a MapView.
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.find_property_btn_map:
PropertyMapFragment fragment = PropertyMapFragment.newInstance(false, null);
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.replace(((ViewGroup) getView().getParent()).getId(), fragment, PropertyMapFragment.class.getSimpleName())
.commit();
break;
}
}
The onCreateView method for my Properties fragments is as follows
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.fragment_properties_list, container, false);
getmBtnMap().setOnClickListener(this);
getmBtnSaveSearch().setOnClickListener(this);
getmBtnSort().setOnClickListener(this);
getmListView().setAdapter(getPropertyAdapter());
getmListView().setOnItemClickListener(this);
getmListView().setOnScrollListener(this);
getmListView().setScrollingCacheEnabled(false);
searchProperties();
return mRootView;
}
searchProperties(); takes care of calling a Web Service and filling the ArrayAdapter.
The thing is that, when I open the MapFragment and then press the back button, my Property fragment is blank and the buttons do not respond to onClick events.
I tried debugging and saw that onCreateView() is being called when coming back to Property fragment, but the buttons are no longer working and the listview is nowhere to be seen.
What am I doing wrong?

If you are trying to launch that web view from a fragment, then try to use add fragment instead of replace.
For example :
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.replace(YOUR_CONTAINER_ID, fragment, PropertyMapFragment.class.getSimpleName())
.commit();
The code above is replace that fragment container with the new one and not adding that fragment on top of that. So when you do a replace fragment with that ID, it just replaces that view with new one.
Now,
Same code but with add:
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.add(YOUR_CONTAINER_ID, fragment, PropertyMapFragment.class.getSimpleName())
.commit();
Now, that web view fragment that you have will be added to the view/fragment and now when you press back from that web view, you previous fragment will be visible.
Just make sure that that the ID you are replacing is the same as the one in which you have all the other properties.
Maybe i misinterpreted the question so please correct me in that context.
Hope this helps.

addToBackStack() <--dont include this for your first fragment.-->
if(getSupportFragmentManager().getBackStackEntryCount() !=1){
fragmentTransaction.addToBackStack(null);
}

Related

Android DetailsFragment transitions on DialogFragment do not work

I am following android tv tutorials from here:
Now I am stuck on DetailsFragment. In these demos is DetailsFragment set like a content of VideoDetailsActivity. When I start this new activity from main activity then I see nice animations(or transitions) belong to DetailsFragment.
But, In my case, I really won't go away from the main activity. I want to stay there. So I created DialogFragment and I set DetailsFragment like its content.
However, I can't get work these animations (transitions). Detail is shown, but there are none transitions.
The original example creates Bundle object and sets it like a second parameter for startActivity of activity which holds DetailsFragment. Seems that's the key to getting work transitions. See:
Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
getActivity(),
((ImageCardView) itemViewHolder.view).getMainImageView(),
VideoDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
getActivity().startActivity(intent, bundle);
But how to do it for DialofFragment? I tried to create the same Bundle object and then I set it this way for DialogFragment:
fragmentDialog.setArguments(bundle);
fragmentDialog.show(getSupportFragmentManager(),"DetailsDialog");
But it won't work. I debugged DetailsFragment and in this way appropriate callbacks for onEntranceTransitionPrepare, onEntranceTransitionStart, onEntranceTransitionEnd are not called.
Then I tried to set the shared element in onCreateView of my FragmentDialog:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.details, parent, false);
detailFragment = new MyDetailsFragment();
((ImageCardView) itemViewHolder.view).getMainImageView().setTransitionName("transitionName");
getChildFragmentManager().beginTransaction()
.add(R.id.container, detailFragment)
//.addToBackStack(createItemFragment.TAG)
.addSharedElement(((ImageCardView) itemViewHolder.view).getMainImageView(), "??? what here")
.addToBackStack("ProfileMenuFragment")
.commit();
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
return view;
}
Now are callbacks called, but I still don't see transitions... Truly, I do not know what should I place like a parameter for setTransitionName of my card view or second parameter for addSharedElement. Maybe that's problematic. ItemViewHolder is shared element between two fragments (item of browsefragment and MyDetailsFragment).
If it can't work with DialogFragment then I can switch browsefragment and MyDetailsFragment on the same activity. But I really want these animations and I must stay on the same activity
Can someone help me?
EDIT :
I try to replace browsefragment and MyDetailsFragment with this code, but transitions are still not displayed.
if (detailFragment == null) {
detailFragment = new MyDetailsFragment();
}
ImageView logo = ((ImageCardView) itemViewHolder.view).getMainImageView();
logo.setTransitionName("transitionName");
context.getFragmentManager()
.beginTransaction()
.addSharedElement(logo, logo.getTransitionName())
.replace(android.R.id.content, detailFragment, "MyDetailFragment")
.addToBackStack("MyBrowseFragment")
.commit();
I set manually logo.setTransitionName because else it crashes. I think this is not correct way. DetailsFragment contains all transitions what I want. I must only somehow start them

Fragment button not opening new activity

I've incorporated a horizontal slide navigation component (which required making the class extend Fragment). The slide part works fine. Here i have respective onClick() buttons which open a new activity. If I add a button into one of those activities I'm not finding a way to have the displayed activity subsequently refresh. I would think inflating an activity from a button within a fragment would be possible but anything I try stops the emulator.
There's not much to my code so far, so I'm not going to clutter my question with the associated layout part. Any help is certainly appreciated.
Fragment #1’s Java code
public class TasksFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tasks, container, false);
Button ID = (Button) rootView.findViewById(R.id.button_create_appraisal_rpt);
ID.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AppraisalReportActivity appraisalRptAct = new AppraisalReportActivity();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.child_fragment, appraisalRptAct);
fragmentTransaction.setTransition(fragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return rootView;
}
}
Fragment #1 (portion), which has the button that should initiate aa refresh of this Fragment #1 with Fragment #2
Fragment #2 that's to supersede/refresh the previous fragment when Fragment #1's button is clicked
I don't really understand what you mean. Do you want to click Button in Fragment to jump to another Activity?
If it is,I think maybe you can try use getActivity() to make Activity are working.
for example:
getActivity().startActivity(new Intent(getActivity(),Activity.class))
I hope my answer will help you

RecyclerView is empty when restoring fragment from backStack

I have a RecyclerView in a Fragment and initially is hidden. When user clicks a button, I set visibility to true for the RecyclerView and I display some data I have on an ArrayList.
The problem starts when I move another fragment on top (I add the previous fragment with the RecyclerView in the backStack) : if I click back from the new fragment the previous fragment (the one with the RecyclerView ) is visible and in onCreateView() I log the values of the dataSet I'm using for the recyclerView and everything is there, but the recyclerView is empty ( only footer item is presented ).
If we call RvFragment the Fragment with the RecyclerView and NextFragment the fragment that comes to the backstack and then leaves the schema is :
(back pressed)
RvFragment ----------> NextFragment ------------> RvFragment
and here's the code from onCreateView() :
#Nullable
#Override
public View onCreateView(final LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_photo_comments, container, false);
ButterKnife.bind(this, view);
Timber.i("onCreateView data.size == %d", commentArrayList.size());
setToolbarTitle();
Picasso.with(getActivity())
.load(photo)
.placeholder(R.drawable.ic_timeline_image_placeholder)
.centerCrop()
.fit()
.into(ivPhoto);
if (hasCommentsVisible) {
Timber.i("comments are visible!! and dataSize == %d", commentArrayList.size());
llFlagsCommentsContainer.setVisibility(View.GONE);
rvCommentsList.setVisibility(View.VISIBLE);
}
tvComments.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
hasCommentsVisible = true;
llFlagsCommentsContainer.setVisibility(View.GONE);
rvCommentsList.setVisibility(View.VISIBLE);
}
});
initRecyclerView();
return view;
}
You can see with the log statements in the code above I can confirm the data exist. Thanks!
I'm not sure I understand how you set up your fragment stack but just to be sure : onCreateView won't be called again when you press the back button if the fragment is still on the stack.
https://developer.android.com/training/basics/fragments/fragment-ui.html#Replace
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
Only onStart() will.
If you want onCreateView to be called again then you need to use the
FragmentTransaction.replace(NextFragment)
without the addToBackStack() but it means the whole fragment will be recreated from scratch. Probably not what you want, especially if you are getting your data from a webservice.
Alternatively, to fully recreate your fragment every time you come back to it, you can simply remove it entirely :
FragmentTransaction.remove(RvFragment)
and then push your next fragment

Fragment: reloading on back press

I am using Fragments and Activity extended by AppCompatActivity in an application.
Working:
I have two fragments "Dashboard" and "Order". I am replacing fragment after clicking "Order Button" from Dashboard Fragment, and coming back to "Dashboard Fragment" after pressing back button.
Problem
I have called an API on onCreateView() of Dashboard Fragment. When I press back from Order Fragment then I come to "Dashboard Fragment" the it recall the API. I don't want to recall the API if I come to the fragment by back press.
Thanks in advance.
Code to replace dashboard fragment with order fragment
// Click event of Order
#OnClick(R.id.ll_order)
void openOrder() {
if (isOrderNotClicked) {
OrderFragment fragment = new OrderFragment();
this.getFragmentManager().beginTransaction().replace(R.id.flContent, fragment, "Order").addToBackStack(null).commit();
isOrderNotClicked = !isOrderNotClicked;
}
}
I did had same problem so i solved by `View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (view == null) {
//inflate layout and codes
}
return view;
}` but i dont know it is the best solution

How to reuse fragment's view in Android?

I am creating a Fragment Activity with tabs. Now whenever i select a tab, corresponding fragment gets recreated and its
onCreateView()
method is called.
But what i want is to reuse the view of the fragment so that whenever a tab is selected system does not call
onCreateView()
of fragment instead it shows the previous view of the fragment if it exists.
Please reply soon.
You may want to show and hide the fragments instead of adding and removing them when selecting a tab.
For example:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (frag.isAdded()) {
transaction.show(R.id.layout, frag);
} else {
transaction.add(R.id.layout, frag);
}
transaction.commit();
setOffScreenPageLimit() method can be used to set how many fragments you want to keep alive even if they are not visible to the user.
Try this, it works for screen rotation and should work for your situation as well:
1) When you add fragment for the first time, create it with name parameter:
getSupportFragmentManager()
.beginTransaction()
.replace(<containerID>, <fragment>, YOUR_FRAGMENT_NAME_CONST)
.commit();
2) When you need to find it:
YourFragmentType fragment;
fragment = (YourFragmentType) getSupportFragmentManager()
.findFragmentByTag(YOUR_FRAGMENT_NAME_CONST);
if (fragment != null){
//TODO set data to the existing fragment
}
else{
//TODO create and initialize your fragment
}
Edit:
You should differentiate Fragment object creation and onCreateView() being called.
It's right that you should avoid unnecessary object creation and so reuse fragments.On the other hand (as for my experience) it's better to adhere Android's onCreateView() politics to guarantee consistent user experience.
If you really want to save CPU time and avoid re-inflating complicated view (and settle all issues yourselves) - you may just check it is null like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// View
if (mView == null) {
mView = inflater.inflate(R.layout.your_fragment, container, false);
...
}
...
}

Categories

Resources