I have faced this issue, maybe there is already the same issue, but I cannot find in this page. So my problem is that I have my activity, which initialize ViewPager and I have 2 fragments in this viewpager.
My Activity:
public class ShoppingDetailsActivity extends BaseActivity {
ViewPagerAdapter adapter;
#Bind(R.id.view_pager)
ViewPager viewPager;
#Bind(R.id.pager_tabs)
PagerSlidingTabStrip pagerSlidingTabStrip;
int shop_id;
int id;
int shop_sub_id;
int subId;
int shop_sub_sub_id;
int subSubId;
int shop_detail_id;
int detailId;
public static final String SHOP_ID = "shop_id";
public static final String SHOP_SUB_ID = "shop_sub_id";
public static final String SHOP_SUB_SUB_ID = "shop_sub_sub_id";
public static final String SHOP_DETAIL_ID = "shop_detail_id";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityComponent().inject(this);
setContentView(R.layout.activity_shopping_details);
ButterKnife.bind(this);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
pagerSlidingTabStrip.setViewPager(viewPager);
shop_id = getIntent().getIntExtra(SHOP_ID, id);
shop_sub_id = getIntent().getIntExtra(SHOP_SUB_ID, subId);
shop_sub_sub_id = getIntent().getIntExtra(SHOP_SUB_SUB_ID, subSubId);
shop_detail_id = getIntent().getIntExtra(SHOP_DETAIL_ID, detailId);
}
}
My Adapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new InfoAdminFragment();
break;
case 1:
fragment = new ViewAdminFragment();
break;
default:
break;
}
return fragment;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return "InfoAdminFragment";
} else if (position == 1) {
return "ViewAdminFragment";
} else {
return super.getPageTitle(position);
}
}
}
As you can see in My Activity I have a lot of IDs using getIntent() and get them successfully, but I also need somehow to pass to my both fragments in ViewPager, how can I make solve this issue?
Pass the ID's as bundle to ViewPager adapter from your activity
adapter = new ViewPagerAdapter(getSupportFragmentManager(), getIntent().getExtras());
Modify your ViewPager adapter as below
public class ViewPagerAdapter extends FragmentPagerAdapter {
private Bundle bundle;
public ViewPagerAdapter(FragmentManager fm, Bundle bundle) {
super(fm);
this.bundle = bundle;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new InfoAdminFragment();
break;
case 1:
fragment = new ViewAdminFragment();
break;
default:
fragment = new InfoAdminFragment();
break;
}
fragment.setArguments(bundle);
return fragment;
}
//other code
}
And retrieve the bundle in your fragments
Bundle bundle = getArguments();
shopId = bundle.getInt(ShoppingDetailsActivity.SHOP_ID);
Check your code with this one:
private int shop_id;
private int shop_sub_id;
private int shop_sub_sub_id;
private int shop_detail_id;
public void setExtraData(int shopId, int shopSubId, shopSubSubId, shopDetailId) {
this.shop_id = shopId;
this.shop_sub_id = shopSubId;
this.shop_sub_sub_id = shopSubSubId;
this.shop_detail_id = shopDetailId;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new InfoAdminFragment();
break;
case 1:
fragment = new ViewAdminFragment();
break;
default:
break;
}
setBundleData(fragment);
return fragment;
}
public void setBundleData(Fragment fragment){
Bundle bundle = new Bundle();
bundle.putInt("shop_id", shop_id);
bundle.putInt("shop_sub_id", shop_sub_id);
bundle.putInt("shop_sub_sub_id", shop_sub_sub_id);
bundle.putInt("shop_detail_id", shop_detail_id);
fragment.setArguments(bundle);
}
And in your activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityComponent().inject(this);
setContentView(R.layout.activity_shopping_details);
ButterKnife.bind(this);
shop_id = getIntent().getIntExtra(SHOP_ID, id);
shop_sub_id = getIntent().getIntExtra(SHOP_SUB_ID, subId);
shop_sub_sub_id = getIntent().getIntExtra(SHOP_SUB_SUB_ID, subSubId);
shop_detail_id = getIntent().getIntExtra(SHOP_DETAIL_ID, detailId);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.setExtraData(shop_id, shop_sub_id, shop_sub_sub_id, shop_detail_id);
viewPager.setAdapter(adapter);
pagerSlidingTabStrip.setViewPager(viewPager);
}
In your fragment you can get:
getArguments().getInt(/*Key*/, /*Default value*/);
like:
getArguments().getInt("shop_id", -1);
You can achieve the same above scenario by passing intent rather than single-single values as I am doing here in setExtraData method of adapter.
Related
I'm trying to send data from MainActivity to one of the fragments which was created using ViewPager2.
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
ViewPager2 viewPager = findViewById(R.id.viewPager);
MainPagerAdapter pagerAdapter = new MainPagerAdapter(this);
viewPager.setAdapter(pagerAdapter);
}
MainPagerAdapter:
public class MainPagerAdapter extends FragmentStateAdapter
{
public MainPagerAdapter(#NonNull FragmentActivity fragmentActivity)
{
super(fragmentActivity);
}
#NonNull
#Override
public Fragment createFragment(int position)
{
switch (position)
{
case 0:
return new Fragment1();
case 1:
return new Fragment2();
default:
return new Fragment3();
}
}
#Override
public int getItemCount()
{
return 3;
}
}
I send data in MainActivity:
Fragment1 fragment1 = new Fragment1();
Bundle bundle = new Bundle();
bundle.putInt("1", 1);
fragment1.setArguments(bundle);
And try to get it in Fragment1:
Bundle bundle = this.getArguments();
if (bundle != null)
{
int i = bundle.getInt("1", 0);
Log.d(Constants.LOG_TAG, "" + i);
}
But it always comes with an empty bundle because the fragment is created when the viewpager scrolls through it.
How can I send data to Fragment when MainActivity is created?
My solution:
MainActivity:
pagerAdapter = new MainPagerAdapter(this);
pagerAdapter.setData(fragment1Container);
MainPagerAdapter:
public class MainPagerAdapter extends FragmentStateAdapter
{
private Fragment1Container fragment1Container;
private Fragment2Container fragment2Container;
public void setData(Fragment1Container container)
{
fragment1Container = container;
}
public void setData(Fragment2Container container)
{
fragment2Container = container;
}
#NonNull
#Override
public Fragment createFragment(int position)
{
switch (position)
{
case 0:
Fragment1 fragment1 = new Fragment1();
Bundle bundle = new Bundle();
Gson gson = new Gson();
bundle.putString("fragment1Container", gson.toJson(fragment1Container));
fragment1.setArguments(bundle);
return fragment1;
case 1:...
Fragment1:
private Fragment1Container fragment1Container;
if (bundle != null)
{
Gson gson = new Gson();
String jsonString = bundle.getString("fragment1Container");
Type entityType = new TypeToken<Fragment1Container>(){}.getType();
fragment1Container = gson.fromJson(jsonString , entityType );
}
my recyclerView Adapter - Activity-1
here i'm sending arguments to ViewPager Fragmnet using setArguments()
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString("projectName", jobCardLists.get(position).getProject());
// set MyFragment Arguments
DetailsFragment detailsFragment = new DetailsFragment();
detailsFragment.setArguments(bundle);
Intent intent = new Intent(context, JobCardViewActivity.class);
context.startActivity(intent);
});
}
Activity-2 which contains ViewPager - Tab layout
public class JobCardViewActivity extends AppCompatActivity {
private ViewPager mViewPager;
private Toolbar mToolbar;
private JobCardViewVPAdapter mViewPagerAdapter;
private TabLayout mTabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_job_card_view);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
//set TabLayout
setViewPager();
}
private void setViewPager() {
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPagerAdapter = new JobCardViewVPAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mViewPagerAdapter);
mTabLayout = (TabLayout) findViewById(R.id.tab);
mTabLayout.setupWithViewPager(mViewPager);
mTabLayout.getTabAt(0).setIcon(R.drawable.ic_home_white_24dp);
}
}
My viewPager Adapter
public class JobCardViewVPAdapter extends FragmentStatePagerAdapter {
private static int TAB_COUNT = 6;
public JobCardViewVPAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return DetailsFragment.newInstance();
case 1:
return WorkActivitiesFragment.newInstance();
case 2:
return DocumentsFragment.newInstance();
case 3:
return TasksFragment.newInstance();
case 4:
return WorkImagesFragment.newInstance();
case 5:
return NotesFragment.newInstance();
}
return null;
}
#Override
public int getCount() {
return TAB_COUNT;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 1:
return WorkActivitiesFragment.TITLE;
case 2:
return DocumentsFragment.TITLE;
case 3:
return TasksFragment.TITLE;
case 4:
return WorkImagesFragment.TITLE;
case 5:
return NotesFragment.TITLE;
}
return super.getPageTitle(position);
}
}
My ViewPager fragment class
here i'm getting NULL from getArguments()
public class DetailsFragment extends Fragment {
private View view;
private Activity activity;
public static final String TITLE = "Details";
private String projectName;
public DetailsFragment() {
// Required empty public constructor
}
public static DetailsFragment newInstance() {
return new DetailsFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = getActivity();
if (getArguments() != null) {
Bundle bundle = getArguments();
projectName = bundle.getString("projectName");
} else {
Toast.makeText(activity, "NULL", Toast.LENGTH_SHORT).show();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_details, container, false);
TextView tvProjectName, startDate, endDate, assignedBy, workCategory, status;
tvProjectName = view.findViewById(R.id.tv_project_name);
tvProjectName.setText(projectName);
return view;
}
1.You can use Single Object (singleton) for your fragment.
In your fragment use,
private static DetailsFragment ourInstance = new DetailsFragment();
public static DetailsFragment newInstance() {
return ourInstance;
}
And in your onBindViewHolder(), use
DetailsFragment detailsFragment = DetailsFragment.newInstance();
detailsFragment.setArguments(bundle);
2.Or else, pass data between the activities
In your onBindViewHolder(), use
Intent intent = new Intent(context, JobCardViewActivity.class);
intent.putString("project", jobCardLists.get(position).getProject());
context.startActivity(intent);
and do,
1.in JobCardViewActivity,get the string and save it
myString=getIntent().getString("project"); //public String myString;
2.in fragment, use that saved string
tvProjectName.setText(((JobCardViewActivity)getActivity()).myString);
this is my ViewPager
private class ViewPagerAdapter extends FragmentPagerAdapter{
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
void addFragment(Fragment fragment, String title){
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position){
return mFragmentTitleList.get(position);
}
}
and in main activity,
public void setupViewPager() {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(NowPlayingFragment.newInstance(0), getString(R.string.now_playing));
adapter.addFragment(NowPlayingFragment.newInstance(1), getString(R.string.up_coming));
adapter.addFragment(NowPlayingFragment.newInstance(2), getString(R.string.popular));
mViewPager.setAdapter(adapter);
and this is my fragment.
public static NowPlayingFragment newInstance(int titleId){
NowPlayingFragment fragment = new NowPlayingFragment();
Bundle args = new Bundle();
args.putInt("title_flag", titleId);
NowPlayingFragment.titleId = titleId;
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
args = savedInstanceState;
mContext = getContext();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_now_playing, container, false);
mUnbinder = ButterKnife.bind(this, view);
Map<String, String> queryString;
queryString = ApiUtils.getQueryStrings(mContext);
Uri uri;
int titleId1 = 0;
if (args != null) {
titleId1 = args.getInt("title_flag");
}
Log.d("tag", "titleId = " + titleId1);
switch (titleId1){
case 0:
uri = ApiUtils.getNowPlayingUri(mContext, queryString);
break;
case 1:
uri = ApiUtils.getUpcomingUri(mContext, queryString);
break;
case 2:
uri = ApiUtils.getPopularUri(mContext, queryString);
break;
default:
uri = ApiUtils.getNowPlayingUri(mContext, queryString);
break;
}
new loadDiscoverList(getContext()).execute(uri);
return view;
}
I try to list three different movie list (now playing, upcoming, popular).
But it only shows now playing list on all three pages.
It seems like passing data from main activity to fragment is not working property, or store fragment argument problem. But I can't find what cause this issue and don't know how to fix it.
The problem is here args = savedInstanceState; it should be args = getArguments(); - at present only your default list in your switch statement is honoured. SavedInstanceState is for configuration changes, you want the Fragment arguments you added with the static Fragment generator method.
You don't have make a cache for fragment like:
private final List mFragmentList = new ArrayList<>();
ViewPager already do it for you.
Try to return the corresponding new instances of fragments inside the method getItem() in your adapter.
I have a weird problem.
In the main activity I use this code:
public class MyPagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = {"Laatste Nieuws", "Uitrukken", "Voertuigen", "Contact", "Top Grossing"};
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = NaviContentFragment.newInstance(position);
break;
case 1:
fragment = NaviContentFragmentTwo.newInstance(position);
break;
case 2:
fragment = NaviContentFragment.newInstance(position);
break;
case 3:
fragment = NaviContentFragment.newInstance(position);
break;
case 4:
fragment = NaviContentFragment.newInstance(position);
break;
default:
break;
}
return fragment;
}
}
So when I open a tab it will open a new fragment. And when I open tab 1 labeled "Uitrukken" it should open a other fragment than the other ones. This fragment:
public class NaviContentFragmentTwo extends Fragment {
private static final String ARG_POSITION = "position";
public static NaviContentFragment newInstance(int position) {
NaviContentFragment fragment = new NaviContentFragment();
Bundle b = new Bundle();
b.putInt(ARG_POSITION, position);
fragment.setArguments(b);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = rootView = inflater.inflate(R.layout.navi_content_two, container, false);
TextView textViewNaviConTwo = (TextView) rootView.findViewById(R.id.textViewNaviConTwo);
textViewNaviConTwo.setText("HALLLOOOTJES :)");
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}
With the Text "HALLLOOOTJES :)". And only in that fragment. But the other way around happens. This text is show on all the tabs except for tab number 1.
I'm certainly missing something.
Screenshots:
It should say "HALLLOOOTJES :)"
In your NaviContentFragmentTwo class, you are returning a NaviContentFragment from your newInstance method.
My guess is you should be returning a NaviContentFragmentTwo instance.
So it should be something like..
public class NaviContentFragmentTwo extends Fragment {
private static final String ARG_POSITION = "position";
public static NaviContentFragmentTwo newInstance(int position) {
NaviContentFragmentTwo fragment = new NaviContentFragmentTwo ();
Bundle b = new Bundle();
b.putInt(ARG_POSITION, position);
fragment.setArguments(b);
return fragment;
}
This code could be the possible cause:
public static NaviContentFragment newInstance(int position) {
NaviContentFragment fragment = new NaviContentFragment();
Bundle b = new Bundle();
b.putInt(ARG_POSITION, position);
fragment.setArguments(b);
return fragment;
}
Try replacing NaviContentFragment to NaviContentFragmentTwo.
If I ave an activity with a viewPAger on it and two sets of data that I want to display, is it best to have one fragment and load information into textViews based on position passed from activity or better to create more than one fragment and load the one needed?
Any help is greatly appreciated.
public class testFragment extends Fragment {
private static final String ARG_PAGE = "pageNumber";
private static final int DEFAULT_INT = 0;
TextView header, sd1;
int h1, page = 0;
public testFragment (){
}
public testFragment newInstance(int pageNumber) {
testFragment fragment = new testFragment ();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
page = getArguments().getInt(ARG_PAGE);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_high_scores_page, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
header = (TextView) getActivity().findViewById(R.id.modes_header);
sd1 = (TextView) getActivity().findViewById(R.id.stat_det_1);
switch (page) {
case 1:
header.setText(R.string.easy_mode);
h1 = DEFAULT_INT;
sh1 = DEFAULT_INT;
sd1.setText(String.valueOf(h1));
break;
case 2:
header.setText(R.string.medium_mode);
h1 = DEFAULT_INT + 1;
sh1 = DEFAULT_INT + 1;
sd1.setText(String.valueOf(h1));
break;
default:
header.setText(R.string.action_restart);
h1 = DEFAULT_INT;
sh1 = DEFAULT_INT;
sd1.setText(String.valueOf(h1));
break;
}
}
public void setTextViewInfo(){
sd1.setText(String.valueOf(h1));
}
}
Or would it be better to send the information from my activity and load one or multiple fragments instead?
public class testActivity extends FragmentActivity {
private static final int NUM_PAGES = 8;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testActivity);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.high_scores_pager);
mPagerAdapter = new testActivity (getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
super.onBackPressed();
} else {
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
private class testActivityAdapter extends FragmentStatePagerAdapter {
public testActivityAdapter (FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
testFragment tf1 = new testFragment ();
notifyDataSetChanged();
return easy.newInstance(position);
case 1:
testFragment2 tf2 = new testFragment ();
notifyDataSetChanged();
return medium.newInstance(position);
default:
testFragment d = new testFragment ();
return d.newInstance();
}
}
#Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
edit:
In my adapter, I just tried
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return HighScoresEasyFragment.newInstance(position);
case 1:
return HighScoresMediumFragment.newInstance(position);
case 2:
return HighScoresExpertFragment.newInstance(position);
case 3:
return HighScoresBrainFartFragment.newInstance(position);
case 4:
return HighScoresClassicFragment.newInstance(position);
case 5:
return HighScoresPuzzleFragment.newInstance(position);
case 6:
return HighScoresPerfectFragment.newInstance(position);
case 7:
return HighScoresPowerFragment.newInstance(position);
default:
return HighScoresEasyFragment.newInstance(position);
}
ugh, but it didn't load anything... my constructor is now...:
public static HighScoresEasyFragment newInstance(int pageNumber) {
HighScoresEasyFragment fragment = new HighScoresEasyFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
It loaded the first page's header but no data and it didn't load anything for second to 8th fragments...
You should call notifyDataChanged() from your activity using your adapter reference. Basically notifyDataChanged just tells all your fragments in your adapter that data has changed and they should refresh themselves. Remove notifyDataChanged from your getItem() method and put it when you change data in your activity.