Android ViewPager with WRAPCONTENT height

Save

Recently, while working with the ViewPager, I found out that sometimes the Android ViewPager with WRAPCONTENT height flag is not visible. The reason for this is perhaps that the wrap_content flag needed height from the child view and the child view height is still not known.

The best way to check this is to fix the height to some hardcoded value say “200dp” and check if the view is visible.

Now if the view is visible and it gets your work done you don’t need to follow this blog anymore as you have achieved your purpose. But, if you still want to have a viewpager which has height set by the wrap_content flag in your XML file, then you should continue reading.

I believe that the purpose of this blog is very clear to you by now. So I will just come to the approach I have used.

APPROACH

  1. Create A custom View class that extends the View Pager class.(say WrapContentViewPager).
  2. Create default constructors for your class as in the View Pager class, so that you can directly call super with these and create a proper view for your custom view and use it in xml as easily as you would use the ViewPager tag for creating the viewpager view.
  3.  Create a Function that will add a simple page Change listener to your custom view and then call this function in the default constructors you just created in above step.
  4.  Override the onMeasure Method of the ViewPager class in your custom View class and get the child’s measured height and then set in the height params and call the super function.

CODE

WrapContentViewPager class :-

Use of this class in your XML File:-

The Above code will just change the height of the Viepager as per the current child. but the main power of the viewPager is to prepare the view for the previous and next item as well so if you want you can get this also and this again is nothing but iterating the viewPager as per the child in the memory so we just need to have a for loop in onMeasure method of the viewPager and iterate each child View.

CODE

EnhancedWrapContentViewPager class:-

Use of this class in your XML File:-

That’s it,  you can run this code and check it yourself.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


27 comments

  • abhay paul
    Thanks a lot
    • Aman Gupta (Moderator)
      @abhay your most welcome. 🙂
  • Divya Gupta
    Thanks man. Finally a working solution after soooooo long time….Heartiest Thanks!!
    • anchit (Moderator)
      @Divya : Thanks for your appreciating words 🙂
  • Vora
    Find solution at this place
    thanx
    • anchit (Moderator)
      Thanks @Vora for your kind words.
  • Juan
    When the app lost focus (maybe the screen is blocked or you switch to another app), when you return to the app, the getChildAt(getCurrentItem()) is null, so the viewpager content is not shown. Are you faced this issue too?
    • anchit (Moderator)
      Hello Juan,

      Thanks for your concern but we never faced this kind of issue in any of our apps.

      The reason for your issues most probably is that you must have overridden the onResume() method of your activity. If that’s the case then you need to explicitly set up the view page and adapter again in onResume() method in order to avoid this issue.

      If your problem is not solved with this approach, then please share your code and i will look into it.

  • S Paran
    Thanks a lot
    • anchit (Moderator)
      Your welcome 🙂
  • Alex
    Thanks!
    • anchit (Moderator)
      Your welcome 🙂
  • sonph
    Hey guys, I’m using your solution. But i faced problem
    My XML layout has format
    LinearLayout
    FrameLayout( this layout used to player play video)
    ScrollView
    LinearLayout
    RelativeLayout ( call is layout1)
    RelativeLayout
    Tablayout
    Viewpager
    When I apply your solution, view pager scroll is OK, but layout1 lost a part on top, and can’t display
    Someone can give to me solution
    Thanks all.
    • anchit (Moderator)
      Hello there,

      can you provide your source code, so that we can have a look into your code and predict how this can be done?

      Generally, if this kind of complex layout architecture is followed then you might have to maintain all the layouts (their width & height) in your view render(Activity/ Fragment) class.

    • Marama
      Same thing happened to me did you figure it out? Im a bit lost
  • Umang Madani
    Thanks a lot man you saved the day
    • anchit (Moderator)
      You are welcome
  • Yongho
    Thank you.

    Your code is working nice.

    If I use this code in my app which is commercial,
    Do I consider any license?

    • anchit (Moderator)
      Hello,

      Thanks for the appreciating words.

      No, this particular piece of information is not under any license.

      You can use it anywhere you want.

  • Kavi
    Thank you very much, after so long time EnhancedWrapContentViewPager solved my issue.
    • anchit (Moderator)
      Your Welcome
  • Radhe
    how can we achieve same with ViewPager2
    • anchit (Moderator)
      Well, this should work with View Pager2 as well.

      Personally, I have not used the ViewPager2 till now.
      But if something similar is troubling you then just make WrapContentViewPager extend ViewPager2, and then in the remaining article replace all the accourences of the view pager with viewPager2 and this should work.

      If this does not works out, then please do share teh exact code with me, so that we can look and update you accordingly.

      Regards,
      Anchit

  • Radhey Gor
    Hi
    This is great solution.
    I am using WrapContentViewPager but it’s not updating height of viewPager on Tab change.
    I have Tablayout with viewpager inside bottomsheetFragment.
    • anchit (Moderator)
      Well, firstly please do check if all the parents of the view pager have wrapcontent flag set in the height.

      If this is already there, then we will need to have a look in your exact code.

  • Vinod
    Hi @Anchit, I have integrated the above ‘EnhancedWrapContentViewPager’ in my app and facing the below error in production.
    Could you please help me on resolving and understand the cause of this issue? Appreciate your response. Thanks
    Error log from Crashlytics:
    {{Fatal Exception: java.lang.IllegalArgumentException: No view found for id 0x7f090338 (com.x.y.z:id/pager) for fragment FinalFragment

    {c762f8e}
    (b82eb4bd-1a41-4ac3-bcfc-3290674e7c54) id=0x7f090338}
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:315)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
    at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:447)
    at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
    at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
    at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
    at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
    at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:303)
    at androidx.fragment.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:270)
    at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
    at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
    at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
    at com.dexels.sportlinked.util.ui.WrapContentViewPager.onMeasure(WrapContentViewPager.java:28)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:27131)
    at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:9384)
    at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1653)
    at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
    at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
    at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3540)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
    at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1204)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:723)
    at android.view.View.measure(View.java:27131)
    at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onMeasure(SwipeRefreshLayout.java:641)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
    at android.view.View.measure(View.java:27131)
    at androidx.drawerlayout.widget.DrawerLayout.onMeasure(DrawerLayout.java:1119)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:146)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7951)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at com.android.internal.policy.DecorView.onMeasure(DecorView.java:1173)
    at android.view.View.measure(View.java:27131)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:4187)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2936)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3204)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2618)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9971)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1010)
    at android.view.Choreographer.doCallbacks(Choreographer.java:809)
    at android.view.Choreographer.doFrame(Choreographer.java:744)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:995)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:246)
    at android.app.ActivityThread.main(ActivityThread.java:8633)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)}}

    • anchit (Moderator)
      Hi Vinod,

      As per the logs, the issue seems to be some fragment being removed and the code is being executed after that as well.

      Please double check the code for execution of some access to the view with id pager after the fragment being detached or killed.

      If still you need some help, then please do provide the code to me so that i can check that in complete details.

  • css.php

    Webkul is a truly trusted and supported IT Company to develop business ideas for e-commerce. They provide professional support after deploying the solution to production and be responsible to act for fixing the reported issues or system errors. We highly encourage to deal with Webkul for business development.

    Hussein Zawia

    Hussein Zawia

    Co-founder, 24Dokan

    Talk to Sales

    Global

    Live Chat
    Start a Project


      Message Sent!

      If you have more details or questions, you can reply to the received confirmation email.

      Back to Home