i'm facing an issue i can't seem to resolve and i'd like some help.
My app is composed by an activity containing a fragment. After the user taps on a suggestion, activity's method onSuggestionClicked(String cardId) is called and activity's content is replaced with a new PagerFragment_new.
@Override
public void onSuggestionClicked(String cardId) {
Log.d("activity","ID:\t" + cardId);
PagerFragment_new pagerFragment = PagerFragment_new.getInstance(
Injection.provideMtgDatabase(getApplicationContext()),
activityPresenter.getAllCardExpansionIds(cardId),
this);
ActivityUtils.replaceFragment(getSupportFragmentManager(), pagerFragment, R.id.MTGRecallActivity_container);
}
PagerFragment_new contains a ViewPager to display CardInfoFragment_new
public class PagerFragment_new extends MtgRecallFragment_new implements PagerFragmentContract.View {
private View fragmentView;
private ViewPager viewPager;
private PagerFragmentContract.Presenter presenter;
private ScreenSlidePageAdapter_new adapter;
private MtgDatabase database;
private String[] printingsIds;
private ScreenSlidePageAdapter_new.ActivePresenterListener listener;
public PagerFragment_new() {
//Required empty constructor
}
public static PagerFragment_new getInstance(MtgDatabase database, String[] printingsIds, ScreenSlidePageAdapter_new.ActivePresenterListener listener) {
PagerFragment_new instance = new PagerFragment_new();
instance.setDatabase(database);
instance.setPrintingsIds(printingsIds);
instance.listener = listener;
return instance;
}
//other stuff
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
setRetainInstance(true);
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
fragmentView = inflater.inflate(R.layout.fragment_pager, container, false);
viewPager = (ViewPager) fragmentView.findViewById(R.id.PAGERFRAG_VIEWPAGER);
adapter = new ScreenSlidePageAdapter_new(getChildFragmentManager(), printingsIds, database, viewPager);
adapter.setListener(listener);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(1);
return fragmentView;
}
@Override
public void setPresenter(PagerFragmentContract.Presenter presenter) {
this.presenter = presenter;
}
}
The adapter to manage ViewPager's element's is ScreenSlidePageAdapter_new, it is responsible of instantiating CardInfoFragments.
public class ScreenSlidePageAdapter_new extends FragmentStatePagerAdapter {
private String[] printingsIds;
private String firstItemId;
private MtgDatabase database;
public ActivePresenterListener activity;
private ViewPager viewPager;
public ScreenSlidePageAdapter_new(FragmentManager fm, String[] printingsIds, MtgDatabase database, ViewPager viewPager) {
super(fm);
this.printingsIds =printingsIds;
this.database = database;
this.firstItemId = printingsIds[0];
this.viewPager = viewPager;
}
@Override
public Fragment getItem(int position) {
//todo create a bundle with cardId
Bundle bundle = new Bundle();
bundle.putString("CardID", printingsIds[position]);
bundle.putString("FirstItemId", firstItemId);
CardInfoFragment_new cardInfoFragment_new = CardInfoFragment_new.getInstance(viewPager);
cardInfoFragment_new.setArguments(bundle);
CardInfoPresenter cardInfoPresenter = new CardInfoPresenter(cardInfoFragment_new, database);
activity.setActivePresenter(cardInfoPresenter);
return cardInfoFragment_new;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
public void setListener(ActivePresenterListener listener) {
this.activity = listener;
}
@Override
public int getCount() {
return printingsIds.length;
}
public interface ActivePresenterListener {
void setActivePresenter(BasePresenter presenter);
}}
Finally, here's the code of CardInfoFragment:
public class CardInfoFragment_new extends MtgRecallFragment_new
implements CardInfoContract.View,
CardPrintingsAdapter.OnItemClickListener {
private ViewPager viewPager;
public CardInfoContract.Presenter presenter;
private View fragmentView;
private MTGCard mtgCard;
RecyclerView printingsRecyclerView;
CardPrintingsAdapter cardPrintingsAdapter;
private String firstItemId; //the first id
public CardInfoFragment_new() {
//required empty constructor
}
private void setViewPager(ViewPager viewPager) {
this.viewPager = viewPager;
}
public static CardInfoFragment_new getInstance(ViewPager viewPager) {
CardInfoFragment_new cardInfoFragment_new = new CardInfoFragment_new();
cardInfoFragment_new.setViewPager(viewPager);
return cardInfoFragment_new;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
setRetainInstance(true);
presenter.start();
String cardId = getArguments().getString("CardID");
firstItemId = getArguments().getString("FirstItemId");
mtgCard = presenter.getCardData(cardId);
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
fragmentView = inflater.inflate(R.layout.fragment_card_info_new, container, false);
setUpCardInfoView(fragmentView);
return fragmentView;
}
public void setUpCardInfoView(final View view){
//others view set-up action omitted
cardprintingsContainer = (LinearLayout) view.findViewById(R.id.CARDINFO_printingsContainer);
printingsRecyclerView = (RecyclerView)fragmentView.findViewById(R.id.CARDINFO_printings_recyclerView);
final List<String> printings = presenter.getCardPrintings(firstItemId, mtgCard.getName());
if (printings.size() < 40) {
setupPrintings(printings,printingsRecyclerView);
}
else {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout printingsRow = new LinearLayout(getContext());
printingsRow = (LinearLayout)inflater.inflate(R.layout.card_info_printings_row,printingsRow,true);
printingsRow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setupPrintings(printings, printingsRecyclerView);
}
});
ImageView printingssetImage = (ImageView)printingsRow.findViewById(R.id.CARDINFO_printingsRow_setImage);
printingssetImage.setVisibility(View.INVISIBLE);
TextView printingssetName = (TextView)printingsRow.findViewById(R.id.CARDINFO_printingsRow_setName);
printingssetName.setText("Click to see all the "+printings.size()+ " versions");
cardprintingsContainer.addView(printingsRow);
}
}
public void setupPrintings(List<String> printings, RecyclerView recyclerView) {
cardPrintingsAdapter =
new CardPrintingsAdapter(getContext(), printings);
cardPrintingsAdapter.setOnItemClickListener(this);
UnscrollableLayoutManager layoutManager = new UnscrollableLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
recyclerView.setAdapter(cardPrintingsAdapter);
recyclerView.setLayoutManager(layoutManager);
}
@Override
public void onItemClick(View itemView, int position) {
int i = viewPager.getAdapter().getCount();
viewPager.setCurrentItem(position);
}
@Override
public void onDestroy() {
presenter = null;
mtgCard = null;
super.onDestroy();
}}
When user click on a RecyclerView item, CardInfoFragment's method onItemClick(View itemView, int position) is called and the viewpager is set to current position. Everything as expected.
THE PROBLEM
When the orientation changes, fragments are able to retain their states, but viewPager.setCurrentItem(position) does nothing, and i'm not able to change displayed fragment.
I already checked:
- ViewPager instance and adapters instances corresponds to those passed to Fragments
- onItemClick is fired
- this questions question1 question2
If i use
android:configChanges="orientation|screenSize"
in manifest it works even after config changes, but i don't want to use this option since is discouraged. Thanks in advance!