태그 보관물: android-viewpager

android-viewpager

ViewPager를 동적으로 업데이트 하시겠습니까? 리턴 될 때만 수행해야합니다. 매개 변수

ViewPager에서 컨텐츠를 업데이트 할 수 없습니다.

FragmentPagerAdapter 클래스에서 instantiateItem () 및 getItem () 메소드의 올바른 사용법은 무엇입니까?

getItem () 만 사용하여 조각을 인스턴스화하고 반환했습니다.

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

이것은 잘 작동했습니다. 내용을 변경할 수 없다는 점만 빼면

그래서 이것을 찾았습니다 : ViewPager PagerAdapter가 View를 업데이트하지 않습니다

“제 접근법은 instantiateItem () 메소드의 인스턴스화 된 뷰에 대해 setTag () 메소드를 사용하는 것입니다.”

이제 instantiateItem ()을 구현하고 싶습니다. 그러나 무엇을 반환 해야하는지 (유형은 Object) 모르겠으며 getItem (int position)과의 관계는 무엇입니까?

나는 참조를 읽었다 :

  • 공개 추상 조각 getItem (int position)

    지정된 위치와 관련된 조각을 반환합니다.

  • 공용 객체 instantiateItem (ViewGroup 컨테이너, int 위치)

    주어진 위치에 대한 페이지를 작성하십시오. 어댑터는 여기에 제공된 컨테이너에보기를 추가해야하지만 finishUpdate (ViewGroup)에서 리턴 될 때만 수행해야합니다. 매개 변수

    컨테이너 페이지가 표시 될 포함보기입니다. position 인스턴스화 할 페이지 위치.

    보고

    새 페이지를 나타내는 Object를 리턴합니다. 이것은 뷰일 필요는 없지만 페이지의 다른 컨테이너 일 수 있습니다.

그러나 나는 여전히 그것을 얻지 못한다.

여기 내 코드가 있습니다. 지원 패키지 v4를 사용하고 있습니다.

ViewPagerTest

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

    @Override
    public int getCount() {
        return slideCount;
    }

    public void setData(String[] data) {
        this.data = data;
    }

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

MyFragment

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

비슷한 문제가있는 사람도 있습니다
.http : //www.mail-archive.com/android-developers@googlegroups.com/msg200477.html



답변

FragmentPagerAdapter 또는 FragmentStatePagerAdapter를 사용할 때는 전적으로 getItem()만지거나 전혀 손대지 않는 것이 가장 좋습니다 instantiateItem(). instantiateItem()destroyItem()isViewFromObject()PagerAdapter에 대한 인터페이스는 FragmentPagerAdapter의 사용이 훨씬 간단 구현하는 낮은 수준의 인터페이스 getItem()인터페이스를.

이것에 들어가기 전에, 나는 명확히해야합니다

표시되는 실제 조각을 끄려면 FragmentPagerAdapter를 피하고 FragmentStatePagerAdapter를 사용해야합니다.

이 답변의 이전 버전은 FragmentPagerAdapter를 사용하는 실수를 예로 들었습니다. FragmentPagerAdapter는 처음 표시 된 후에는 FragmentPagerAdapter가 조각을 파괴하지 않기 때문에 작동하지 않습니다.

나는 당신이 링크 한 게시물에 제공된 setTag()findViewWithTag()해결 방법을 권장하지 않습니다 . 발견했듯이 조각을 사용 setTag()하고 findViewWithTag()작동하지 않으므로 일치하지 않습니다.

올바른 해결책은 재정의하는 것 getItemPosition()입니다. 경우 notifyDataSetChanged()라고, ViewPager 통화 getItemPosition()가 다른 위치로 이동하거나 제거 할 필요가 있는지 여부를 확인하기 위해 어댑터에있는 모든 항목에.

기본적 getItemPosition()으로을 반환합니다 POSITION_UNCHANGED. 즉, “이 개체는 아무 곳에 나 있으면 파괴하거나 제거하지 마십시오.” 반환 POSITION_NONE대신에, 말을하지 않습니다에 의해 수정에게 문제를 “이 개체는 더 이상 내가 그것을 제거, 표시하고있어 항목입니다.” 따라서 어댑터의 모든 단일 항목을 제거하고 다시 만드는 효과가 있습니다.

이것은 완전히 합법적 인 수정입니다! 이 수정 사항은 notifyDataSetChanged가보기 재활용없이 일반 어댑터처럼 작동하도록합니다. 이 수정 프로그램을 구현하고 성능이 만족 스럽다면 경쟁을 시작한 것입니다. 작업이 완료되었습니다.

더 나은 성능이 필요하면 더 멋진 getItemPosition()구현을 사용할 수 있습니다 . 다음은 문자열 목록에서 조각을 만드는 호출기의 예입니다.

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

이 구현에서는 새 제목을 표시하는 조각 만 표시됩니다. 여전히 목록에있는 제목을 표시하는 조각은 대신 목록의 새 위치로 이동하고 더 이상 목록에없는 제목을 가진 조각은 완전히 삭제됩니다.

프래그먼트를 다시 만들지 않았지만 업데이트해야 할 경우 어떻게해야합니까? 살아있는 조각에 대한 업데이트는 조각 자체에 의해 가장 잘 처리됩니다. 그것은 결국 조각을 갖는 이점입니다. 그것은 자체 컨트롤러입니다. 조각은의 다른 객체에 리스너 또는 관찰자를 추가 한 onCreate()다음에서 제거 onDestroy()하여 업데이트 자체를 관리 할 수 ​​있습니다. getItem()ListView 또는 다른 AdapterView 유형의 어댑터에서와 같이 모든 업데이트 코드를 내부에 넣을 필요는 없습니다 .

마지막으로 FragmentPagerAdapter가 프래그먼트를 파괴하지 않는다고해서 FragmentPagerAdapter에서 getItemPosition이 완전히 쓸모 없다는 의미는 아닙니다. 이 콜백을 사용하여 ViewPager에서 프래그먼트를 재정렬 할 수 있습니다. 그러나 FragmentManager에서 완전히 제거하지는 않습니다.


답변

전체보기 재생 POSITION_NONE에서 돌아와서 재생하는 대신 다음을 getItemPosition()수행하십시오.

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

조각은 UpdateableFragment인터페이스 를 구현해야합니다 .

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

그리고 인터페이스 :

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

데이터 클래스 :

public class UpdateData {
    //whatever you want here
}

답변

내가 ViewPager7 조각으로 가질 때 이전에 직면했던 것과 같은 문제에 여전히 직면하는 사람들을 위해 . 이 조각의 기본값은 API서비스 에서 영어 내용을로드하는 문제이지만 여기서는 설정 활동에서 언어를 변경하고 설정 활동을 마친 후에 ViewPager주요 활동에서 사용자의 언어 선택과 일치하도록 조각을 새로 고치고 싶습니다 . 사용자가 아랍어를 선택하면 아랍어 콘텐츠가 처음부터 작업 한 것

1- 위에서 언급 한대로 FragmentStatePagerAdapter를 사용해야합니다.

mainActivity의 2- onResume을 무시하고 다음을 수행했습니다.

if (!(mPagerAdapter == null)) {
    mPagerAdapter.notifyDataSetChanged();
}

3-i getItemPosition()는 mPagerAdapter에서 재정 의하여 반환 POSITION_NONE합니다.

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

매력처럼 작동합니다


답변

나는이 문제에 직면하여 오늘 그것을 마침내 해결 했으므로 내가 배운 것을 적어두고 Android에 익숙하지 않은 사람에게 도움이되기를 바랍니다 ViewPager. FragmentStatePagerAdapterAPI 레벨 17에서 사용 중이며 현재 2 개의 조각 만 있습니다. 정확하지 않은 것이 있다고 생각합니다. 감사합니다.

  1. 직렬화 된 데이터는 메모리에로드되어야합니다. 이것은 CursorLoader/ AsyncTask/를 사용하여 수행 할 수 있습니다 Thread. 자동로드 여부는 코드에 따라 다릅니다. 를 사용하는 경우 CursorLoader등록 된 데이터 옵저버가 있으므로 자동으로로드됩니다.

  2. 을 호출 한 후에 viewpager.setAdapter(pageradapter)는 어댑터 getCount()가 지속적으로 호출되어 프래그먼트를 빌드합니다. 따라서 데이터가로드되면 getCount()0을 반환 할 수 있으므로 데이터가 표시되지 않도록 더미 조각을 만들 필요가 없습니다.

  3. 데이터가로드 된 getCount()후에도 여전히 0이므로 어댑터가 프래그먼트를 자동으로 빌드하지 않으므로 실제로로드 된 데이터 번호를로 설정 getCount()하여 어댑터의를 호출 할 수 있습니다 notifyDataSetChanged(). ViewPager메모리의 데이터로 조각 (처음 두 조각 만)을 만들기 시작하십시오. notifyDataSetChanged()반환 되기 전에 완료되었습니다 . 그런 다음 ViewPager필요한 조각이 있습니다.

  4. 데이터베이스와 메모리의 데이터가 모두 업데이트 (쓰기)하거나 메모리의 데이터 만 업데이트 (다시 쓰기)되거나 데이터베이스의 데이터 만 업데이트되는 경우 마지막 두 경우에 데이터가 데이터베이스에서 메모리로 자동로드되지 않는 경우 (위에서 언급 한 바와 같이). ViewPager및 호출기 어댑터는 메모리에 데이터를 처리.

  5. 따라서 메모리의 데이터가 업데이트되면 어댑터를 호출하기 만하면됩니다 notifyDataSetChanged(). 프래그먼트가 이미 작성되었으므로 어댑터가 리턴 onItemPosition()되기 전에 호출됩니다 notifyDataSetChanged(). 에서 수행 할 작업이 없습니다 getItemPosition(). 그런 다음 데이터가 업데이트됩니다.


답변

코드 destroyDrawingCache()에서 ViewPager를 사용해보십시오 notifyDataSetChanged().


답변

좌절의 시간이 문제를 극복하기 위해 위의 모든 솔루션을 시도 또한 같은 다른 유사한 문제에 많은 솔루션을하는 동안 후 , 그리고 모두가이 문제를 해결하고 만들기 위해 나와 함께 실패하는 ViewPager기존의 파괴 Fragment와 채우기 pager로 새로운 Fragments. 다음과 같이 문제를 해결했습니다.

1) 만들기 기능 ViewPager확장에 클래스를 FragmentPagerAdapter다음과 같은 :

 public class myPagerAdapter extends FragmentPagerAdapter {

2) 에 대한 항목을 작성 ViewPager가게가 title와를 fragment다음과 같은 :

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) 인스턴스 생성자 를 다음과 같이 ViewPagerFragmentManager인스턴스에 저장하십시오 class.

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4) 다음과 같이 새 목록에서 새 항목을 다시 설정 하기 위해 직접 adapter이전 항목 fragment을 모두 삭제하여 새 데이터로 데이터 를 재설정하는 방법을 작성하십시오 .fragmentManageradapterfragment

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) 컨테이너에서 Activity또는 Fragment새 데이터로 어댑터를 다시 초기화하지 마십시오. setPagerItems다음과 같이 새 데이터로 메소드 를 통해 새 데이터를 설정하십시오 .

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();

도움이 되길 바랍니다.


답변

어떤 이유로 든 대답이 나를 위해 일하지 않았으므로 fragmentStatePagerAdapter에서 super를 호출하지 않고 restoreState 메서드를 재정의해야했습니다. 암호:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}