I am using ViewPager in my activity and it only has two fragments, both implemented in similar structure as follow, so there should always be a fragment returned when getInstanced is called:
public class ListReminderFragment extends Fragment {
private View rootView;
private static ListReminderFragment listReminderFragment;
public static ListReminderFragment getInstance() {
if(listReminderFragment != null)
return listReminderFragment;
else {
listReminderFragment = new ListReminderFragment();
return listReminderFragment;
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.content_main_screen, container, true);
return rootView;
}
#Nullable
#Override
public View getView() {
return rootView;
}
}
This is my adapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return ListReminderFragment.getInstance(); // temporary
}
#Override
public int getCount() {
return 2;
}
}
And I am initialising my ViewPager as below, in OnCreate() in the activity that has the ViewPager:
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
ViewPager viewPager = (ViewPager) findViewById(R.id.main_view_pager);
viewPager.setAdapter(viewPagerAdapter);
But when I call viewPager.getChildAt(), viewPagerAdapter.getItem(0).getView(), they both return null,
when I call viewPager.getChildCount(), it returns 0 instead of 2.
How should I access the views in side the fragment in ViewPager?
Related
I am trying to refresh the current fragment in the tabbed layout of my viewpager. I have one fragment (UserProgressFragment) that creates the ViewPager and sets the adapter (UserProgressAdapter) along with creating tabbed layout.
In my UserProgressAdapter, in the getItem() method I am returning two other fragments, (UserWeightTrackerFragment and UserCalorieCounterFragment) based on which tab i am on.
My issue is how do i refresh the fragment and update its content/view from the UserCalorieCounterFragment on a button click, because access to the viewpager and adapter are set in the UserProgressFragment? I have considered notifyDataChange for the adapter but i dont know how to call this from this class as it is set up on the UserProgressFragment class. The purpose of wanting to refresh this page is to update a specific view which is a chart, if context is needed.
I have attached the code below:
UserProgressFragment
public class UserProgressFragment extends Fragment{
public static UserProgressFragment newInstance() {
return new UserProgressFragment();
}
public UserProgressFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_user_progress, container, false);
ViewPager viewPager = view.findViewById(R.id.progress_viewpager);
viewPager.setAdapter(new UserProgressTabsAdapter(getChildFragmentManager()));
TabLayout tabLayout = view.findViewById(R.id.progress_sliding_tabs);
tabLayout.setupWithViewPager(viewPager, true);
return view;
}
}
UserProgressTabsAdapter
public class UserProgressTabsAdapter extends FragmentStatePagerAdapter {
private static final int PAGE_COUNT = 2;
private String tabTitles[] = new String[]{"Weight Tracker", "Calorie Counter"};
public UserProgressTabsAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return UserWeightTrackerFragment.newInstance(position);
case 1:
return UserCalorieCounterFragment.newInstance(position + 1);
}
return null;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
UserCalorieCounterFragment (need to refresh this one)
public class UserCalorieCounterFragment extends Fragment implements View.OnClickListener, AdapterView.OnItemSelectedListener {
public static final String ARG_PAGE = "ARG_PAGE";
public static UserCalorieCounterFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
UserCalorieCounterFragment fragment = new UserCalorieCounterFragment();
fragment.setArguments(args);
return fragment;
}
public UserCalorieCounterFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int mPage = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_user_calorie_counter, container, false);
Button mAddCalories = view.findViewById(R.id.btn_add_calorie);
mAddCalories.setOnClickListener(this);
return view;
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_add_calorie:
//REFRESH/UPDATE HERE
break;
}
}
You can create a public method in your fragment which contains the view pager which will contain the notifyDataSetChanged() function. And in the view pager fragment/item, you can call getParentFragment() and type cast it to your parent/first fragment and access that public method to notifyDataSetChanged().
EDIT:
I'm new in android and i try to use fragments in my app. I try to use a fragment function in my activity but i got a null pointer exception..
Fragment:
public class VideoviewFragment extends Fragment {
private View card;
public static VideoviewFragment create() {
return new VideoviewFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_videoview, container, false);
card = (View) view.findViewById(R.id.card_video);
return view;
}
public void setalphacard(float value){
card.setAlpha(value);
}
}
In main activity i want to do that for example (i simplified my code):
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Viewpager
final SmartFragmentStatePagerAdapter adapterViewPager;
final ViewPager viewPager = (ViewPager) findViewById(R.id.am_view_pager);
adapterViewPager = new MainPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapterViewPager);
final VideoviewFragment videoviewFragment = (VideoviewFragment) adapterViewPager.getRegisteredFragment(2);
videoviewFragment.setalphacard(0.3f);
}
}
Main pager adapter:
public class MainPagerAdapter extends SmartFragmentStatePagerAdapter {
public MainPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return CameraFragment.create();
case 1:
return OptionFragment.create();
case 2:
return VideoviewFragment.create();
}
return null;
}
#Override
public int getCount() {
return 3;
}
}
You just have to declare the View globally like this:
public class VideoviewFragment extends Fragment {
private View card;
public static VideoviewFragment create() {
return new VideoviewFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_videoview, container, false);
card = (View) view.findViewById(R.id.card_video);
return view;
}
public void setalphacard(float value){
card.setAlpha(value);
}
}
Declare your View Object globally in your fragment.
I have a simple FragmentPagerAdapter :
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
pagerAdapterList = new ArrayList<>();
super(fm);
}
#Override
public Fragment getItem(int position) {
PagerAdapter fragment;
if (position > pagerAdapterList.size() - 1) {
fragment = new PagerAdapter(followRequests.get(position));
pagerAdapterList.add(fragment);
} else
return pagerAdapterList.get(position);
return fragment;
}
public int removeView (ViewPager pager, int position)
{
pager.setAdapter (null);
pagerAdapterList.remove (position);
data.remove (position);
pager.setAdapter (this);
return position;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
getItem(position);
return super.instantiateItem(container, position);
}
#Override
public int getCount() {
return data.size();
}
}
and PagerAdapter class:
public class PagerAdapter extends Fragment {
Data data;
private View overlayView;
public PagerAdapter() {
}
public PagerAdapter(Data data) {
this.data= data;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.notification_header_fragment_pager, container, false);
TextView id_txtView = (TextView)
overlayView = (View) rootView.findViewById(R.id.viewOverlay);
//bind some data for example id_txtView.setText(data.getText());
return rootView;
}
public void showOverlayView() {
if(overlayView != null)
overlayView.setVisibility(View.VISIBLE);
}
}
first I call
removeView(mViewPager, position);
then I get new data, and then call
adapter.notifyDataSetChanged();
All things work fine and I can bind new data in PagerAdapter and show it on View Pager.
But when I call
((PagerAdapter) adapter.getItem(mViewPager.getCurrentItem())).showOverlayView();
I get current fragment without any reference to its ui components(like overlayView) and they are null !!
what's my wrong?
Please help me, Thanks.
I have a ViewPager that I want to add Fragments to.
The ViewPager is viewed correctly on the screen but unfortunately it does not hold any content.
I have seen the suggestion in some posts to replace
getSupportFragmentManager()
with
getChildFragmentManager()
But I need the ActionBar. Unfortunately the ChildFragmentmanager is not available in the AppCompatActivity.
While debugging I have realized that the Fragment's onCreateView() method is called and it returns a layout.
Question: How can I make the Fragments visible? And were is the main difference from my code to that sample ?
Activity:
public class ViewPagerActivity extends AppCompatActivity {
private ViewPager mViewPager;
private List<Location> locationList = new ArrayList<>();
private locationsBaseHandler db;
private CustomPagerAdapter mAdapter;
private Location mLocation;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpager);
locationList.add(someData);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mAdapter = new CustomPagerAdapter(this, getSupportFragmentManager(), locationList);
mViewPager.setAdapter(mAdapter);
}
}
Pager Adapter:
public class CustomPagerAdapter extends FragmentPagerAdapter {
private Context mContext;
private List<Location> locationList = new ArrayList<>();
public CustomPagerAdapter(Context mContext, FragmentManager fm, List<Location> locationList) {
super(fm);
this.locationList.addAll(locationList);
this.mContext = mContext;
}
#Override
public Fragment getItem(int position) {
return LocationFragment.newInstance(position);
}
#Override
public int getCount() {
return 5;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return false;
}
}
Fragment:
public class LocationFragment extends Fragment {
private static final String ARG_LAYOUT_ID = "page_number";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_location, container, false);
return layout;
}
public static LocationFragment newInstance(int selectedIdForIndex) {
LocationFragment fragment = new LocationFragment();
Bundle args = new Bundle();
args.putInt(ARG_LAYOUT_ID, selectedIdForIndex);
fragment.setArguments(args);
return fragment;
}
public int getPageNumber() {
return getArguments().getInt(ARG_LAYOUT_ID);
}
}
Try to remove the method isViewFromObject in CustomPagerAdapter.
#Override
public boolean isViewFromObject(View view, Object object) {
return false;
}
We can see this comment to isViewFromObject:
Determines whether a page View is associated with a specific key object
as returned by {#link #instantiateItem(ViewGroup, int)}. This method is
required for a PagerAdapter to function properly.
I make a FragmentPagerAdapter
There is a fragment which has a pager.
And the pager show 3 fragments and it works well.
But, After application cache clearing,
(It means... long time has passed application service backgrounded)
only pager showing up and 3 fragments have empty layout (white space).
As a result checking Log, I caught some problem lines...
After clearing cache, SectionsPagerAdapter() constructure called then
getItem() method never called.
Please Help me
public class ReviewFragment extends SherlockFragment {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.review_fragment, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) getActivity().findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new BFragment();
} else {
return new CFragment();
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "1";
case 1:
return "2";
}
return null;
}
}