우리는 여기 ViewPager와 관련하여 매우 이상한 문제로 고통 받고 있습니다. 각 ViewPager 페이지에 목록을 포함하고 목록 데이터를 업데이트 할 때 목록 어댑터와 뷰 페이저 어댑터 모두에서 notifyDataSetChanged를 트리거합니다.
우리가 관찰 한 것은 때때로 페이지가 뷰 트리를 업데이트하지 않는다는 것입니다. 즉, 빈 상태로 유지되거나, 페이지를 페이징 할 때 사라지기도합니다. 몇 번 앞뒤로 페이징하면 콘텐츠가 갑자기 다시 나타납니다. Android에보기 업데이트가 누락 된 것 같습니다. 또한 계층 뷰어로 디버깅 할 때 뷰를 선택하면 뷰가 항상 다시 나타납니다. 계층 뷰어가 선택한 뷰를 강제로 다시 그리도록하기 때문입니다.
그래도이 작업을 프로그래밍 방식으로 만들 수는 없습니다. 목록보기 또는 전체보기 호출기를 무효화해도 효과가 없었습니다.
이것은 compatibility-v4_r7 라이브러리입니다. 나는 또한 뷰 페이저와 관련된 많은 문제를 해결한다고 주장하기 때문에 최신 개정판을 사용하려고 시도했지만 문제를 더 악화 시켰습니다.
다른 사람도 이러한 문제를 겪고 있습니까? 아니면이 문제의 원인이 무엇인지 알고 있습니까?
답변
마침내 해결책을 찾았습니다. 분명히 우리의 구현에는 두 가지 문제가 있습니다.
- 어댑터가에서보기를 제거하지 않았습니다
destroyItem()
. - 레이아웃을 한 번만 확장해야하도록 뷰를 캐싱하고에서 뷰를 제거하지 않았기 때문에 뷰를
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 사용) :
- 고르다
New > Android Sample Project
- 대상 API 레벨을 선택하십시오 (사용 가능한 최신 API를 제안합니다).
- 고르다
Support4Demos
- 프로젝트를 마우스 오른쪽 버튼으로 클릭하고
Android Tools > Add Support Library
- 앱을 실행하고 선택
Fragment
후Pager
이에 대한 코드는 src/com.example.android.supportv4.app/FragmentPagerSupport.java
. 행운을 빕니다!
답변
나는 이것에 부딪 쳤고 매우 유사한 문제가 있었다. 나는 심지어 스택 오버플로에 대해 물었다 .
나를 위해, 내 부모 의 부모 에서 누군가 를 호출하지 않고 하위 클래스를 지정 LinearLayout
하고 덮어 썼습니다 . 이것은 내 ViewPager에서 호출되는 것을 방지 하고 호출 하지 못했습니다 (hierarchyviewer가 수동으로 호출하지만). 측정되지 않으면 ViewPager에서 공백으로 표시됩니다.requestLayout()
super.requestLayout()
onMeasure
onLayout
따라서 포함하는 뷰를 확인하십시오. View에서 하위 클래스인지 확인하고 requestLayout 또는 이와 유사한 것을 맹목적으로 재정의하지 마십시오.