I have problem: A Fragment is not reattached to its hosting ViewPager after returning from another fragment by using popBackStack.
One Activity hosting a Fragment whose layout holds a ViewPager. The ViewPager is populated by a FragmentStateViewPagerAdapter. The Fragment hosted inside the pager can open sub page lists, containing a new set of pages. All works fine as long as the back button is not pressed. As soon as the user closes one of the sub Page the previous Page is recreated, but without the Page that was displayed previously (Empty page with whiteblank page). I have searching but still not resolve my problem.
Full Code of TestProject can be found on Github
MainActivity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val ft = supportFragmentManager.beginTransaction()
ft.add(R.id.frameLayout, HomeFragment.newInstance())
ft.commit()
}
}
HomeFragment:
public class HomeFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home, container, false);
TabLayout tabLayout = v.findViewById(R.id.tabLayout);
ViewPager viewPager = v.findViewById(R.id.viewPager);
VPAdapter adapter = new VPAdapter(getFragmentManager());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
return v;
}
public static Fragment newInstance() {
return new HomeFragment();
}
}
VPAdapter:
public class VPAdapter extends FragmentStatePagerAdapter{
public VPAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return TabFragment.newInstance(position);
}
#Override
public CharSequence getPageTitle(int position) {
return "TAB " + position;
}
#Override
public int getCount() {
return 2;
}
}
TabFragment:
public class TabFragment extends Fragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("TAB", "onCreate");
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.e("TAB", "onCreateView");
return inflater.inflate(R.layout.fragment_tab, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle args = getArguments();
if (args != null) {
int tabIndex = args.getInt("tab_index", 0);
TextView tv = view.findViewById(R.id.textView);
tv.setText(String.format(Locale.getDefault(), "TAB FRAGMENT INDEX %d", tabIndex));
}
Button button = view.findViewById(R.id.button);
button.setText("Open Next Fragment");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frameLayout, LastFragment.newInstance());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("TAB", "onDestroy");
}
public static Fragment newInstance(int index) {
Bundle args = new Bundle();
args.putInt("tab_index", index);
TabFragment tab = new TabFragment();
tab.setArguments(args);
return tab;
}
}
LastFragment:
public class LastFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_last, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getFragmentManager().popBackStack();
}
});
}
public static Fragment newInstance() {
return new LastFragment();
}
}
You have to Use getChildFragmentManager() For Viewpager to adapt Popback Feature.
VPAdapter adapter = new VPAdapter(getChildFragmentManager());
You Can Refer this Documentation on ChildFragmentManager()
Related
I am trying to replace the current active fragment inside ViewPager when item inside fragment's recycelerview is clicked. So far, I manage to pop up the Toast on the second fragment when the item on the first fragment is clicked, but the all the view of the second fragment is blank.
Here is my code:
MainActivity.class
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewPager = findViewById(R.id.view_pager);
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(adapter.getCount() - 1);
}
// ..........
private static class FragmentAdapter extends FragmentStatePagerAdapter {
public FragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return AllGenreFragment.newInstance();
case 1:
return DashboardFragment.newInstance();
case 2:
return NotificationFragment.newInstance();
}
return null;
}
#Override
public int getCount() {
return 3;
}
}
// ..........
}
AllGenreFragment.class
public class AllGenreFragment extends Fragment {
RecyclerView genreRV;
private AllGenreAdapter allGenreAdapter;
private List<Genre> genreList;
public static AllGenreFragment newInstance() {
return new AllGenreFragment();
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_genre, container, false);
genreRV = v.findViewById(R.id.rv);
genreRV.setHasFixedSize(true);
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 2);
genreRV.setLayoutManager(layoutManager);
genreList = new ArrayList<>();
allGenreAdapter = new AllGenreAdapter(genreList, getContext());
genreRV.setAdapter(allGenreAdapter);
return v;
}
}
AllGenreAdapter.class
public class AllGenreAdapter extends RecyclerView.Adapter<AllGenreAdapter.ViewHolder> {
// .......
class ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder {
public ViewHolder(final View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "Genre: " + genre_title.getText().toString(), Toast.LENGTH_SHORT).show();
AppCompatActivity activity = (AppCompatActivity) itemView.getContext();
FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment allAnimeFragment = new AllAnimeFragment();
Bundle bundle = new Bundle();
bundle.putString("genreid", genre_id.getText().toString().trim());
allAnimeFragment.setArguments(bundle);
fragmentTransaction.replace(R.id.view_pager, allAnimeFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
}
}
// .......
}
AllAnimeFragment.class
public class AllAnimeFragment extends Fragment {
RecyclerView animeRV;
private AllAnimeAdapter allAnimeAdapter;
private List<Anime> animeList;
String genreid;
public static AllAnimeFragment newInstance() {
return new AllAnimeFragment();
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_anime, container, false);
Bundle arguments = getArguments();
genreid = arguments.getString("genreid");
Toast.makeText(getContext(), genreid, Toast.LENGTH_SHORT).show();
// .....
return v;
}
}
Your approach is not really good, try below way:
Create a container fragment, called ContainerFragment, example, you will be using this fragment for your ViewPager.
The ContainerFragment should contain a container view, and add AllGenreFragment in the first them it is invoked.
In AllGenreFragment, create a callback, when an item in the RecyclerView be clicked, then in ContainerFragment will replace (or add) current fragment (AllGenreFragment) to AllAnimeFragment
First, create ContainerFragment,
public class ContainerFragment extends Fragment implements AllGenreFragment.OnAllGenreFragmentListener {
#Nullable #Override public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_container, container, false);
}
#Override public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initialLoad();
}
private void initialLoad() {
getChildFragmentManager()
.beginTransaction()
.add(R.id.container, AllGenreFragment.newInstance())
.commit();
}
#Override public void onItemClicked() {
getChildFragmentManager()
.beginTransaction()
.replace(R.id.container, AllAnimeFragment.newInstance())
.commit();
}
}
This Fragment should implement a callback from AllGenreFragment for handling fragment transaction.
also, the xml layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Next step, add above fragment into ViewPager, we using ContainerFragment instead of AllGenreFragment.
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return ContainerFragment().newInstance();
case 1:
return DashboardFragment.newInstance();
case 2:
return NotificationFragment.newInstance();
}
return null;
}
Ok, so now come back to AllGenreFragment, we should create a CallBack that we implement in ContainerFragment
public interface AllGenreFragmentListener {
onItemClicked();
}
and then,
private AllGenreFragmentListener listener;
#Override public void onAttach(Context context) {
super.onAttach(context);
if (getParentFragment() instanceof AllGenreFragmentListener) {
listener = (AllGenreFragmentListener) getParentFragment();
}
}
so we have an instance of AllGenreFragmentListener, from now, whenever listener call onItemClicked, the method onItemClicked in ContainerFragment will be invoked.
Ok, let do it,
create below variable and method in your AllGenreAdapter:
private AllGenreFragmentListener listener;
public void setListener(AllGenreFragmentListener listener) {
this.listener = listener;
}
and update your ViewHodler
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "Genre: " + genre_title.getText().toString(), Toast.LENGTH_SHORT).show();
if (listener != null)
listener.onItemClicked()
});
}
Don't forget call setListener method in your AllGenreFragment, so please add
#Override public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (allGenreAdapter != null) allGenreAdapter.setListener(listener);
}
That all,
I type this code by hand, not in my IDE so maybe it not compile, so please fix it if you face any compile error.
Note
If you want to keep the behavior of the BACK button, override onBackPressed in your MainActivity
#Override public void onBackPressed() {
Fragment f = getCurrentFragment();
if (f != null) {
if (f.getChildFragmentManager().getBackStackEntryCount() > 1) {
f.getChildFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
} else {
super.onBackPressed();
}
}
public Fragment getCurrentFragment() {
return (Fragment) viewPager.getAdapter()
.instantiateItem(viewPager, viewPager.getCurrentItem());
}
Also, add fragment into backStack whenever we add them to the container view (in your ContainerFragment)
private void initialLoad() {
getChildFragmentManager()
.beginTransaction()
.add(R.id.container, AllGenreFragment.newInstance())
.addToBackStack(null)
.commit();
}
#Override public void onItemClicked() {
// change `replace` to `add` and add more `.addToBackStack(null)`
getChildFragmentManager()
.beginTransaction()
.add(R.id.container, AllAnimeFragment.newInstance())
.addToBackStack(null)
.commit();
}
you should add a context in the constructor of your adapter
public class AllGenreAdapter(Context context) extends RecyclerView.Adapter<AllGenreAdapter.ViewHolder> {
// .......
}
then pass your activity to your adapter, use it to replace your fragment
I have 3 tabs each are sharing a single fragment. But this fragment contains a viewPager. So all the three tabs will have a UI with a viewPager and viewPager have three different fragments. After following the examples available I managed to implement Tab layout with single fragment. But when I tried to implement a viewPager inside this fragment I am facing issue. Tab is not scrolling smoothly and its not moving to third tab. I am also not able to see my viewPager fragment.
Main Fragment with tablayout implementation:
public class DashboardFragment extends android.support.v4.app.Fragment {
Activity mActivity;
private TabLayout tabLayout;
private ViewPager viewPager;
private static final String TAG = "DashboardFragment";
public DashboardFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = getActivity();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dashboard_fragment, container, false);
tabLayout = (TabLayout)view.findViewById(R.id.tabs);
viewPager = (ViewPager)view.findViewById(R.id.viewpager);
tabLayout.addTab(tabLayout.newTab().setText("Yesterday"));
tabLayout.addTab(tabLayout.newTab().setText("Last Week"));
tabLayout.addTab(tabLayout.newTab().setText("This Month"));
setupViewPager(viewPager);
return view;
}
private void setupViewPager(ViewPager viewPager) {
DashboardTabPagerAdapter adapter = new DashboardTabPagerAdapter(((AppCompatActivity)getActivity()).getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
DashboardPagerAdapter:
public class DashboardTabPagerAdapter extends FragmentStatePagerAdapter {
private int mNoOfTabs;
public DashboardTabPagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
mNoOfTabs=tabCount;
}
#Override
public Fragment getItem(int position) {
DashboardYesterdayFragment fragment = new DashboardYesterdayFragment();
Bundle args = new Bundle();
switch (position) {
case 0:
args.putSerializable(AppConstants.TAB_DASHBOARD_TYPE, AppConstants.TAB_DASHBOARD_YESTERDAY);
break;
case 1:
args.putSerializable(AppConstants.TAB_DASHBOARD_TYPE, AppConstants.TAB_DASHBOARD_LAST_WEEK);
break;
case 2:
args.putSerializable(AppConstants.TAB_DASHBOARD_TYPE, AppConstants.TAB_DASHBOARD_THIS_MONTH);
break;
default:
return null;
}
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return mNoOfTabs;
}
}
TabFragment which contains a childViewPager:
public class DashboardYesterdayFragment extends android.support.v4.app.Fragment {
private String title;
private Bundle bundle;
ViewPager mViewPager;
public DashboardYesterdayFragment(){
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
bundle = getArguments();
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dashboard_yesterday_layout, container, false);
mViewPager = view.findViewById(R.id.vpPager);
setupViewPager(mViewPager);
return view;
}
private void setupViewPager(ViewPager viewPager) {
DashboardViewPagerAdapter adapter = new DashboardViewPagerAdapter( getChildFragmentManager(),bundle);
mViewPager.setAdapter(adapter);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
mViewPager.setPageMargin(24);
}
ChildViewPagerAdapter:
public class DashboardViewPagerAdapter extends FragmentStatePagerAdapter {
private static int NUM_ITEMS = 3;
private Bundle bundle;
public DashboardViewPagerAdapter(FragmentManager fm, Bundle bundle) {
super(fm);
this.bundle=bundle;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return IncidentsFragment.newInstance(bundle);
case 1:
return VehicleUtilizationFragment.newInstance(bundle);
case 2:
return FleetPerformanceFragment.newInstance(bundle);
default:
return null;
}
}
#Override
public int getCount() {
return NUM_ITEMS;
}
}
ChildViewPager first fragment:
public class IncidentsFragment extends Fragment {
private TextView mOverSpeeding,mGeoFence,mIdlingCase,mFuelFilling,mMosetIncidences, mLeastIncidences;
public static IncidentsFragment newInstance(Bundle bundle) {
IncidentsFragment fragmentFirst = new IncidentsFragment();
Bundle args = new Bundle();
args.putBundle("bundle", bundle);
fragmentFirst.setArguments(args);
return fragmentFirst;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.incident_layout, container, false);
initViews(view);
return super.onCreateView(inflater, container, savedInstanceState);
}
private void initViews(View view) {
mOverSpeeding = (TextView)view.findViewById(R.id.over_speeding_value);
mGeoFence = (TextView)view.findViewById(R.id.geofence_value);
mIdlingCase = (TextView)view.findViewById(R.id.idling_value);
mFuelFilling = (TextView)view.findViewById(R.id.fuel_value);
mMosetIncidences = (TextView)view.findViewById(R.id.vehicle_reg_no);
mLeastIncidences = (TextView)view.findViewById(R.id.least_incidences_value);
}
}
I am confused what is going wrong.
Change this:
DashboardTabPagerAdapter adapter = new DashboardTabPagerAdapter(((AppCompatActivity)getActivity()).getSupportFragmentManager(),tabLayout.getTabCount());
to this:
DashboardTabPagerAdapter adapter = new DashboardTabPagerAdapter(((AppCompatActivity)getActivity()).getChildFragmentManager(),tabLayout.getTabCount());
I'm working on a flashcard like app and i've been wrestling with the flip animation. I've based my code on the AnimationsDemo from android with the difference being that it is done inside a fragment instead of an activity.
It works fine, not entirely as the preview of the aforementioned demo, but decent enough. Except... after changing orientation.
If the app is started in landscape, it works fine in landscape, but freaks in portrait and if the app is launched in portrait it works in portrait and freaks in landscape.
This is my code ( i skimmed the datamodel obviously)
public class MyFlashCardFragment extends Fragment {
private MyDataModel model;
private Handler mHandler = new Handler();
private boolean mShowingBack = false;
FrameLayout frameLayout;
public static MyFlashCardFragment create(MyDataModel m) {
MyFlashCardFragment fragment = new MyFlashCardFragment();
Bundle bundle = new Bundle();
bundle.putString(AppKeys.FRONT_KEY,m.getFrontText());
bundle.putString(AppKeys.BACK_KEY,m.getBackText());
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!getArguments().isEmpty()) {
model = new MyDataModel();
model.setFrontText(getArguments().getString(AppKeys.FRONT_KEY));
model.setBackText(getArguments().getString(AppKeys.BACK_KEY));
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
if (model == null) {
return super.onCreateView(inflater, container, savedInstanceState);
} else {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_flashcard, container, false);
frameLayout = (FrameLayout) root.findViewById(R.id.chilfd_frame);
Button btn_overlay = (Button) root.findViewById(R.id.overlaybutton);
btn_overlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
flipCard();
}
});
return root;
}
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if(savedInstanceState == null) {
getChildFragmentManager()
.beginTransaction()
.add(R.id.chilfd_frame, CardFrontFragment.create(model.getFrontText()))
.commit();
} else {
mShowingBack = (getChildFragmentManager().getBackStackEntryCount() > 0);
}
getChildFragmentManager().addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
mShowingBack = (getChildFragmentManager().getBackStackEntryCount() > 0);
getActivity().invalidateOptionsMenu();
}
});
}
private void flipCard() {
if (mShowingBack) {
getChildFragmentManager().popBackStack();
return;
}
mShowingBack = true;
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(
R.animator.card_flip_right_in, R.animator.card_flip_right_out,
R.animator.card_flip_left_in, R.animator.card_flip_left_out)
.replace(frameLayout.getId(), CardBackFragment.create(model.getBackText()))
.addToBackStack(null)
.commit();
mHandler.post(new Runnable() {
#Override
public void run() {
getActivity().invalidateOptionsMenu();
}
});
}
/**
* A fragment representing the front of the card.
*/
public static class CardFrontFragment extends Fragment {
String frontText;
public static CardFrontFragment create(String frontText) {
CardFrontFragment fragment = new CardFrontFragment();
Bundle bundle = new Bundle();
bundle.putString(AppKeys.FRONT_KEY,frontText);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!getArguments().isEmpty()) {
frontText = getArguments().getString(AppKeys.FRONT_KEY);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (TextUtils.isEmpty(frontText)) {
return super.onCreateView(inflater, container, savedInstanceState);
} else {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_flashcard_front, container, false);
((TextView) rootView.findViewById(R.id.tv_name)).setText(frontText);
return rootView;
}
}
}
/**
* A fragment representing the back of the card.
*/
public static class CardBackFragment extends Fragment {
String backText;
public static CardBackFragment create(String backText) {
CardBackFragment fragment = new CardBackFragment();
Bundle bundle = new Bundle();
bundle.putString(AppKeys.BACK_KEY,backText);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!getArguments().isEmpty()) {
backText = getArguments().getString(AppKeys.BACK_KEY);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (TextUtils.isEmpty(backText)) {
return super.onCreateView(inflater, container, savedInstanceState);
} else {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_flashcard_back, container, false);
((TextView) rootView.findViewById(R.id.tv_name)).setText(backText);
return rootView;
}
}
}
}
The parentfragment is loaded form a viewpager:
pager = (ViewPager) findViewById(R.id.pager);
adapter = new FlashCardPageAdapter(getFragmentManager(), getAllFrom(ref));
pager.setAdapter(adapter);
pager.setCurrentItem(position,true);
pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
}
});
and the adapter used is:
public class FlashCardPageAdapter extends FragmentStatePagerAdapter {
private ArrayList<MyDataModel> Models;
public FlashCardPageAdapter(FragmentManager fm, ArrayList<MyDataModel> list) {
super(fm);
this.Models = list;
}
#Override
public Fragment getItem(int position) {
return FlashCardFragment.create(Models.get(position));
}
#Override
public int getCount() {
return Models.size();
}
}
I also tried to create the animations form an Animator object and add that to a transparent button and animating views in and out and toggling the visibility and the result is the same.
Any ideas/suggestions would be welcome.
It turns out there's nothing missing in my code and the problem is emulator related. Well at least it seems that way. I tried it on 2 real devices (1 phone/1 tablet) and the problem didn't manifest on them, so might be an AVD bug or simple shortcoming of the simulated orientation change.
When I am trying to load a new fragment it loads previous fragment.
I have a fragment profile fragment and on it some onclicks are there. I want to open a new fragment on the click event but it is opening the previous fragment, somewhere backstack is missing or something else i could not find out.
relativeLayoutManagement.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction transaction;
if(getParentFragment() == null){
transaction = childFragmentManager.beginTransaction();
}else {
transaction = childFragmentManagerOfParent.beginTransaction();
transaction.replace(R.id.frameLayoutChildContainer, HotelManagementFragment.newInstance(),FragmentTags.HOTEL_MANAGEMENT);
transaction.addToBackStack(FragmentTags.HOTEL_MANAGEMENT);
transaction.commit();
}
}
});
}
This is my new fragment code.
public class HotelManagementFragment extends BaseFragment {
public HotelManagementFragment() {
}
public static HotelManagementFragment newInstance() {
HotelManagementFragment fragment = new HotelManagementFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_hotel_managment, container, false);
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
}
If you are trying to load fragment on another fragment then Use that id which is in your main activity layout like this. //transaction.replace(R.id.main_activity_fragment_id,your_fragment);
I have a fragment with a ViewPager inside it. In the ViewPager I have 4 content screens so swipe around in. The content has a few TextView components and I'm trying to access them from the first fragment, however when I go to use setText or similar I get a null pointer exception. Ive checked and the id for the TextView is valid, and I've done a clean build.
Here is a snippet of my relevant code:
private TextView textViewOne;
private PagerAdapter mPagerAdapter;
private ViewPager pager;
View rootView;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_layout_viewpager, container, false);
InitializePaging();
textViewOne = (TextView) rootView.findViewById(R.id.create_name);
//would return null if I did this:
textViewOne.setText("test");
return rootView;
}
private void InitializePaging() {
mPagerAdapter = new ViewPagerAdapter(getContext(), getChildFragmentManager(),
Arrays.asList(PageOne.class, PageTwo.class, PageThree.class, PageFour.class));
pager = (ViewPager) rootView.findViewById(R.id.content_pager);
pager.setAdapter(mPagerAdapter);
}
The PageOne class:
public class PageOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(container == null) {
return null;
}
return (LinearLayout) inflater.inflate(R.layout.fragment_page_one, container, false);
}
}
This is the fragment_layout_viewpager xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/content_pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
You are inflating fragment_layout_viewpager, so the create_name should exist in that layout, otherwise it will throw a null pointer.
Create an interface with 1 abstract method. Let the Fragment implement the interface and call the callback method from Activity.In the below example, I try to pass value on click of button from MainActivity to ThirdFragment.
public interface FragmentCommunicator {
public void passDataToFragment(String someValue);
}
public class MainActivity extends FragmentActivity {
FragmentCommunicator fragmentCommunicator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button btn= (Button)findViewById(R.id.button) ;
btnsetOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
randomvalue= getRansomString();
if(fragmentCommunicator!=null)
fragmentCommunicator.passDataToFragment(randomvalue);
}
});
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return FirstFragment.newInstance("FirstFragment, Instance 1");
case 1: return ThirdFragment.newInstance("ThirdFragment, Instance 1");
default: return FirstFragment.newInstance("FirstFragment,Instance 1");
}
}
#Override
public int getCount() {
return 2;
}
}
public static class FirstFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.first_frag, container, false);
TextView tv = (TextView) v.findViewById(R.id.tvFragFirst);
tv.setText(getArguments().getString("msg"));
return v;
}
public static FirstFragment newInstance(String text) {
Log.e("FirstFragment","newInstance called");
FirstFragment f = new FirstFragment();
Bundle b = new Bundle();
b.putString("msg", text);
f.setArguments(b);
return f;
}
}
public class ThirdFragment extends Fragment implements FragmentCommunicator {
TextView tv;
String value="";
public FragmentCommunicator fragmentCommunicator;
#Override
public void passDataToFragment(String someValue) {
this.value = someValue;
tv.setText(value);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
((MainActivity)activity).fragmentCommunicator = this;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement FragmentCommunicator");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.first_frag, container, false);
value=getArguments().getString("msg");
tv = (TextView) v.findViewById(R.id.tvFragFirst);
tv.setText(value);
return v;
}
public static ThirdFragment newInstance(String text) {
ThirdFragment f = new ThirdFragment();
Bundle b = new Bundle();
b.putString("msg",text);
f.setArguments(b);
return f;
}
}