EventBus in viewPager fragment issue - android

I have thee fragments in viewpager, Fragment1, Fragment2, and Fragment3.
fragment1 has a button and when onclick it setEnable(true) a button in fragment2 and the button in fragment 2 setEnable(true) a button3 in fragment3
All seem to work fine, but when I navigate through the fragments when passing from fragment 3 to fragment 1, fragment3 lose the information and the button comes back to its initial state -setEnable(false) as in the beginning, but fragment1 and fragment2 still work fine and don't lose the information when I navigate through all the fragments in viewpager.
How can I keep the information in fragment3 while navigating?
Here is my code:
fragment1
public class FragmentUno extends Fragment {
Button btnClick;
private EventBus bus = EventBus.getDefault();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_uno, container, false);
btnClick = (Button)rootView.findViewById(R.id.button1);
btnClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
bus.post(new EventoBotton());
System.out.println("saliendoooo");
}
});
return rootView;
}
}
fragment2
public class FragmentDos extends Fragment {
private EventBus bus = EventBus.getDefault();
private EventBus bus2 = EventBus.getDefault();
Button btnNext;
#Override
public void onResume() {
super.onResume();
bus.register(this);
}
#Override
public void onPause() {
super.onPause();
bus.unregister(this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_dos, container, false);
btnNext = (Button)rootView.findViewById(R.id.btnF2);
btnNext.setEnabled(false);
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//HERE I POST EVENT TO SEND TO FRAG 3
bus2.post(new EventoDos());
}
});
return rootView;
}
#Subscribe
public void reenvio(EventoBotton ev) {
btnNext.setEnabled(true);//HERE RECEIVE EVENT FORM FRAG 1
}
}
Fragment3
public class FragmentTres extends Fragment {
TextView txtDos;
Button btnDis;
private EventBus bus2 = EventBus.getDefault();
#Override
public void onResume() {
super.onResume();
bus2.register(this);
}
#Override
public void onPause() {
super.onPause();
bus2.unregister(this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tres, container, false);
txtDos = (TextView)rootView.findViewById(R.id.txtCambio);
btnDis = (Button)rootView.findViewById(R.id.buttonF2);
btnDis.setEnabled(false);
return rootView;
}
#Subscribe
public void actualizar(EventoDos eventoDos) {
System.out.println("estamos aquiiii"); // Here I receive the event from frag 2
txtDos.setText("hola mundo");
btnDis.setEnabled(true);
}
}
These are my POJO events
public class EventoBotton {
public EventoBotton() {}
}
The other event
public class EventoDos {
public EventoDos() {}
}
I'm using eventbus 3.0 with my SDK 21.
All works fine but when I slip through the view pager, if I slide from 3 to 2, the information is still there in frag3. But when I slide from 3 to 2 and reach 1 when I come back to 3, the information is lost. That is to say, the button in frag 3 come back to its original state (enabled false) Why?? How can I persist the changes in all the navigation in the viewpager?

You can try using:
setOffscreenPageLimit(int limit) // In your case, limit = 2
on the ViewPager object which sets the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state.

Related

Fragment goes blank when returning from another activity

There are two activities in my app:
MainActivity (containing 3 fragments)
FragmentHome
FragmentOrders
FragmentAccount
AccountEditActivity
The code to set fragments in MainActivity is this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
// set Home as the default fragment
setFragment(FragmentMainHome.getInstance());
}
private void setFragment(Fragment fragment){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, fragment);
transaction.commit();
}
The code for FragmentAccount is:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_activity_main_account, container, false);
layout = rootView.findViewById(R.id.layout_fragment_main_account);
etName = (EditText) layout.findViewById(R.id.etNameLabelValue);
etEmail = (EditText) layout.findViewById(R.id.etEmailLabelValue);
etGender = (EditText) layout.findViewById(R.id.etGenderLabelValue);
etPhoneNumber = (EditText) layout.findViewById(R.id.etPhoneNumberLabelValue);
btnEditAccount = (ImageButton) layout.findViewById(R.id.btnEditAccount);
btnManageAddresses = (ImageButton) layout.findViewById(R.id.btnAccountManageAddresses);
btnManageAddresses.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
btnEditAccount.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
return rootView;
}
The code for FragmentOrders is:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_activity_main_order_history, container, false);
layout = rootView.findViewById(R.id.layout_fragment_main_order_history);
lvOrders = (ListView) layout.findViewById(R.id.lvOrders);
tvNoOrdersFound = (TextView) layout.findViewById(R.id.tvNoOrdersFound);
final SwipeRefreshLayout pullToRefresh = rootView.findViewById(R.id.swipe_refresh_layout_order_history);
pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// load orders
pullToRefresh.setRefreshing(false);
}
});
lvOrders.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
return rootView;
}
and similar kind of code goes for FragmentHome
The Problem
I can move between fragments and the view works fine.
Now from Account fragment, I move to AccountEditActivity
I do some update there and come back to MainActivity by pressing hardware back button
FragmentHome is displayed fine but when I click on FragmentAccount, screen goes blank
Now, if I click on Home fragment and click FragmentAccount again, it displays fine.
What is wrong here?
better use viewpager in your activity to show the fragments
it's easy to manage while using viewpagers
have a look at the link
Fragments in viewpager
and in your case just move this code from onCreate to onResume
setFragment(FragmentMainHome.getInstance());
for understanding better have a look at the lifecycle of activity in android
Activity life cycle

Used to Add a fragment A to fragment B and go back with the result to fragment A [duplicate]

I am developing an Android application. I have a requirement like there is a button in fragment 1, when a user clicks that button result should be displayed in fragment 2. While loading the activity both fragments is attached. Here is my try:
In main activity:
public void dsp(String str) {
secondfragment f2=new secondfragment();
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
f2.setArguments(bundle);
}
In first fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragone, container,false);
Button btn = (Button) v.findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
m.dsp("clicked");
}
});
return v;
}
In second fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragtwo, container,false);
tv= (TextView) v.findViewById(R.id.textView1);
tv.setText(this.getArguments().getString("name"));
return v;
}
When communicating from Fragment to Fragment you use an interface to pass data to the Activity which in turn updates the fragment you want to change.
For Example:
In Fragment 1:
public class FragmentOne extends Fragment{
public Callback mCallback;
public interface Callback{
void onUpdateFragmentTwo(String message);
}
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
mCallback = (Callback) activity;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragone, container,false);
Button btn = (Button) v.findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mCallback.onUpdateFragmentTwo("clicked");
}
});
return v;
}
}
then in main Activity implement the interface:
public class MainActivity extends AppCompatActivity implements Callback{
FragmentTwo fragmentTwo;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// ... Load views or perform logic
// ... Load Fragment Two into your container
if(savedInstanceState == null){
fragmentTwo = FragmentTwo.newInstance(new Bundle()); // use real bundle here
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_holder, fragmentTwo, "Frag2").commit();
}
}
// Interface method
#Override
public void onUpdateFragmentTwo(String message){
// Call activity method with the argument
if(fragmentTwo != null){
fragmentTwo.updateFragmentTwo(message);
}
}
}
Update
In your second fragment I typically use a static newInstance(Bundle args) method to initialize and then would use a public method to communicate from the Activity to the Fragment for example:
public class FragmentTwo extends Fragment{
public static FragmentTwo newInstance(Bundle args){
FragmentTwo fragment = new FragmentTwo();
fragment.setArguments(args);
return fragment;
}
//... Class overrides here onCreateView etc..
// declare this method
public void updateFragmentTwo(String updateText){
// .. do something with update text
}
}
Thats it, happy coding!
Here you have what the Android Documentation says about Communicating Between Fragments. Here you'll have all the necessary steps to make two or more fragments communicate securely :)

How to Enable/ Disable button from another fragment in android?

i have an activity with 4 fragments from fragment number 1 I want to enable an existing button (that is disable) on fragment 3, when i click in my button in fragment1. this is my attempt:
fragment 1:
public class FragmentEvolucion extends Fragment {
//btnGuardar is in fragment1, the others are in fragment 3 and 4
Button btnGuardar, btnHabilitarMed, btnHabilitarImc;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_evolucion, container, false);
btnGuardar=(Button)rootView.findViewById(R.id.btnGuardarEvolucion);
btnHabilitarMed=(Button)rootView.findViewById(R.id.btnGuardarMedicacion);
btnHabilitarImc=(Button)rootView.findViewById(R.id.btnGuardarDiagnostico);
btnGuardar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btnHabilitarMed.setEnabled(true);
btnHabilitarImc.setEnabled(true);
}
});
this give me an error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setEnabled(boolean)' on a null object reference
How can i access the button and change it status enabled correctly?
First of all, create a interface.
UpdateButtonListener.java
public interface UpdateButtonListener {
void onUpdate(boolean status);
}
Now in fragment 3, implement interface to class
public class Fragment3 extends Fragment implements UpdateButtonListener{
public static UpdateButtonListener updateButton;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment3, container, false);
updateButton = this;
return view;
}
#Override
public void onUpdate(boolean status) {
// here set the functionality of button whether to disable or not .
if(status){
btnHabilitarMed.setEnabled(true);
btnHabilitarImc.setEnabled(true);
}
}
}
Now in first fragment.
btnGuardar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment3.updateButton.onUpdate(true);
}
Like-wise do for other's.

Communication between two fragment from different activity?

I have two activities in my app. In MainActivity I am loading 2 fragments Fragment1 and Fragment2. From Fragment1 i am jumping to Fragment2 and from Fragment2 I am jumping to Activity2 which contains Fragment2_1 From Fragment 2_1 I want to jump back to Fragment2 in MainActivity but I am getting an error when I try to do this.
I want to know is it possible to jump from 1 activity fragment to another activity fragment?
My code is:
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
Fragment fragment1=new Fragment1();
fragmentTransaction.replace(R.id.mainContainer,fragment1,"MainActivity");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
Fragment1.java:
public class Fragment1 extends Fragment {
public Fragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view=inflater.inflate(R.layout.fragment_fragment1, container, false);
Button buttonfrag1=(Button)view.findViewById(R.id.buttonfrag1);
buttonfrag1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragmentManager=getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
Fragment2 fragment2 = new Fragment2();
fragmentTransaction.replace(R.id.mainContainer,fragment2,"Fragment1");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return view;
}
Fragment2.java
public class Fragment2 extends Fragment {
public Fragment2() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2, container, false);
Button buttonfrag2=(Button)view.findViewById(R.id.buttonfrag2);
buttonfrag2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(getActivity(),Activity2.class);
startActivity(intent);
}
});
return view;
}
}
Activity2.java
public class Activity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
FragmentTransaction fragmentTransaction=getSupportFragmentManager().beginTransaction();
Fragment2_1 fragment2_1=new Fragment2_1();
fragmentTransaction.replace(R.id.frag2_1,fragment2_1,"Activity2");
fragmentTransaction.commit();
}
}
Fragment2_1.java
public class Fragment2_1 extends Fragment {
public Fragment2_1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2_1, container, false);
Button buttonfrag2_1=(Button)view.findViewById(R.id.buttonfrag2_1);
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
Fragment2 fragment2=new Fragment2();
fragmentTransaction.replace(R.id.mainContainer,fragment2,"frag2_1");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return view;
}
}
All code works fine but when I want to move from Fragment2_1 to Fragment1 my app crashes with an exception :
java.lang.IllegalArgumentException: No view found for id 0x7f0b0059 (saleskit.orbitsys.com.fragmentdemo:id/mainContainer) for fragment Fragment2{29eb9c90 #1 id=0x7f0b0059 frag2_1}
try this: in Fragment2_1
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.putExtra("frag", "fragment2");
startActivity(intent);
}
});
Now in Mainactivity onResume() load your desired fragment in maincontainer
in MainActivity
#Override
public void onResume(){
super.onResume();
Intent intent = getIntent();
if(intent.getExtras() != null)
{
String frag = intent.getStringExtra("frag");
}
switch(frag){
case "fragment2":
//here you can load Fragment2 to your activity as usual;
fragmentManager.beginTransaction().replace(R.id.mainContainer, new Fragment2()).commit();
break;
}
}
In your Fragment2_1 within your second activity you are trying to place Fragment2 in the container R.id.mainContainer. Your code below :
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
Fragment2 fragment2=new Fragment2();
fragmentTransaction.replace(R.id.mainContainer,fragment2,"frag2_1");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
But since you are currently inside your second activity that container doesn't exist (it is part of your first activity). You need to either load your your MainActivity again or finish Activity2 by calling finish(). If you do the later android will by itself take you back to your MainActivity and since you moved to Activity2 from Fragment2 android will also remember that and show you Fragment2.
Your Fragment2_1 should look like this:
public class Fragment2_1 extends Fragment {
public Fragment2_1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2_1, container, false);
Button buttonfrag2_1=(Button)view.findViewById(R.id.buttonfrag2_1);
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().finish();
}
});
return view;
}
}
OR, If you just want to show Fragment2 in your second activity you can do something like this :
public class Fragment2_1 extends Fragment {
public Fragment2_1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_fragment2_1, container, false);
Button buttonfrag2_1=(Button)view.findViewById(R.id.buttonfrag2_1);
buttonfrag2_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
Fragment2 fragment2=new Fragment2();
fragmentTransaction.replace(R.id.frag2_1,fragment2,"frag2");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return view;
}
}
R.id.frag2_1 is the container where you need to replace the fragment.
Note that : You will still be in your second activity. Just the fragment will be replaced.

How can I close the fragment?

I am have Fragment on the Activity. Fragment has button. if i click on the button, Fragment must be close. How i am did this?
public class ItemFragment extends Fragment{
private ImageView btnApply;
private ClickButton clickButton = new ClickButton();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.item_info, container, false);
btnApply = (ImageView) rootView.findViewById(R.id.btnSendItem);
btnApply.setOnClickListener(clickButton);
return rootView;
}
private class ClickButton implements View.OnClickListener {
#Override
public void onClick(View v) {
if (R.id.btnSendItem == v.getId()) {
Toast.makeText(getActivity(),"CLOSE",Toast.LENGTH_LONG).show();
return;
}
}
}
}
There's no such thing like close the fragment, but you can remove the fragment from the stack. To pop the fragment use the following inside button click listener
getActivity().getFragmentManager().beginTransaction().remove(this).commit();
When this fragment is of type androidx.fragment.app.Fragment then this seems to work:
getActivity().getFragmentManager().popBackStack();
This pops the top visible fragment off the stack.

Categories

Resources