I just need to remove a fragment when a button in it is tapped
public static class EditNameDialog extends DialogFragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_find_in_page, container);
...
Button cancelButton = (Button) view.findViewById(R.id.cancel_button);
cancelButton.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View arg0, MotionEvent arg1) {
//remove the fragment here
return false;
}
});
return view;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
}
}
I just need to remove the fragment when the button is tapped
You can remove the fragment with use below code:
//remove the fragment from transaction manager
FragmentManager frgManager = getSupportFragmentManager();
Fragment fragment = frgManager.findFragmentByTag(tagName);
if (fragment != null) {
FragmentTransaction ft = frgManager.beginTransaction();
ft.remove(fragment).commit();
}
Related
I am frustrated.
i want to get value from child fragment to parent fragment
i had tries many method.
interface, viewModel, sharedpreferences but no one work.
I had follow this method
but it doesn't work for me.
here my code parent fragment:
public class Chart_Fragment extends Fragment
implements Product_Fragment.pf_interface {
String dt;
TextView tv;
public Chart_Fragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.chart_fragment, container, false);
// create product_fragment as childfragment
FragmentManager fm = getChildFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Product_Fragment product_fragment = new Product_Fragment();
ft.replace(R.id.fl_two, new Product_Fragment());
ft.commit();
return v;
}
public void onViewCreated(View v, Bundle savedInstanceState){
super.onViewCreated(v,savedInstanceState);
tv = (TextView)v.findViewById(R.id.rcv);
}
#Override
public void data(String d) {
FragmentManager fragmentManager = getChildFragmentManager();
Product_Fragment product_fragment =
(Product_Fragment)fragmentManager.findFragmentByTag("data");
if(product_fragment != null){
String dt = d;
tv.setText(dt);
}
}
}
and my childfragment is :
public class Product_Fragment extends Fragment {
private pf_interface pf;
public Product_Fragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.product_fragment, container, false);
Button b = (Button)v.findViewById(R.id.btn_sender);
b.setOnClickListener(new btnClick());
return v;
}
public void onAttachToParentFragment(Fragment fragment){
try {
pf = (pf_interface)fragment;
}catch (ClassCastException e){
throw new ClassCastException(
fragment.toString()+ "must implement pf_interface"
);
}
}
public void onCreate(Bundle savedInstanceState){
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
onAttachToParentFragment(getParentFragment());
}
private class btnClick implements View.OnClickListener{
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_sender:
if(pf != null){
pf.data("button click interface");
}break;
}
}
}
public interface pf_interface{
void data(String d);
}
}
textview on parent fragment didn't show the string d ("button click interface")from child fragment
Why you're checking for child fragment in callback on your parent fragment ?
#Override
public void data(String d) {
FragmentManager fragmentManager = getChildFragmentManager();
Product_Fragment product_fragment =
(Product_Fragment)fragmentManager.findFragmentByTag("data");
if(product_fragment != null){ // Why to check for child fragment nullability?
String dt = d;
tv.setText(dt);
}
}
You can directly use like this:
#Override
public void data(String d) {
tv.setText(d);
}
Note: on any certain scenario if any of object is null, your callback won't be executed. You've already check for null reference.
I have two fragment inside a LinearLayout.
When I click on a FAB button I would like to hide one but a
null object reference appears on FragmentTransaction hide method.
Why doesn't "f" have a view reference?
public class FragmentOne extends Fragment {
public FragmentOne() {
// 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
View returnView = inflater.inflate(R.layout.fragment_one, container, false);
FloatingActionButton fabTemp = returnView.findViewById(R.id.fabTemp);
final Fragment f = getActivity().getSupportFragmentManager().getFragments().get(0).getChildFragmentManager().getFragments().get(1);
final FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
fabTemp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
transaction.setCustomAnimations(android.R.animator.fade_in,
android.R.animator.fade_out);
if (f.isHidden()) {
transaction.show(f);
} else {
transaction.hide(f);
}
transaction.commit();
}
});
return returnView;
}
I solved in another way despite not being as i wanted
final View frag = getView().findViewById(R.id.frgSettemp);
frag.setVisibility(View.GONE);
In onCreateView just inflate and return the view.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View returnView = inflater.inflate(R.layout.fragment_one, container, false);
return returnView;
}
Try the other processing in onViewCreated #override method. like this
#Override
public void onViewCreated(View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
FloatingActionButton fabTemp = getView().findViewById(R.id.fabTemp);
final Fragment f = getActivity().getSupportFragmentManager().getFragments().get(0);
final FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
fabTemp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
transaction.setCustomAnimations(android.R.animator.fade_in,
android.R.animator.fade_out);
if (f.isHidden()) {
transaction.show(f);
} else {
transaction.hide(f);
}
transaction.commit();
}
});
}
Hope this will help.
You should call only
final Fragment f = getActivity().getSupportFragmentManager().getFragments().get(0);
or
final Fragment f = getActivity().getSupportFragmentManager().getFragments().get(1);
What you have done will return null for sure.
I have three fragment and one activity. It works this way:
[activity]-> [MainFragment]->[MenuFragment]->[SignUpFragment]
When [SignUpFragment] is back pressed, the [MainFragment] is created twice.
I tried setRetaInInstance(true) and I checked savedInstanceState but I can not prevent [MainFragment] recreating.
This is my MainActivity:
public class MainActivity extends AppCompatActivity {
public Bundle mSavedInstanceState;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedInstanceState = savedInstanceState;
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
callMainFragment();
}
private void callMainFragment() {
if (mSavedInstanceState == null) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container_category, new MainFragment(), MainFragment.class.getSimpleName());
transaction.addToBackStack(null);
transaction.commit();
}
}
public ActionBar getMainActionBar(){
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Action Bar Display settings
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
// Custom view inflater
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Custom layout view
View viewActionBar = inflater.inflate(R.layout.action_bar, null);
// Set custom view
actionBar.setCustomView(viewActionBar);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
}
return actionBar;
}
This is my MainFragment:
public class MainFragment extends BaseFragment implements AdapterView.OnItemClickListener, BuyersGuideCategoriesDelegate, View.OnClickListener {
private Bundle mSavedInstanceState;
private BuyersGuideCategoriesFragment mCategoriesFragment;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRetainInstance(true);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mSavedInstanceState = savedInstanceState;
if (mSavedInstanceState == null) {
mView = inflater.inflate(R.layout.fragment_main, container, false);
// Call Grid View Buyers Guide Fragment
mCategoriesFragment = new BuyersGuideCategoriesFragment();
mCategoriesFragment.mGridViewDelegate = this;
setIcons();
setTitles();
setTexts();
initListView();
}
return mView;
}
#Override
public void onResume() {
super.onResume();
ImageView menu = (ImageView) ((MainActivity) getActivity()).getMainActionBar().getCustomView().findViewById(R.id.action_bar_menu_icon);
menu.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (mSavedInstanceState == null) {
MainActivity activity = (MainActivity) getActivity();
FragmentManager manager = activity.getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container_category, new MenuFragment(),MenuFragment.class.getSimpleName());
transaction.addToBackStack(null);
transaction.commit();
}
}
}
This is my MenuFragment:
public class MenuFragment extends BaseFragment implements AdapterView.OnItemClickListener, View.OnClickListener {
private Bundle mSavedInstanceState;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mSavedInstanceState = savedInstanceState;
if (savedInstanceState == null) {
mView = inflater.inflate(R.layout.fragment_menu, container, false);
setMenuItemsListViewAdapter();
}
return mView;
}
private void setMenuItemsListViewAdapter() {
ListView menuItems = (ListView) mView.findViewById(R.id.list_menu_items);
ListMenuItemsListViewAdapter adapter = new ListMenuItemsListViewAdapter(getContext(),getMenuItemNames());
menuItems.setAdapter(adapter);
menuItems.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch ((String) parent.getAdapter().getItem(position)){
case SIGN_UP:
replaceFragment(R.id.container_category,new SignUpFragment(),SignUpFragment.class.getSimpleName());
break;
}
}
private void replaceFragment(int containerId,Fragment fragment, String fragmentTag){
if (mSavedInstanceState == null){
MainActivity activity = (MainActivity) getActivity();
FragmentManager manager = activity.getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(containerId,fragment,fragmentTag);
transaction.addToBackStack(null);
transaction.commit();
}
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.menu_back_icon:
replaceFragment(R.id.container_category, new MainFragment(),MainFragment.class.getSimpleName());
break;
}
}
}
And this is my SignUpFragment:
public class SignUpFragment extends BaseFragment implements View.OnClickListener{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (savedInstanceState == null) {
mView = inflater.inflate(R.layout.fragment_sign_up, container, false);
}
return mView;
}
}
EDIT 1: The MainFragment is recreated only when I return from SignUpFragment to MenuFragment. I am doing wrong using so many fragments? Should I use activity?
When you are move between Fragments, call addToBackStack() :
FragmentTransaction ft = fragmentManager.beginTransation();
ft.replace( R.id.fragment, new MyFragment() ).addToBackStack( "ftransaction" ).commit();
Create first Fragment:
FragmentTransaction ft = fragmentManager.beginTransation();
ft.add(R.id.container, new FirstFragment()).addToBackStack(null).commit();
Second:
FragmentTransaction ft = fragmentManager.beginTransation();
ft.replace(R.id.container, new SecondFragment()).addToBackStack(null).commit();
and Third:
FragmentTransaction ft = fragmentManager.beginTransation();
ft.replace(R.id.container, new ThirdFragment()).commit();
In my MainActivity there is a FrameLayout (id=fragment_container) that is replaced by the Activity in onCreate with FragmentA. FragmentA just contains a single Button and calls onClick in the MainActivity in order to replace the FrameLayout with FragmentB. FragmentB contains a RecyclerView and is shown correctly. I call fragmentManager.popBackStack() to bring back FragmentA. Now FragmentA is shown on top of FragmentB (which I still can interact with).
Why is FragmentB not removed after calling popBackStack?
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private FragmentManager fragmentManager;
#Override
public void onBackPressed() {
fragmentManager.popBackStack();
}
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, new FragmentB());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//...
fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FragmentA fragment = FragmentA.getInstance(this); //register OnClickListener
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
//...
}
FragmentA
public class FragmentA extends Fragment {
private View.OnClickListener onClickListener;
public FragmentA() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, container, false);
FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab);
fab.setOnClickListener(onClickListener);
return view;
}
public static FragmentA getInstance(View.OnClickListener onClickListener) {
FragmentA fragmentA = new FragmentA();
fragmentA.setOnClickListener(onClickListener);
return fragmentA;
}
private void setOnClickListener(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
}
FragmentB
public class FragmentB extends Fragment {
//...
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.FragmentB, container, true);
//manipulating Views...
//...
return view;
}
}
The problem is in the FragmentB class. You should not pass the argument attachToRoot=true.
Try this instead:
public class FragmentB extends Fragment {
//...
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
//don't pass true
View view = inflater.inflate(R.layout.FragmentB, container, false);
//manipulating Views...
//...
return view;
}
}
Use popBackStackImmediate instead,
#Override
public void onBackPressed() {
fragmentManager.popBackStackImmediate();
}
From the popBackStackImmediate docs,
Like popBackStack(), but performs the operation immediately inside of the call. This is like calling executePendingTransactions() afterwards.
Here is my code
I need to go from A->B->C and onBackPressed() from B and C should go to A
while pressing back it goes to B and then to C , It seems to me that transaction.addToBackStack(null); not using as needed
public class TestfragmentActivity extends FragmentActivity{
private FrameLayout layout;
private String TAG = "TAG";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_fragment);
layout = (FrameLayout) findViewById(R.id.container);
A fragment = new A();
doFragmentTransaction(fragment, false);
}
private void doFragmentTransaction(Fragment fragment, boolean addToBackstack) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.container, fragment);
if (addToBackstack)
transaction.addToBackStack(TAG);
transaction.commit();
}
///////////////
public class A extends Fragment {
private Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.test_fragment1, null);
button = (Button) view.findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
B fragment = new B();
doFragmentTransaction(fragment, true);
}
});
return view;
}
private void doFragmentTransaction(Fragment fragment, boolean addToBackstack) {
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, fragment);
if (addToBackstack) {
transaction.addToBackStack(null);
}
transaction.commit();
}
//////////////////////
public class B extends Fragment {
private Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.test_fragment2, null);
button = (Button) view.findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
C fragment = new C();
doFragmentTransaction(fragment, false);
}
});
return view;
}
private void doFragmentTransaction(Fragment fragment, boolean addToBackstack) {
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, fragment);
if (addToBackstack)
transaction.addToBackStack(null);
transaction.commit();
}
}
}
in fragment B and C,
#Override
public void onBackPressed() {
}
in the function, replace the Container with Fragment A.