i am stuck at nested fragments , some one please guide me a little bit. i am in learning phase...
actually i am using a bottomNavigationView and popluate fragments and when selecting an item, one fragment has a view pager and tab layout in it, and loading list data from fire base. the problem is that when a fragment with viewpager in it selected, data fetched successfuly but not populated in list view, but when i swite view pages the listview is populated . any one please help me for this problem or guide me where to put network calls in fragment or something else solution of it.
First Fragment which have Viewpager in .
public class explore extends Fragment {
public static explore Instance = null;
private TabLayout tabLayout;
private ViewPager viewPager;
private Activity activity;
private Context context;
private PagerAdapter pagerAdapter;
public static explore getInstance() {
if (Instance == null) {
Instance = new explore();
}
return Instance;
}
public explore() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
activity = (Activity) getActivity();
context = getActivity();
return inflater.inflate(R.layout.fragment_explore, container, false);
}
#Override
public void onViewCreated(#NonNull View v, #Nullable Bundle savedInstanceState) {
tabLayout = v.findViewById(R.id.tabs_Explore);
viewPager = v.findViewById(R.id.viewpager_Explore);
tabLayout.setupWithViewPager(viewPager);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
List<Category> categories = new FirebaseHelper(getActivity()).getCategoriesList();
pagerAdapter = new PagerAdapter(getChildFragmentManager(), categories);
viewPager.setAdapter(pagerAdapter);
super.onActivityCreated(savedInstanceState);
}
}
pager's first fragment means(ChildFragment)
public class categories extends Fragment {
private static categories Obj = null;
private RecyclerView listView;
private List<Category> categoryList;
private CategoryAdapter categoryAdapter;
public categories() {
categoryList = new ArrayList<>();
}
public static categories getInstance() {
if (Obj == null) {
Obj = new categories();
}
return Obj;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_blank, container, false);
listView = v.findViewById(R.id.mRecycler);
listView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
listView.setHasFixedSize(true);
SnapHelper helper = new LinearSnapHelper();
helper.attachToRecyclerView(listView);
categoryAdapter = new CategoryAdapter(getActivity(), categoryList);
listView.setAdapter(categoryAdapter);
return v;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
Bundle bundle = getArguments();
if (bundle != null) {
categoryList = bundle.getParcelableArrayList("data");
categoryAdapter.notifyDataSetChanged();
}
super.onActivityCreated(savedInstanceState);
}
}
Related
I have Recycler view in list income fragment and I want to use the same list income fragment for all my dynamically created tags by updating the data of recycler view according to the tab selected. I have the below code and works fine for the first time and only in first tab it works. When I swipe to 2nd, 3rd and 4th or come back to 1st, it shows empty recycler data. I am struggling with this past 2 days. Help is very much appreciated.
IncomeListTabsFragment.java
public class IncomeListTabsFragment extends Fragment {
private TabLayout branchesTabLayout;
private ViewPager incomeListViewPager;
private BranchAPIService branchAPIService;
private List<Branch> branchesList;
private View view;
private ViewPagerAdapter viewPagerAdapter;
public IncomeListTabsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_income_list_tabs, container, false);
incomeListViewPager = (ViewPager) view.findViewById(R.id.viewpager);
setupViewPager(incomeListViewPager);
return view;
}
private void setupViewPager(ViewPager viewPager) {
getBranchesFromAPI();
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
viewPagerAdapter = new ViewPagerAdapter(getFragmentManager());
for (Branch branch: branchesList) {
IncomeListFragment incomeListFragment = IncomeListFragment.newInstance(branch.getId());
viewPagerAdapter.addFrag(incomeListFragment, branch.getName());
}
branchesTabLayout = (TabLayout) view.findViewById(R.id.branchTabLayout);
branchesTabLayout.setupWithViewPager(viewPager);
viewPager.setAdapter(viewPagerAdapter);
}
private List<Branch> getBranchesFromAPI() {
// .......
return branchesList;
}
}
ViewPagerAdapter.java
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
IncomeListFragment.java
public class IncomeListFragment extends Fragment {
View view;
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
TabLayout branchesTabLayout;
ViewPager incomeListViewPager;
public static final String ARG_BRANCH_ID = "branch_id";
private BranchAPIService branchAPIService;
private List<Branch> branchesList;
private int branchId;
public IncomeListFragment() {
// Required empty public constructor
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
((IncomeAdapter) recyclerView.getAdapter()).onSaveInstanceState(outState);
}
public static IncomeListFragment newInstance(int branch_id) {
IncomeListFragment incomeListFragment = new IncomeListFragment();
Bundle args = new Bundle();
args.putInt(ARG_BRANCH_ID, branch_id);
incomeListFragment.setArguments(args);
return incomeListFragment;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_income_list, container, false);
branchId = getArguments().getInt(ARG_BRANCH_ID);
List<IncomeParent> incomeParentTest = ((GlobalVariableHelper) getActivity().getApplicationContext()).getIncomeParents();
recyclerView = (RecyclerView) view.findViewById(R.id.income_list_recycler_view);
layoutManager = new LinearLayoutManager(this.getActivity());
recyclerView.setLayoutManager(layoutManager);
IncomeAdapter incomeAdapter = new IncomeAdapter(getActivity(), incomeData());
incomeAdapter.setParentClickableViewAnimationDefaultDuration();
incomeAdapter.setParentAndIconExpandOnClick(true);
recyclerView.setAdapter(incomeAdapter);
return view;
}
private List<ParentObject> incomeData() {
//get data for recycler view
return incomeParentObject;
}
}
I have a fragment that implements a ViewPager, in this fragment, I save the ViewPager status using the onSaveInstanceState() method. I can save it in the bundle using viewPager.getCurrentItem(), but when I go to restore the status of the ViewPager, the viewPager.setCurrentItem() doesn't seem to work.
How can I save the fragment status correctly?
This is my fragment code
public class HomeFragment extends Fragment {
private ViewPager viewPager;
private ViewPagerAdapter adapter;
Integer[] colors=null;
List<Model> models;
private String[] mDescriptions;
private String[] mTitle;
private String mPlayerName;
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentItem", viewPager.getCurrentItem());
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
models = new ArrayList<>();
Resources res = getResources();
mDescriptions = res.getStringArray(R.array.newGameDescription);
mTitle = res.getStringArray(R.array.newGame);
models.add(new Model(R.drawable.ic_launcher_background,mTitle[0], mDescriptions[0]));
models.add(new Model(R.drawable.ic_launcher_background,mTitle[1], mDescriptions[1]));
models.add(new Model(R.drawable.ic_launcher_background,mTitle[2], mDescriptions[2]));
models.add(new Model(R.drawable.ic_launcher_background,mTitle[3], mDescriptions[3]));
adapter = new ViewPagerAdapter(getContext(), models, mPlayerName);
int orientation = getResources().getConfiguration().orientation;
adapter.setOrientation(orientation);
View view = inflater.inflate(R.layout.fragment_home, container, false);
viewPager = (ViewPager) view.findViewById(R.id.gameModeViewPager);
viewPager.setAdapter(adapter);
viewPager.setPadding(130,0,130,0);
return view;
}
#Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// Restore last state for checked position.
viewPager.postDelayed(new Runnable() {
#Override
public void run() {
int item = savedInstanceState.getInt("currentItem");
viewPager.setCurrentItem(item);
}
}, 100);
}
}
}
Any suggestion and review are welcome, thanks in advance
onCreateView does not return bundle value from onSaveInstanceState you have to get it from onActivityCreated
#public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// Restore last state for checked position.
viewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
int item = savedInstanceState.getInt("currentItem");
viewPager.setCurrentItem(item);
}
});
}
I am using ViewPager in my Android project, and I use FragmentStatePagerAdapter to set the pages.
class MyPageAdapter extends FragmentStatePagerAdapter {
List<Fragment> mList = new ArrayList<>();
public MyPageAdapter(FragmentManager fm) {
super(fm);
this.init();
}
private void init() {
mList.add(new FragmentOne());
mList.add(new FragmentTwo());
mList.add(new FragmentThree());
....
}
#Override
public Fragment getItem(int position) {
return mList.get(position);
}
}
And for each Fragment data will be loaded from the server once the view created, like this:
public class FragmentOne extends Fragment {
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(getViewResourceId(), container, false);
ButterKnife.bind(this, v);
setRetainInstance(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
mRecycleView.setLayotManager(linearLayoutManager);
endlessRecyclerViewScrollListener = new EndlessRecyclerViewScrollListener((LinearLayoutManager) mRecycleView.getLayoutManager()) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
loadByPage(page);
}
};
mRecycleView.addOnScrollListener(endlessRecyclerViewScrollListener);
return v;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = createAdapter();
mRecycleView.setAdapter(mAdapter);
loadByPage(1); // load data from server
}
}
As shown, the Fragment contains a endless recyclerview.
So far so good. However once I change the selected view pageļ¼ I found that the data will be reloaded every time. For example, I have scroll 3 pages in FragmentOne, and then change to FragmentTwo, and when I change to FragmentOne back, FragmentOne will try load data of page 1.
Is it possible to avoid this?
you can do something like this :
private boolean isDataCalled = true;
private List<ItemModel> itemModelList;
and then
if (isDataCalled){
loadByPage(1); // Initialize itemModelList in this method
setItemAdapter(itemModelList);
isDataCalled = false;
}else {
setItemAdapter(itemModelList);
}
setItemAdapter method
private void setItemAdapter(List<ItemModel> itemModelList){
mAdapter = createAdapter(itemModelList);
mRecycleView.setAdapter(mAdapter);
}
As the title says, I am trying to access (setText,etc) a TextView thats inside a fragment. The fragment is loaded into a viewpager in an activity. I want to access this TextView from the activity class.
private PagerAdapter mPagerAdapter;
private ViewPager pager;
FragmentPageOne fragPageOne;
FragmentPageTwo fragPageTwo;
Exert of Activity's onCreate:
fragPageOne= new FragmentPageOne();
fragPageTwo = new FragmentPageTwo();
mPagerAdapter = new ViewPagerAdapter(this, getSupportFragmentManager(),
fragPageOne.getClass(), fragPageTwo.getClass(),
);
pager = (ViewPager) findViewById(R.id.eventPager);
pager.setAdapter(mPagerAdapter);
ViewPagerAdapter class:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Class<? extends Fragment>> fragmentsClasses;
private final Context context;
public EventViewPagerAdapter(Context context, FragmentManager fm, Class<? extends Fragment>... fragmentsClasses) {
super(fm);
this.context = context;
this.fragmentsClasses = Arrays.asList(fragmentsClasses);
}
public Fragment getItem(int position) {
return Fragment.instantiate(context, fragmentsClasses.get(position).getName());
}
#Override
public int getCount() {
return fragmentsClasses.size();
}
}
FragmentPageOne class (FragmentPageTwo's structure is similar.):
public class FragmentPageOne extends Fragment {
public View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(container == null) {
return null;
}
rootView = inflater.inflate(R.layout.fragment_page_1, container, false);
return (LinearLayout) rootView;
}
}
I am getting a null pointer (obviously) when i try to use this (within the activity itself):
TextView text = (TexView) pager.findViewById(R.id.textview1);
text.setText("hello world);
get your current fragment :
public Fragment getVisibleFragment(){
FragmentManager fragmentManager = this.getSupportFragmentManager();
List<Fragment> fragments = fragmentManager.getFragments();
if(fragments != null){
for(Fragment fragment : fragments){
if(fragment != null && fragment.isVisible())
return fragment;
}
}
return null;
}
then get the view of the fragment to use findViewById from this view.
You're best bet is to do this in the instantiateItem override method in the pager adapter like so;
private LayoutInflater layoutInflater;
private Activity activity;
private int[] layouts;
public WalletViewPagerAdapter(int[] layouts , Activity activity) {
this.activity = activity;
this.layouts =layouts;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(layouts[position], container, false);
if (position ==0) {
TextView availableBalance = view.findViewById(R.id.available);
availableBalance.setText("N100,0000,000");
}
container.addView(view);
return view;
}
The view you're trying to access is not yet available as at the time you're calling it. Try overriding the onViewCreated method then use the view parameter to get textView like so;
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
TextView availableBalance = view.findViewById(R.id.available);
availableBalance.setText("N100,0000,000");
}
I am making a list that will be placed under another view.
Based on the other article, i should contain the other view in the header of the listview.
I am using ListFragment and will be attached to several activity. So I am creating a method to set the header of the ListFragment.
The problem is the getListView() method is returning null, although I call the addHeader after the list is shown.
Why is the the getListView() is always null?
Here is my code:
public class NewsListFragment extends ListFragment {
private final int topNewsCount = 5;
private DBNewsDataSource dataSource;
private Activity myActivity;
private Context myContext;
private boolean isHome;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isHome = true;
myActivity = getActivity();
Bundle extras = myActivity.getIntent().getExtras();
if (extras != null) {
isHome = extras.getBoolean("isHome");
}
dataSource = new DBNewsDataSource(getActivity());
dataSource.open();
List<DBNews> news = dataSource.getAllNews();
List<String> titleList = new ArrayList<String>();
dataSource.close();
for(int i = 0; i< (isHome?topNewsCount:news.size()); i++)
{
titleList.add(news.get(i).getTitle());
}
NewsListArrayAdapter adapter = new NewsListArrayAdapter(getActivity(),news,titleList,isHome);
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Do something with the data
}
public void addHeader(View v)
{
ListView lv = getListView();
lv.addHeaderView(v);
}
Here is the activity that call the Fragment
public class HomeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.template_activity_home);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
NewsListFragment frgNews = new NewsListFragment();
MainSlideShowFragment frgSS = new MainSlideShowFragment();
View vw = frgSS.getView();
frgNews.addHeader(vw);
fragmentTransaction.add(R.id.layout_news_list , (Fragment) frgNews);
fragmentTransaction.commit();
//frgNews.addHeader(vw);
}
Override onCreate view and let it returns a View wich contains a ListView with id android:id="#android:id/list"
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.cart_list,
null);
return view;
}
You are using a fragment but haven't called
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
This is where the layout will be inflated. Hence it is null as it is not yet inflated.