[android] ViewPager가 콘텐츠를 다시 그리지 않고 그대로 유지 / 비어 있음

우리는 여기 ViewPager와 관련하여 매우 이상한 문제로 고통 받고 있습니다. 각 ViewPager 페이지에 목록을 포함하고 목록 데이터를 업데이트 할 때 목록 어댑터와 뷰 페이저 어댑터 모두에서 notifyDataSetChanged를 트리거합니다.

우리가 관찰 한 것은 때때로 페이지가 뷰 트리를 업데이트하지 않는다는 것입니다. 즉, 빈 상태로 유지되거나, 페이지를 페이징 할 때 사라지기도합니다. 몇 번 앞뒤로 페이징하면 콘텐츠가 갑자기 다시 나타납니다. Android에보기 업데이트가 누락 된 것 같습니다. 또한 계층 뷰어로 디버깅 할 때 뷰를 선택하면 뷰가 항상 다시 나타납니다. 계층 뷰어가 선택한 뷰를 강제로 다시 그리도록하기 때문입니다.

그래도이 작업을 프로그래밍 방식으로 만들 수는 없습니다. 목록보기 또는 전체보기 호출기를 무효화해도 효과가 없었습니다.

이것은 compatibility-v4_r7 라이브러리입니다. 나는 또한 뷰 페이저와 관련된 많은 문제를 해결한다고 주장하기 때문에 최신 개정판을 사용하려고 시도했지만 문제를 더 악화 시켰습니다.

다른 사람도 이러한 문제를 겪고 있습니까? 아니면이 문제의 원인이 무엇인지 알고 있습니까?



답변

마침내 해결책을 찾았습니다. 분명히 우리의 구현에는 두 가지 문제가 있습니다.

  1. 어댑터가에서보기를 제거하지 않았습니다 destroyItem().
  2. 레이아웃을 한 번만 확장해야하도록 뷰를 캐싱하고에서 뷰를 제거하지 않았기 때문에 뷰를 destroyItem()추가하지 않고 instantiateItem()현재 위치에 해당하는 캐시 된 뷰를 반환했습니다.

나는 소스 코드를 너무 깊이 들여다 보지 않았고 ViewPager-당신이 그것을해야한다는 것이 명확하지 않지만 문서에는 다음과 같이 말합니다.

destroyItem ()
주어진 위치에 대한 페이지를 제거합니다. 어댑터는 해당 컨테이너에서 뷰를 제거해야하지만 finishUpdate (ViewGroup)에서 반환 될 때까지이 작업이 수행되도록해야합니다.

과:

매우 간단한 PagerAdapter는 페이지 뷰 자체를 키 개체로 사용하도록 선택할 수 있으며, 생성 후 instantiateItem (ViewGroup, int)에서 반환하고 부모 ViewGroup에 추가 할 수 있습니다. 일치하는 destroyItem (ViewGroup, int, Object) 구현은 상위 ViewGroup에서 View를 제거하고 isViewFromObject (View, Object)는 return view == object;로 구현 될 수 있습니다.

내 결론은 그래서 ViewPager명시 적으로 추가 /에서 아이를 제거하기 위해 기본 어댑터에 의존 instantiateItem()/ destroyItem(). 즉, 어댑터가의 하위 클래스 인 PagerAdapter경우 하위 클래스는이 논리를 구현해야합니다.

참고 : 내부 목록을 사용 하는 경우이 점에 유의하세요 ViewPager.


답변

이 경우 ViewPager기호가있는 조각 내부 설정 FragmentPagerAdapter, 사용하는 getChildFragmentManager()대신에 getSupportFragmentManager()당신의 초기화 매개 변수로 FragmentPagerAdapter.

mAdapter = new MyFragmentPagerAdapter(getChildFragmentManager());

대신에

mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());


답변

나는 똑같은 문제가 있었지만 실제로 destroyItem에서 뷰를 파괴했습니다 (생각했습니다). 그러나 문제는 내가 viewPager.removeViewAt(index);insted ofviewPager.removeView((View) object);

잘못된:

@Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeViewAt(position);
}

권리:

@Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeView((View) object);
}


답변

ViewPager는 항목 재사용과 관련하여 영리한 작업을 시도하지만 변경된 경우 새 항목 위치를 반환해야합니다. PagerAdapter에 다음을 추가해보십시오.

public int getItemPosition (Object object) { return POSITION_NONE; }

기본적으로 ViewPager에 모든 것이 변경되었음을 알리고 모든 것을 다시 인스턴스화하도록합니다. 그게 내 머릿속에서 생각할 수있는 유일한 것입니다.


답변

너무 많은 솔루션을 시도했지만 예기치 않게 viewPager.post()작동했습니다.

 mAdapter = new NewsVPAdapter(getContext(), articles);
    viewPager.post(new Runnable() {
        @Override
        public void run() {
            viewPager.setAdapter(mAdapter);
        }
    });


답변

Android 지원 라이브러리에는 모든 페이지에 ListView가있는 ViewPager가 포함 된 데모 활동이 있습니다. 당신은 아마 그것을보고 그것이 무엇을하는지보아야 할 것입니다.

Eclipse에서 (Android Dev Tools r20 사용) :

  1. 고르다 New > Android Sample Project
  2. 대상 API 레벨을 선택하십시오 (사용 가능한 최신 API를 제안합니다).
  3. 고르다 Support4Demos
  4. 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Android Tools > Add Support Library
  5. 앱을 실행하고 선택 FragmentPager

이에 대한 코드는 src/com.example.android.supportv4.app/FragmentPagerSupport.java. 행운을 빕니다!


답변

나는 이것에 부딪 쳤고 매우 유사한 문제가 있었다. 나는 심지어 스택 오버플로에 대해 물었다 .

나를 위해, 내 부모부모 에서 누군가 를 호출하지 않고 하위 클래스를 지정 LinearLayout하고 덮어 썼습니다 . 이것은 내 ViewPager에서 호출되는 것을 방지 하고 호출 하지 못했습니다 (hierarchyviewer가 수동으로 호출하지만). 측정되지 않으면 ViewPager에서 공백으로 표시됩니다.requestLayout()super.requestLayout()onMeasureonLayout

따라서 포함하는 뷰를 확인하십시오. View에서 하위 클래스인지 확인하고 requestLayout 또는 이와 유사한 것을 맹목적으로 재정의하지 마십시오.