I have 3 fragments where 1 fragment makes changes to the other 2.
The problem is: When I rotate the screen background color and places of fragments 2 and 3 are restored.
I want to keep them without modifying AndroidManifest.xml.
Is it best to use onSaveInstanceState or setRetainInstance or both?
I found some other answers about retaining fragments but none of them were beneficial for my case.
FirstFragment
public class FirstFragment extends Fragment
{
private OnFragmentInteractionListener mListener;
private ChangeColorListener mCallBack;
private boolean clickCheck = false;
public FirstFragment() { }
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_first, container, false);
Button buttonOk = v.findViewById(R.id.button_ok);
Button btn = v.findViewById(R.id.button_replace);
buttonOk.setOnClickListener(v1 -> mCallBack.changeColor(R.color.black));
btn.setOnClickListener(v12 -> {
clickCheck = !clickCheck;
mListener.changeFragment(clickCheck);
});
return v;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState!=null) {
mCallBack =(MainActivity)getActivity();
mListener = (MainActivity)getActivity();
}
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
if (context instanceof ChangeColorListener) {
mCallBack = (ChangeColorListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement ChangeColorListener");
}
try {
mListener = (OnFragmentInteractionListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
}
SecondFragment
public class SecondFragment extends Fragment
{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_second, container, false);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
public void change(int color){
getView().setBackgroundColor(color);
}
}
ThirdFragment
public class ThirdFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_third, container, false);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
public void change(int color){
getView().setBackgroundColor(color);
}
}
setRetainInstance() is deprecated. ViewModel is recommended for retaining data across configuration changes.
Related
I have created an Activity which contains four Floating Button and a fragment which calls Activity's Floating button to make them visible/invisible but when I access these Floating Buttons from fragment it throws null pointer exception.
Activity Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
getInitialized();
fabSettings = (FloatingActionButton) this.findViewById(R.id.fabSetting);
fabStory = (FloatingActionButton) this.findViewById(R.id.fabStory);
fabImage = (FloatingActionButton) this.findViewById(R.id.fabImage);
fabVideo = (FloatingActionButton) this.findViewById(R.id.fabVideo);
}
Fragment Code:
#SuppressLint("RestrictedApi")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_all_community, container, false);
SessionManager sessionManager = new SessionManager(getActivity());
if(sessionManager.isLoggedIn()){
ActivityUser.fabSettings.setVisibility(View.VISIBLE);
ActivityUser.laySearchCode.setVisibility(View.VISIBLE);
ActivityUser.bottomLayout.setVisibility(View.VISIBLE);
tvCreateCommunity.setVisibility(View.VISIBLE);
}else{
MainActivity.fabSettings.setVisibility(View.VISIBLE);
MainActivity.bottomLayout.setVisibility(View.VISIBLE);
MainActivity.laySearchCode.setVisibility(View.VISIBLE);
((MainActivity) getActivity()).getSupportActionBar().setTitle("");
tvCreateCommunity.setVisibility(View.GONE);
}
}
Please help
Use this code
Fragment:
public class Fragment extends Fragment {
public interface onHideEventListener {
public void hideEvent(boolean isVisible);
}
onHideEventListener hideEventListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
hideEventListener = (onHideEventListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement onHideEventListener");
}
}
final String LOG_TAG = "myLogs";
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment2, null);
SessionManager sessionManager = new SessionManager(getActivity());
if(sessionManager.isLoggedIn()){
hideEventListener.hideEvent(false);
}else{
hideEventListener.hideEvent(true);
}
return v;
}
}
Activity:
public class MainActivity extends Activity implements onSomeEventListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
public void hideEvent(boolean isVisible) {
fabSettings.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
laySearchCode.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
bottomLayout.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
}
}
I am new to Android. Please excuse me if it's a silly question:
If i click on button of a Fragment - it has to trigger a test and show the result in other Fragment. So to make things simple, have written a code on button click as follows. It's not working. Please suggest.
My actual intent is to register a log.add BroadcastReceiver, so that anywhere any log error or debug is called, that message has to appear in the TestStatusFragment.
public class TriggerTestFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_trigger, container, false);
Button stopScheduler = (Button) view.findViewById(R.id.testButton);
stopScheduler.setOnClickListener((View sview) -> {
View teststatusView = inflater.inflate(R.layout.fragment_teststatus, container, false);
TextView textView = (TextView) teststatusView.findViewById(R.id.text_view);
textView.setText("test result....");
});
return view;
}
}
MainActivity.java
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new TriggerTestFragment(), "TRIGGERTEST");
adapter.addFragment(new TestStatusFragment(), "TEST STATUS");
viewPager.setAdapter(adapter);
}
Second Fragment:
public class TestStatusFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Context context = getContext();
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_teststatus, container, false);
return view;
}
}
Use interface to communicate between them.
Fragment One
public class FragOne extends Fragment {
EditText etxtName, etxtDesc;
Button btnSubmit;
String name, desc;
private OnFragmentInteractionListener mListener;
public FragOne() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_frag_one, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
etxtName = (EditText) view.findViewById(R.id.etxtName);
etxtDesc = (EditText) view.findViewById(R.id.etxtDesc);
btnSubmit = (Button) view.findViewById(R.id.btnSubmit);
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
name = etxtName.getText().toString().trim();
desc = etxtDesc.getText().toString().trim();
if(name == null || desc == null) {
Toast.makeText(getActivity(), "Both fields required", Toast.LENGTH_SHORT).show();
} else {
mListener.onFragmentInteraction(name, desc);
etxtName.setText("");
etxtDesc.setText("");
}
}
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(String name, String desc);
}
}
Fragment Two
public class FragTwo extends Fragment implements FragOne.OnFragmentInteractionListener{
TextView textView, textDesc;
public FragTwo() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_frag_two, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
textView = (TextView) view.findViewById(R.id.txtName);
textDesc = (TextView) view.findViewById(R.id.txtDesc);
}
#Override
public void onFragmentInteraction(String name, String desc) {
textView.setText(name);
textDesc.setText(desc);
}
}
Init fragments
fragOne = new FragOne();
fragTwo = new FragTwo();
PagerAdapter
public static class MyPagerAdapter extends FragmentPagerAdapter implements FragOne.OnFragmentInteractionListener{
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return fragOne;
case 1:
return fragTwo;
default:
return null;
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
return "Page " + position;
}
#Override
public void onFragmentInteraction(String name, String desc) {
fragTwo.onFragmentInteraction(name, desc);
}
}
MainActivity need implement onFragmentInteraction interface
public class MainActivity extends AppCompatActivity implements FragOne.OnFragmentInteractionListener{
static FragOne fragOne;
static FragTwo fragTwo;
MyPagerAdapter myPagerAdapter;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragOne = new FragOne();
fragTwo = new FragTwo();
viewPager = (ViewPager) findViewById(R.id.viewPager);
myPagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(myPagerAdapter);
}
#Override
public void onFragmentInteraction(String name, String desc) {
myPagerAdapter.onFragmentInteraction(name, desc );
}
public static class MyPagerAdapter extends FragmentPagerAdapter implements FragOne.OnFragmentInteractionListener{
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return fragOne;
case 1:
return fragTwo;
default:
return null;
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
return "Page " + position;
}
#Override
public void onFragmentInteraction(String name, String desc) {
fragTwo.onFragmentInteraction(name, desc);
}
}
}
You can read full article here https://www.mytrendin.com/passing-data-between-fragments/
I trying out Fragment and have a problem with OnClickListener. Anyone can help?
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frag_one frag1=new frag_one();
FragmentManager manager=getSupportFragmentManager();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.top,frag1,"");
transaction.commit();
}
}
frag_one.java
public class frag_one extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_frag_one,container,false);
}
public class calculator extends AppCompatActivity implements View.OnClickListener {
TextView get_result;
EditText get_num1;
EditText get_num2;
Button get_button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frag_one);
get_result=(TextView)findViewById(R.id.result);
get_num1=(EditText) findViewById(R.id.num1);
get_num2=(EditText) findViewById(R.id.num2);
get_button=(Button)findViewById(R.id.submit);
get_button.setOnClickListener(this);
}
public void onClick(View v) {
int num1=Integer.parseInt((get_num1.getText().toString()));
int num2=Integer.parseInt((get_num2.getText().toString()));
int sum=num1+num2;
get_result.setText(Integer.toString(sum));
}
}
}
When I run on normal activity without using Fragment. When i click the button, the calculation works. But when i move to Fragment, its not working. Please help! thx
You made a second Activity that uses the layout of the Fragment instead of actually placing the logic into the Fragment class....
public class frag_one extends Fragment implements View.OnClickListener {
TextView get_result;
EditText get_num1;
EditText get_num2;
Button get_button;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_frag_one,container,false);
get_result=(TextView)rootView.findViewById(R.id.result);
get_num1=(EditText)rootView.findViewById(R.id.num1);
get_num2=(EditText) rootView.findViewById(R.id.num2);
get_button=(Button)rootView.findViewById(R.id.submit);
get_button.setOnClickListener(this);
return rootView;
}
public void onClick(View v) {
// TODO: Check v.getId() == R.id.submit
int num1=Integer.parseInt((get_num1.getText().toString()));
int num2=Integer.parseInt((get_num2.getText().toString()));
int sum=num1+num2;
get_result.setText(Integer.toString(sum));
}
}
you not referring any view here, hope this will help you
public class ABC extends Fragment implements OnClickListener {
View view;
Context context;
Button btnClick;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, container, false);
return view;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = activity;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
btnClick = (Button) view.findViewById(R.id.btnClick);
btnClick.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnClick:
break;
default:
break;
}
}
}
In my MainActivity class I have view pager with 3 tab fragmentHome class, fragmentHot class and FragmentCategoryclass
Here is fragmentCategory class:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view;
view = inflater.inflate(R.layout.fragmentcategory, container, false);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.category_fragment, new TabCategoryFragment());
transaction.commit();
return view;
}
In TabCategoryFragment class, I have grid category news and when click item grid I called:
FragmentTransaction transaction = getFragmentManager().beginTransaction();
Bundle bundle = new Bundle();
bundle.putString("category", arrDataZone.get(position).getZone_name());
bundle.putString("zoneid", arrDataZone.get(position).getZone_id());
ListCategoryFragment myFrag = new ListCategoryFragment();
myFrag.setArguments(bundle);
transaction.replace(R.id.category_fragment, myFrag,"listFramgnet");
transaction.addToBackStack("grid_category");
transaction.commit();
Now I want call method in ListCategoryFragment from MainActivity or call method in ListCategoryFragment from FragmentCategory.
Because I try call method in FragmentCategory from MainACtivity with:
linearPlayer.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int number=viewPager.getCurrentItem();
Fragment fragment= adapter.getItem(number);
if (number==0) {
((FragmentHome)fragment).playAudioSerVice();
} else if(number==1) {
((FragmentHot)fragment).playAudioSerVice();
} else if( number==2) {
((FragmentNew)fragment).playAudioSerVice();
} else if( number==3) {
((FragmentCategory)fragment).playAudioSerVice();
}
}
});
and it ran. Please give me your idea or code to do it.
You can use Eventbus postSticky to resolve it,you can see the api, eventbus
I wrote a demo to simulate your case.Here is the code.
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main22);
getSupportFragmentManager().beginTransaction().replace(R.id.contaner,new MainActivityFragment()).commit();
EventBus.getDefault().register(this);
}
#Subscribe
public void changeFragment(ChangeFragmentEvent event) {
// get event from MainActivityFragment immediately--->EventBus.getDefault().post(new ChangeFragmentEvent());
getSupportFragmentManager().beginTransaction().replace(R.id.contaner,PlusOneFragment.newInstance()).commit();
}
#Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
MainActivityFragment:
public class MainActivityFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main22, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
View button = view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EventBus.getDefault().post(new ChangeFragmentEvent());//notify MainActivity change fragment
EventBus.getDefault().postSticky(new MEvent());//send a msg to PlusOneFragment,when it shown
}
});
}
}
PlusOneFragment:
public class PlusOneFragment extends Fragment {
public PlusOneFragment() {
}
public static PlusOneFragment newInstance() {
PlusOneFragment fragment = new PlusOneFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_plus_one, container, false);
return view;
}
#Subscribe(sticky = true)
public void getMEvent(MEvent event){
// get event from MainActivityFragment when PlusOneFragment show --->EventBus.getDefault().postSticky(new MEvent());
Toast.makeText(getActivity(),"Hello,there",Toast.LENGTH_SHORT).show();
}
#Override
public void onDetach() {
super.onDetach();
EventBus.getDefault().unregister(this);
}
}
I want to change the Fragment when i click the button. The fragments are in the same adapter/viewpager.
FROM THIS FRAGMENT:
public class LoginFragment extends Fragment {
TextView linkToRegister;
public static final LoginFragment newInstance()
{
LoginFragment mf = new LoginFragment();
Bundle bd = new Bundle(1);
mf.setArguments(bd);
return mf;
}
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState )
{
View v = inflater.inflate(R.layout.fragment_login, container, false);
linkToRegister = (TextView) v.findViewById(R.id.link_to_register);
linkToRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Change Fragment
}
});
return v;
}
}
TO THIS FRAGMENT:
public class RegisterFragment extends Fragment {
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final RegisterFragment newInstance()
{
RegisterFragment mf = new RegisterFragment();
Bundle bd = new Bundle(1);
mf.setArguments(bd);
return mf;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
View v = inflater.inflate(R.layout.fragment_register, container, false);
return v;
}
}
PagerAdapter:
public class WelcomePagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> Welcomefragments;
public WelcomePagerAdapter(FragmentManager fm, List<Fragment> Welcomefragments) {
super(fm);
this.Welcomefragments = Welcomefragments;
}
#Override
public Fragment getItem(int position) {
return this.Welcomefragments.get(position);
}
#Override
public int getCount() {
return this.Welcomefragments.size();
}
}
Activity:
public class WelcomeActivity extends AppCompatActivity {
ViewPager welcomeViewPager;
WelcomePagerAdapter welcomePagerAdapter;
List<Fragment> welcomeFragments;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
welcomeViewPager = (ViewPager) findViewById(R.id.viewPagerWelcome);
welcomeFragments = getWelcomeFragments();
welcomePagerAdapter = new WelcomePagerAdapter(getSupportFragmentManager(), welcomeFragments);
welcomeViewPager.setAdapter(welcomePagerAdapter);
}
public List<Fragment> getWelcomeFragments() {
List<Fragment> newFragment = new ArrayList<Fragment>();
newFragment.add(LoginFragment.newInstance());
newFragment.add(RegisterFragment.newInstance());
return newFragment;
}
}
Step 1: Define a callback interface in the Fragment and hook in the Activity when the Fragment attaches to it.
public class MyFragment extends Fragment {
public interface OnInteractionListener {
void doAction(); // Can include parameters here if needed
}
private OnInteractionListener listener;
#Override
public void onAttach(Context context) {
if (context instanceof OnInteractionListener) {
listener = (OnInteractionListener) context;
} else {
throw new ClassCastException(context + "must implement " + OnInteractionListener.class.getSimpleName());
}
super.onAttach(context);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_layout, container, false);
// ...
return v;
}
}
Step 2: Make sure your Activity implements that Interface
public class MyActivity extends AppCompatActivity implements MyFragment.OnInteractionListener {
#Override
public void doAction() {
// TODO: Implement this... e.g. switch fragments
}
...
}
Step 3: Inside the Fragment, you can invoke the callback whenever you want to perform some action
if (listener != null) {
listener.doAction();
}
From MainActivity(), get the navController and then use the navigate() function:
NavController navController = Navigation.findNavController(this,R.id.nav_host_fragment);
navController.navigate(R.id.nav_grid);