android fragment replace to second fragment not working - android

My situation is I have a Activity(only FrameLayout),one fragment has a butoon that it's function is changing to second fragmnet,but when i set replace and commit.It's fail.
I tried this function success brfore,but it's not working now.
Is anyone can tell me the problem ? It will be grateful.
The first fragment code:
public class StartPage extends Fragment implements View.OnClickListener {
}
public static StartPage newInstance() {
return new StartPage();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.start_page_fragment, container, false);
//findViews();
imageRegistered = (ImageView) view.findViewById(R.id.imageRegistered);
imageRegistered.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragment=getFragmentManager();
FragmentTransaction transaction=fragment.beginTransaction();
transaction.replace(R.id.frameStartPage,Register.newInstance(),null);
transaction.commit();
Toast.makeText(getActivity(),"Test",Toast.LENGTH_SHORT).show();
}
});
return view;
}
and it's my frameLayout on the Activity:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frameStartPage"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.huaweb_system.taiwanuniversityhome.MainActivity">
</FrameLayout>
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
if (savedInstanceState == null) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frameStartPage, StartPage.newInstance());
transaction.commit();
}
}
}
second fragment:
public class Register extends Fragment implements View.OnClickListener {
public static StartPage newInstance() {
return new StartPage();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.register_activity, container, false);
findViews();
return view;
}
}

Actually getting instance using new operator and using newInstance() static method is same.
Problem is in your code :
public static StartPage newInstance() {
return new StartPage();
}
you are using the same method in both the fragments StartPage and Register.
Therefore You should change newInstance method of your Register fragment like this
public static Register newInstance() {
return new Register();
}

Related

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 can I replace fragment inside a fragment?

I have an Activity with a ViewPager, each page of the ViewPager has a Fragment.
Inside my Screen3Fragment I have a LinearLayout (lly_fragments) where I am showing some other fragments. I start by showing the fragment Screen3_1
public class Screen3Fragment extends Fragment {
private FragmentManager manager;
private FragmentTransaction transaction;
public static Screen3Fragment newInstance() {
final Screen3Fragment mf = new Screen3Fragment();
return mf;
}
public Screen3Fragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3, container, false);
Screen3_1Fragment frag31 = new Screen3_1Fragment();
manager = getChildFragmentManager();
transaction = manager.beginTransaction();
transaction.add(R.id.lly_fragments,frag31,"frag31");
transaction.addToBackStack("frag31");
transaction.commit();
return v;
}
}
This works fine without problems. Problem comes when, from within frag31 (which is inside Screen3Fragment), I want to call fragt32, for that I do the following.
public class Screen3_1Fragment extends Fragment {
private ImageButton imgbt_timer;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3_1,container,false);
imgbt_timer = (ImageButton) v.findViewById(R.id.bT_scr31_timer);
imgbt_timer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getChildFragmentManager().beginTransaction()
.replace(R.id.lly_fragments, new Screen3_2Fragment(), "frag32")
.commit();
}
});
return v;
}
}
As I read in other answers, the line transaction.replaceshould do the trick and replace the existing frag31 by the given frag32 inside the same given container lly_fragments.
However, I get java.lang.IllegalArgumentException: No view found for id..... I am not sure why.
getFragmentManager() will return always attributes from parent, in most cases the activities. getChildFragmentManager() wil return parent attributes (in your case, Screen3Fragment attributes). It should be used when you add a fragment inside a fragment.
In your case, Screen3Fragment should be added using getFragmentManager() and Screen3_1Fragment should be added using getChildFragmentManager() because Screen3_1Fragment is Screen3Fragment child. Screen3Fragment is the parent.
I recomand you to use always getFragmentManager() with add method, not replace because your parent will be the same.
getChildFragmentManager() can be used when you add a ViewPager inside a fragment.
You can use the callback, as following :
that worked for me, I hope my answers helps you
1) create a interface
public interface ChangeFragmentListener {
void onChangeFragmentLicked(int fragment);
}
2) implement the interface and transaction methods in your activity:
public class MainActivity extends AppCompatActivity implements ChangeFragmentListener {
FragmentTransaction fragmentTransaction;
Fragment1 fragment1;
Fragment2 fragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
fragment1 = new Fragment1();
fragment1.setChangeFragmentListener(this);
fragment2 = new Fragment2();
fragment2.setChangeFragmentListener(this);
initListeners();
}
void changeToFrag1() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container,fragment1, "");
fragmentTransaction.commit();
}
void changeToFrag2() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container, fragment2, "");
fragmentTransaction.commit();
}
#Override
public void onChangeFragmentLicked(int fragment) {
switch (fragment){
case 1:
changeToFrag1();
break;
case 2:
changeToFrag2();
break;
}
}
3) Create object from the interface to handle the callback:
public class Fragment1 extends Fragment {
private ChangeFragmentListener changeFragmentListener;
#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);
view.findViewById(R.id.fragment1_textView).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
changeFragmentListener.onChangeFragmentLicked(2);
}
});
return view;
}
public Fragment1 setChangeFragmentListener(ChangeFragmentListener changeFragmentListener) {
this.changeFragmentListener = changeFragmentListener;
return this;
}
}

Is it possible to start Fragment class from an Activity class..Using Intent

I have a MainActivity class,Is it possible to start a fragment class using Button onclicklistner
Main Activity Class:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button r_btn=(Button) findViewById(R.id.btn_register);
r_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, test.class);
startActivity(i);
}
});
Fragment Class
public class test extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_test, container, false);
rootView.findViewById(R.id.label1);
// Inflate the layout for this fragment
return rootView;
}
}
Any tips would be helpful..
Yes you can but you cant treat fragment like activity so you cant use startActivity method. Use fragment manager to call fragment
fragmentContainer = (RelativeLayout) findViewById(R.id.fragmentContainer);
r_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
replaceFragmentInContainer(new test(), fragmentContainer.getId(), getSupportFragmentManager());
}
});
public void replaceFragmentInContainer(Fragment DestinationFragment,int containerResourceID,FragmentManager fragmentManager )
{
FragmentTransaction ft=fragmentManager.beginTransaction();
int viewResourceID = containerResourceID;
ft.replace(viewResourceID, DestinationFragment);
ft.commit();
}
Your container in activity xml that will handle your fragment
<RelativeLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_below="#+id/toolbar"
android:layout_height="match_parent"
>
</RelativeLayout>
or you can check this

how to switch between two fragments by clicking on one of them?

suppose we have two fragments Frag1 and Frag2, now my question is how to switch between them by clicking on one of them using "FragmentTransaction Replace"
this is my codes:
public class Frags extends Fragment{
private boolean mShowingBack = false;
CardFrontFragment fr=new CardFrontFragment();
CardBackFragment bk=new CardBackFragment();
static View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (!mShowingBack)
{
return fr.onCreateView(inflater, container, savedInstanceState);
}
else
{
return bk.onCreateView(inflater, container, savedInstanceState);
}
}
public static class CardFrontFragment extends Fragment {
public CardFrontFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view=inflater.inflate(R.layout.fragment_card_front, container, false);
view.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
}
});
return view;
}
}
public static class CardBackFragment extends Fragment {
public CardBackFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view= inflater.inflate(R.layout.fragment_card_back, container, false);
view.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
}
});
return view;
}
}
public void flipCard() {
if (mShowingBack) {
getChildFragmentManager().popBackStack();
mShowingBack = !true;
return;
}
mShowingBack = true;
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(
R.animator.card_flip_right_in, R.animator.card_flip_right_out,
R.animator.card_flip_right_in, R.animator.card_flip_right_out)
.replace(R.id.container, this.bk)
.addToBackStack(null)
.commit();
}
and the problem: container can not be found
logcat: No View found for id 0x7f600054(id/container)
so where i am wrong?
is there any better way to do this?
It usually means that you have not define fragment with id container in your layout file.
In fragment layout
<LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "fill_parent">
<FrameLayout
android:id="#+id/container" <!-- this part is missing that is why view cannot find -->
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Also it seems like you did not inflate your layout in fragment onCreateView. This may also cause problem as system may not not which view it wants to create.

ViewPager with multiple fragment instances of same class

I am trying to create a ViewPager which contains 5 fragments.
5 fragments "container", so each of them contain 2 fragments.
The 4 first fragments have the same layout and belong to the same class. The fifth is from an other class, and there is no problem with that one.
The problem is that when the activity launches, only 1 fragment seem to be working (the one at position 0 in viewPager). I tried to return new Fragment() at position 0 in my PagerAdapter, but when I do that it's the 2nd fragment that is working. (By working i mean displaying the list on the left, I still haven't taken care of the details fragment on the right)
Here is some code
CustomPagerAdapter.java
public class CustomPagerAdapter extends FragmentPagerAdapter{
public CustomPagerAdapter(FragmentManager fm) {
super(fm);
}
public CustomPagerAdapter(FragmentManager fm, Context context) {
super(fm);
}
#Override
public Fragment getItem(int pos) {
if(pos == 4)
return new OtherContainerFragment();
else
return new ContainerFragment(pos);
}
#Override
public int getCount() {
return 5;
}
ContainerFragment.java
public class ContainerFragment extends Fragment {
private int CONTAINER_TYPE;
public ContainerFragment(){
}
public ContainerFragment(int type){
CONTAINER_TYPE = type;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_container, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
CustomListFragment frag = new CustomListFragment(CONTAINER_TYPE);
ft.replace(R.id.replaceable_list, frag);
ft.commit();
CustomListFragment.java
public class CustomListFragment extends SuperCustomListFragment{
private ArrayList<Model> mModels;
private int TYPE;
public CustomListFragment(){
}
public CustomListFragment(int type){
TYPE = type;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mModels = new ArrayList<Model>();
if(TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL){
mAdapter = AppUtils.getJournalListAdapter(getActivity(), mModels);
new syncPapers().execute();
}else if(TYPE == AppConstants.FRAGMENT_TYPE_MOVIES){
mAdapter = AppUtils.getMoviesListAdapter(getActivity(), mModels);
new syncMovies().execute();
}
if(mAdapter != null)
mListView.setAdapter(mAdapter); //mListView is defined in the superClass
Here are the constants I use :
public class AppConstants {
public static final int FRAGMENT_TYPE_AGENDA = 0; //so Fragment at position 0 should be of type agenda
public static final int FRAGMENT_TYPE_NEWS = 1; // position 1 should be of type news
public static final int FRAGMENT_TYPE_MOVIES = 2; // ...
public static final int FRAGMENT_TYPE_JOURNAL = 3; // ...
}
And the xml for the container :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/replaceable_list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
<LinearLayout
android:id="#+id/replaceable_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/background" >
</LinearLayout>
</LinearLayout>
SO this code is not working, it seems that the list on the left in the fragment container is replaced in each fragment, and only the fragment at position 0 displays it. (Currently it displays the list with the adapter of type "JOURNAL", but it should display list of type "AGENDA".
--------------------
*BUT !...*
--------------------
If I create different fragment_container layout-files, and write IF conditions in the onCreateView and onViewCreated in the ContainerFragment.java, everything works fine.
So :
ContainerFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL)
return inflater.inflate(R.layout.fragment_container_journal, container, false);
else if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_MOVIES)
return inflater.inflater(R.layout.fragment_container_movies, container, false);
else
return super.onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
CustomListFragment frag = new CustomListFragment(CONTAINER_TYPE);
if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL)
ft.replace(R.id.replaceable_journal_list, frag);
else if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_MOVIES)
ft.replace(R.id.replaceable_movies_list, frag);
else
return;
ft.commit();
I guess that's because in each fragment, I replace the LinearLayout of the same ID ? (replaceable_list)
I thought it was possible to share the same layout file for every fragments and didn't want to create 4 layout-files that would be the same. But it looks like I must do so ?
Or am I missing something here ?
Thank you for your time,
Though a very late response but I was facing same kind of issue and I fixed the issue by using
getChildFragmentManager().beginTransaction()
instead of
getActivity().getSupportFragmentManager().beginTransaction()
As in this case we are trying to make transaction from within a fragment (one out of the list of fragments which are attached to the ViewPager, thus the Activity holding the ViewPager) so we have to use getChildFragmentManager() here for desired results.
I was able to solve this by setting the id of the layout that is inflated within each fragment to its position.
What you would have to do is simply change the method onCreateView in you ContainerFragment class to:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_container, container, false);
v.setId(CONTAINER_TYPE)
return v;
This works because of the way the FragmentPagerAdapter implementation handles fragment tags.

Categories

Resources