viewPager.setCurrentItem() is not working
Asked Answered
H

6

6

setCurrentItem() function isnt working for following android(java) code how to make it work ?

    Intent i = getIntent();
    int position = i.getIntExtra("img", 0);
    viewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
    ImageAdapter adapter = new ImageAdapter(this);
    viewPager.setAdapter(adapter);
    viewPager.setCurrentItem(position);
Hyohyoid answered 4/9, 2015 at 15:48 Comment(5)
Where are you setting the extra found in that intent?Luhe
i am giving the extra to the setCurrentItem() using positon so it can be displyed first.Hyohyoid
He means where you are sending the int extra called "img", from the first activityLeadwort
actually i want to open an image when i click on gridview so i am sending the position of clicked image to the new activity so i can show it in full screen and the image also should be swapable like you must have seen in a gallery app.Hyohyoid
Did you find the solution ? If yes, please share it.Kilburn
S
10

Frank is right. To provide the the scroll device independent, you should use onGlobalLayoutListener. Thereby, you can guarantee that the view is rendered when you call viewPager.setCurrentItem(position). Otherwise setCurrentItem won't have any effect since the view is not rendered yet.

viewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
        {
            @Override
            public void onGlobalLayout()
            {
                viewPager.setCurrentItem(position, false);
            }
        });

I know the question is already old but maybe someone else will find this usefull!

Scram answered 29/11, 2016 at 17:10 Comment(2)
Just in case someone's wondering now that my vote has taken this to the top of the list (because it was useful) and you probably won't be reading the answers in chronological order, the Frank in the answer is a commenter to a hack answer invoking a Runnable to delay setCurrentItem.Tortuous
Bear in mind that this can lead to unintended behavior. See the answer by Yosef https://mcmap.net/q/1587845/-viewpager-setcurrentitem-is-not-working.Bergius
I
7
private ViewPager viewPager;

@Override
public void onResume() {
 Intent i = getIntent();
int position = i.getIntExtra("img", 0);
viewPager.postDelayed(new Runnable() {

    @Override
    public void run() {
        viewPager.setCurrentItem(position);
    }
 }, 100);
}
Immunotherapy answered 5/9, 2015 at 9:17 Comment(3)
Although this might answer the question, one should also explain why and how the problem is solved.Squalid
if the system is slow it won't work, this is a workaround, not a solutionOverlook
This solution works but it does not seem right way to solve it. Anyone know what is the real underlying problem here?Tolly
C
6

just adding a shorter answer with androidx using view extension in kotlin

view_pager.doOnLayout {
    view_pager.setCurrentItem(position, false)
}

note that the previos answer using global layout is not removing the OnGlobalLayoutListener afterwords which is not advisable.

androidx ext doOnLayout does that.

Please, make sure you have a gradle dependency: implementation 'androidx.core:core-ktx:1.3.2'

Chilt answered 14/7, 2020 at 13:11 Comment(3)
Hi Yosef, I'm unable to find doOnLayout along with view_pager. I'm working on an android x project. Could you please help me here?Mutation
just add this import: import androidx.core.view.doOnLayout it's an extension to all viewsChilt
Thanks, Yosef. But my real problem was I'm not added implementation "androidx.core:core-ktx:1.3.2". Added the dependency and I'm able to find the method.Mutation
A
3

None of these answers worked for me - it took hours for me to find out that I'd forgotten to update getCount().

My getCount() method in my implementation of the FragmentPagerAdapter was displaying the incorrect count, so it could not change page since it was not part of its count.

Altitude answered 5/3, 2017 at 21:14 Comment(0)
V
0

This worked with me

if (mViewPager.getAdapter() != null)
    mViewPager.setAdapter(null);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(desiredPos);
Vincenty answered 4/10, 2021 at 9:23 Comment(0)
T
0

Ok, for me, I have been troubleshooting this issue like for 3 hours stright and I got to a point that I made it work this way

Before, I had this inside my ViewPagerStateAdapter

override fun getItemCount(): Int = 2

    override fun createFragment(position: Int): Fragment {
        return when (position) {
            1 -> myFragmentInstance1()
            else -> myFragmentInstance2()
        }
    }

Then for changing the pages I was using the following

private fun navigateTo1() {
        binding.viewPager.setCurrentItem(1, false)
    }

private fun navigateTo2() {
        binding.viewPager.setCurrentItem(2, false)
    }

First of all after initializing my viewpager adapter like this

private fun setupViewPager() {
        binding.viewPager.apply {
            adapter = MyViewPagerStateAdapter(this@MainFragment)
        }
    }

the initial position inside createFragment was 0 , so the else block was always called starting my viewpager with the inscance of myFragmentInstance2()

This is not all, after clicking and trying to setCurrentItem to another position the viewpager was changing only once and then it did not work anymore to switch pages

After long times of debug and research I tried to change the positions of the fragments like this

override fun getItemCount(): Int = 2

    override fun createFragment(position: Int): Fragment {
        return when (position) {
            0 -> myFragmentInstance1()
            else -> myFragmentInstance2()
        }
    }

which in first place worked for loading 0 as the default destination, and then switching with currentItem worked as expected

private fun navigateTo1() {
       binding.viewPager.setCurrentItem(0, false)
   }
    
private fun navigateTo2() {
       binding.viewPager.setCurrentItem(1, false)
   }

I also tried with

private fun navigateTo1() {
       binding.viewPager.currentItem = 0
   }
    
private fun navigateTo2() {
       binding.viewPager.currentItem = 1
   }

which puts a smoothTransition to true as default and is working fine.

So my conclusion is that the createFragment initializes our different fragments in a position-based way, starting from 0 and if we start creating our fragments at position 1 it will mess the order and then we will end up having just 1 fragment in the stack to switch.

I did lots of research on the issue but did not found anything related to this issue because if we use TabLayoutMediator this issue is not happening, it only happens when we try to switch the viewPager programatically with currentItem

Timmi answered 27/9, 2022 at 22:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.