밍쯔와 안작고 안귀여운 에러들🖤

[Android/Java] wrap_content 오류 : ViewPager2 그리고 FragmentStateAdapter(fragment)_동적 높이 변환 본문

Develop/Android | iOS

[Android/Java] wrap_content 오류 : ViewPager2 그리고 FragmentStateAdapter(fragment)_동적 높이 변환

밍쯔 2023. 8. 22. 11:11

[문제]

viewPager2 내에 FragmentStateAdapter로 fragment를 사용하고 있는 경우,

그리고 그 fragment 안에 Recyclerview를 사용하고 있어서

height가 달라지니 wrap_content로 설정했으나 아래와 같은 문제가 발생한다.

 

참조 1 스택오버플로 - gnekki4의 첨부 이미지

예를 들어,

fragment1 : 100dp , fragment2 : 300dp, fragment3 : 50dp 일때

첫번째 fragment1의 높이인 100dp에 맞춰진 상태로 고정되어 2,3의 fragment가 짤리거나 남는 경우의 에러를 볼 수 있다.

 

[구조]

CustomScrollView > LinearLayout > ViewPager2(LinearLayout>Recyclerview...) ...

 

[해결]

해당 탭이 선택 될 때, 뷰의 높이를 동적으로 변경해줘야 한다.

viewParger2의 registerOnPageChangeCallback, onPageSelected 를 사용해서 문제를 해결한다.

activity에서 fragment를 adapter를 통해 생성하는 과정에 추가해 주었다.

// tabPager : ViewPager2
// pagerAdapter : FragmentStateAdapter

private void setTabs() {
    // 화면 슬라이드 전환을 막기 위함
    binding.tabPager.setUserInputEnabled(false);
    
    // viewPager2의 height를 동적으로 변환 시키기 위함.
    // 없을 경우, 탭을 선택해 화면을 전환시킬 때 아래 view == null 반환
    binding.tabPager.setOffscreenPageLimit(2);

    ...

    binding.tabPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);

            if (pagerAdapter.getItemCount() > position) {
                View view = Objects.requireNonNull(((RecyclerView) binding.tabPager.getChildAt(0)).getLayoutManager()).findViewByPosition(position);
                if (view != null) {
                    view.post(new Runnable() {
                        @Override
                        public void run() {
                            int wMeasureSpec = View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY);
                            int hMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
                            view.measure(wMeasureSpec, hMeasureSpec);

                            if (binding.tabPager.getLayoutParams().height != view.getMeasuredHeight()) {
                                ViewGroup.LayoutParams layoutParams = binding.tabPager.getLayoutParams();
                                layoutParams.height = view.getMeasuredHeight();
                                binding.tabPager.setLayoutParams(layoutParams);
                            }
                        }
                    });
                }
            }
        }
    });
}

 

 

 

[참고]

1 : https://stackoverflow.com/questions/58492796/viewpager2-with-differing-item-heights-and-wrap-content

 

ViewPager2 with differing item heights and WRAP_CONTENT

There are a few posts on getting ViewPager to work with varying height items that center around extending ViewPager itself to modify its onMeasure to support this. However, given that ViewPager2 is

stackoverflow.com

2 : https://stackoverflow.com/questions/61354528/android-viewpager2-not-dynamically-wrapping-height-of-different-sized-fragments/64235840#64235840

 

Android ViewPager2 not dynamically wrapping height of different sized fragments

I have a ViewPager2 that has different height fragments as children, the height of the children change after data is loaded <com.google.android.material.appbar.CollapsingToolbarLayout ...

stackoverflow.com