I have some sliders inside recyclerview among some other items. this is my pager adapter:
class PagerFragmentAdapter extends FragmentStatePagerAdapter {
public PagerFragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
and i call setup on binding viewholder:
setup(RecyclerView.ViewHolder holder) {
pos = holder.getAdapterPosition();
if (pagerHolder == null) {
pagerHolder = (PagerHolder) holder;
viewPager = pagerHolder.getViewPager();
adapter = new PagerFragmentAdapter(fragmentManager);
viewPager.setAdapter(adapter);
pagerHolder.bindAdapter();
} else if(adapter!=null)
adapter.notifyDataSetChanged();
}
the first slider in recyclerview is OK but others are not OK!!
non of the fragments are loaded! and if i scroll it just shows first page of pager not all of them.
I have also tried creating fragments inside getItem() method but nothing changed..
Related
I have a ViewPager and Tablayout that shows nth number of items. The Tabs are populated with the correct page titles and the ViewPager contained Fragments display the correct fine except that the selected Tab is not synched with the ViewPager current item.
The selected Tab position is 1 less than the position of viewpager current item. Here is the Viewpager adapter.
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm){
super(fm);
}
#Override
public Fragment getItem(int position) {
Recipe selectedRecipe = getRecipeList().get(position);
return RecipeDetailFragment.newInstance(selectedRecipe.getId);
}
#Override
public int getCount() {
return .getRecipeList().size();
}
#Override
public CharSequence getPageTitle(int position) {
Recipe selectedRecipe = .getRecipeList().get(position);
String title = selectedRecipe.getTitle();
return title ;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Here is how I setup the ViewPager
private void setupViewPager() {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
Here is what the output looks like
Edit 1:
I think the problem have to do with how the getItem method of the ViewPager is being called, here is log of left and right scroll for10 items
instead of using static variable in fragment you can use,
public function in fragment like below.
add
#Override
public Fragment getItem(int position) {
Recipe selectedRecipe = getRecipeList().get(position);
RecipeDetailFragment receiptFRagment= new ReceiptFragment();
receiptFragment.setData(selectedRecipe.getId);
return receiptFragment;
}
instead of this
#Override
public Fragment getItem(int position) {
Recipe selectedRecipe = getRecipeList().get(position);
return RecipeDetailFragment.newInstance(selectedRecipe.getId);
}
Add public function in fragment,
public void setData(int id){
this.id= id;
}
Finally, this is how I synched the ViewPager selected item with the Tablayout selected tab.
void selectPage(final int pageIndex){
new Handler().postDelayed(
new Runnable() {
#Override public void run() {
tabLayout.setSmoothScrollingEnabled(true);
tabLayout.setScrollPosition(pageIndex, 0f, true);
}
}, 100);
}
Then I called this method from two places, first when I setup Viewpager
recipePosition = getIntent().getIntExtra(Constants.RECIPE_POSITION, 0);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
if (recipePosition > 0){
recipePosition--;
}
viewPager.setCurrentItem(recipePosition,true);
selectPage(recipePosition);
And then second in the setItem
Recipe selectedRecipe = getRecipeList().get(position);
RecipeDetailFragment receiptFRagment= new ReceiptFragment();
receiptFragment.setData(selectedRecipe.getId);
selectPage(position);
return receiptFragment;
Its works, I still could not understand why these are not synched by default!
I use FragmentStatePagerAdapter to manage my ViewPager. I have overwritten "getItemPosition" function. Here is my code:
mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
#Override
public Fragment getItem(int position) {
Crime c = mCrimes.get(position);
return CrimeFragment.newInstance(c.getmId());
}
#Override
public int getCount() {
return mCrimes.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
});
But the problem is that when I delete the first fragment, the last fragment will be deleted, but others work well. I don't know why.
I use a PageViewer to scroll through two types of fragments.
One of them has an EditText the other multiple buttons.
Upon entering the EditText Fragment I automatically open the softkeyboard. Upon entering the Button Fragment i close it.
This works fine.
The problem is that I have multiple EditText Fragments as direct neighbours to each other.
-> I dont want the keyboard to be closed when transitioning from one EditText Fragment to the next.
For this I somehow need to predict the class to which I am transitioning next.
Is there a way to achieve this?
Note: I close the keyboard in the pageTransform method as soon as a swipe movement occurs.
EDIT
because of an request in the comments here my PagerAdapter:
public class ButtonCollectionPagerAdapter extends FragmentStatePagerAdapter {
public ButtonCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
private Fragment currentFragment;
#Override
public Fragment getItem(int i) {
Bundle args = new Bundle();
List<MultipleChoiceQuestion> multipleChoiceQuestions = QuestionTexts.getMCQuestionTexts();
List<String> questionTexts = QuestionTexts.getQuestionTexts();
if(i < multipleChoiceQuestions.size()){
String question = multipleChoiceQuestions.get(i).getText();
ArrayList<String> choices = (ArrayList<String>) multipleChoiceQuestions.get(i).getChoices();
currentFragment = ButtonFragment.newInstance(question, choices, i);
} else if(i < (multipleChoiceQuestions.size() + questionTexts.size())){
currentFragment = TextViewFragment.newInstance(questionTexts.get(i - multipleChoiceQuestions.size()), i);
} else {
currentFragment = SendFragment.newInstance(i);
}
return currentFragment;
}
#Override
public int getCount() {
return 23;
}
#Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object){
super.setPrimaryItem(container, position, object);
currentFragment = (Fragment) object;
((PagerAdapterUpdateProgress) object).onGettingPrimary(position);
}
public Fragment getCurrentFragment() {
return currentFragment;
}
}
I think the more simple way to do that is to open/close keyboard directly from your fragments. You can determine when your fragment becomes visible by overriding setUserVisibleHint method of your fragment. The code in this method for your EditText Fragment should just show keyboard, and the code for other fragment should hide keyboard.
This is an interesting question.
I believe that you can achieve what you are doing by using ViewPager.OnPageChangeListener listener especially onPageSelected(int position) method in which we could get the position of the currently selected fragment after the swipe animation has finished.
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Log.d("ViewPager", "Page selected " + position);
onPageSelectedLogic(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
// This is because the first fragment doesn't fire the OnPageChangeListener.
onPageSelectedLogic(0);
an this is the implementation of onPageSelectedLogic method
private void onPageSelectedLogic(int position) {
// Check the type of the fragment editable vs button
if(!mPagerAdpater.isFragmentEdiatable(position)) {
// Close the Keyboard
}
}
And this is how you should implement your PagerAdapter
class CustomPagerAdapter extends FragmentStatePagerAdapter {
private SparseBooleanArray fragmentsEditable = new SparseBooleanArray();
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fargment;
// get the fragment
if(some condition) {
// Get an editable fragment
fragmentsEditable.put(position, true);
} else {
fragmentsEditable.put(position, false);
}
return fragment;
}
#Override
public int getCount() {
return NUM_PAGES;
}
public boolean isFragmentEditable(int postion) {
return fragmentsEditable.get(postion);
}
}
I using view pager for swipe view for android app. I build view pager Dynamically. Like add and remove item. Now i want to know how to get exactly position of view pager items.For example, I have 3 items, i want to get 3rd number position when i am in 2nd or 1st item. i used viewPager.getCurrentItem() but it return where i am.
Please suggest me how to give personal ids of every viewpager items and used it in when item is background or on screen.Thanks please help me about this, i left 2 weeks already for this. Thanks in advance
public TabsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
return new MyWebBrowser();
}
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
#Override
public int getCount() {
return COUNT_TAB;
}
}
Now this code Under my fragment class, from WebView chrom class i want to set up title as website title.
#Override
public void onReceivedTitle(WebView view, String title) {
TAB_TITLE=title;
Toast.makeText(HomeActivity.this,title,Toast.LENGTH_LONG).show();
super.onReceivedTitle(view, title);
}
take a look at this Adapter:
class MyAdapter extends FragmentStatePagerAdapter
{
private final SparseArray<WeakReference<YourFragment>> mPageReferences;
public MyAdapter(FragmentManager fm) {
super(fm);
mPageReferences = new SparseArray<WeakReference<YourFragment>>();
}
#Override
public Fragment getItem(int i) {
WeakReference<YourFragment> fragment =
new WeakReference<YourFragment>(YourFragment.newInstance());
mPageReferences.put(i, fragment);
return fragment.get();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferences.remove(position);
}
#Override
public int getCount() {
return number of fragment;
}
public YourFragment getFragment(int key) {
return mPageReferences.get(key).get();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
WeakReference<YourFragment> fragment = new WeakReference<YourFragment>((YourFragment) super.instantiateItem(container,
position));
mPageReferences.put(position, fragment);
return fragment.get();
}
}
you can easily get the reference of any pages from mPageReferences BUT be careful because it may be null because it is possible that it has not created when you call it. you can use (getFragment(int key) to get the item at the position of key)
you can know the current position from the PagerAdapter.
by calling pageAdapter.getItemPosition(itemNumber)
link to the documentation
I created a viewpager and an adapter with fragments that contains 2 views. I want to make the second view in the fragment invisible when I click on the frist one. I implemented this method on my view to handle the click events
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
ImageFragment fragment = (ImageFragment) ImageGallery.fragmentmanager.findFragmentByTag("android:switcher:"+R.id.imagerpager+":"+position);
if (fragment != null) {
fragment.setTransparency();
}
return super.onSingleTapConfirmed(e);
}
All fragments I get are null. To make sure that my objects are not null, following works but for the wrong(preloaded) fragments
ImageFragment fragment = (ImageFragment) ImageGallery.fragmentmanager.findFragmentById(R.id.imagepager);
I`m quite sure I have to implement a FragmentTransition to my adapter to make fragmentmanager.findFragmentByTag work. But I could not figure out how to do that. My adapter looks like
public class GalleryAdapter extends FragmentStatePagerAdapter {
private int mCount = pictureUrlList.size();
public GalleryAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
ImageFragment fragment = ImageFragment.newInstance(position);
return fragment;
}
#Override
public int getCount() {
return mCount;
}
public void setCount(int count) {
if (count > 0 && count <= 10) {
mCount = count;
notifyDataSetChanged();
}
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Can anybody show me how to do that?