조각 내에서 조각 뷰 페이지 표시
조각 내에서 조각 뷰 페이지 표시
ViewPager가 포함 된 조각이 있습니다. ViewPager는 조각 집합을 포함하는 어댑터와 연결됩니다.
부모 조각을로드 할 때라 IllegalStateException
는 메시지가 나타납니다 java.lang.IllegalStateException: Recursive entry to executePendingTransactions
.
일부 연구 결과 시스템이 다른 조각 내에서 조각을 표시 할 수 없다는 결론에 도달했습니다. 그러나 ViewPager ( 다른 조각과 함께 사용하는 ViewPager의 버그)를 사용하여 정확히이를 수행 할 수 있다는 표시가있는 것 같습니다. ).
사실, mPager.setAdapter(mAdapter)
눌 렸을 때 ViewPager 를 호출 하는 부모 조각에 버튼을 추가 하면 ViewPager가 성공적으로로드됩니다. 이것은 이상적이지 않습니다.
그런 다음 문제는 조각 수명주기와 관련되어야합니다. 따라서 내 질문은 이것이다 : 다른 사람이이 문제를 해결하는 방법을 찾았습니까? 그렇다면 어떻게합니까?
조각 트랜잭션이 끝날 때까지 ViewPager에서 어댑터 설정을 지연하는 방법이 있습니까?
다음은 부모 조각 코드입니다.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
final Button button = (Button)mView.findViewById(R.id.load_viewpager_button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mViewPager.setAdapter(mAdapter);
button.setVisibility(View.GONE);
}
});
mAdapter = new ViewPagerAdapter(getFragmentManager());
// mViewPager.setAdapter(mAdapter);
return mView;
}
그리고 어댑터 :
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
if (mCursor == null) return 0;
else return mCursor.getCount();
}
@Override
public Fragment getItem(int position) {
Bundle b = createBundle(position, mCursor);
return TeamCardFragment.newInstance(b);
}
}
AsyncTask를 사용하여 viewPager에 대한 어댑터를 설정하십시오. 그것은 나를 위해 작동합니다. asyncTask는 원본 조각이 전환을 완료하도록 만드는 것입니다. 그런 다음 기본적으로 재귀를 피하기 위해 viewPager 조각을 진행합니다.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
final Button button = (Button)mView.findViewById(R.id.load_viewpager_button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mViewPager.setAdapter(mAdapter);
button.setVisibility(View.GONE);
}
});
mAdapter = new ViewPagerAdapter(getFragmentManager());
new setAdapterTask().execute();
return mView;
}
private class setAdapterTask extends AsyncTask<Void,Void,Void>{
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void result) {
mViewPager.setAdapter(mAdapter);
}
}
FragmentStatePagerAdapter
대신 사용할 수 있습니다 FragmentPageAdapter
. 조각이 제거됩니다.
I just ran into this same problem. I had a Fragment
that needed to host a ViewPager
of Fragments
. When I stacked another Fragment
on top of my ViewPagerFragment
, and then hit back, I would get an IllegalStateException
. After checking the logs (when stacking a new Fragment
), I found that my ViewPagerFragment
would go through its lifecycle methods to stop and destroy, however its children Fragments
in the the ViewPager
would stay in onResume
. I realized that the children Fragments
should be managed by the FragmentManager
for the ViewPagerFragment
, not the FragmentManager
of the Activity
.
나는 그 당시에 위의 대답 Fragments
은 아이를 가질 수 없다는 한계를 극복하기위한 것이었다는 것을 알고 있습니다 Fragments
. 그러나 이제 최신 지원 라이브러리가 Fragment
중첩 을 지원하므로 더 이상 .NET 용 어댑터 설정을 해킹 할 필요가 없으며 ViewPager
전달 만하면 getChildFragmentManager()
됩니다. 이것은 지금까지 완벽하게 작동했습니다.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager) mView.findViewById(R.id.team_card_master_view_pager);
mAdapter = new ViewPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(mAdapter);
return mView;
}
Handler.post()
원래 조각 트랜잭션 외부에서 어댑터를 설정 하는 데 사용 했습니다.
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mHandler.post(new Runnable() {
@Override
public void run() {
mViewPager.setAdapter(mAdapter);
}
});
}
ViewCreated의 TabIndicator에서 viewPager 어댑터를 초기화하려고 할 때이 문제에 직면했습니다. 온라인에서 그것에 대해 읽은 후 나는 이것이 조각이 아직 활동에 추가되지 않았기 때문일 수 있음을 깨달았습니다. 그래서 초기화 코드를 조각의 onStart ()로 옮겼으므로 문제가 해결 될 것입니다. 그러나 나에게는 여전히 같은 문제가 다시 발생했습니다.
하지만 내 코드에서 모든 것이 잘 작동한다는 것을 차단 한 후 executePendingTransactions ()를 명시 적으로 호출하여 보류중인 작업의 정상적인 비동기 실행을 우회하려고 시도했기 때문입니다.
부모 조각을로드 할 때 java.lang.IllegalStateException : recursive entry to executePendingTransactions 메시지와 함께 IllegalStateException이 발생합니다.
일부 연구 결과 시스템이 다른 조각 내에서 조각을 표시 할 수 없다는 결론에 도달했습니다. 그러나 ViewPager (다른 조각과 함께 사용하는 ViewPager의 버그)를 사용하여 정확히이를 수행 할 수 있다는 표시가있는 것 같습니다. ).
ViewPager의 ID를 명시 적으로 설정합니다.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
mViewPager.setId(100);
final Button button = (Button)mView.findViewById(R.id.load_viewpager_button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mViewPager.setAdapter(mAdapter);
button.setVisibility(View.GONE);
}
});
mAdapter = new ViewPagerAdapter(getFragmentManager());
mViewPager.setAdapter(mAdapter);
return mView;
}
매직 넘버 100 대신 xml 리소스에서 id를 사용할 수 있습니다.
<resources>
<item name="Id_For_ViewPager" type="id"/>
</resources>
및 setId (R.Id_For_ViewPager).
자세한 내용은 FragmentManager.java 소스를 참조하십시오.
또는이 페이지 (일본어)를 참조하십시오. 원래 아이디어는 사실 내가 아니라 그녀에게서 나온 것입니다. http://y-anz-m.blogspot.jp/2012/04/androidfragment-viewpager-id.html
Thomas Amssler의 멋진 게시물 사용 : http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html
Iv'e는 모든 유형의 조각을 만드는 데 사용할 수있는 어댑터를 만들었습니다. 어댑터 자체는 다음과 같습니다.
public abstract class EmbeddedAdapter extends FragmentStatePagerAdapter {
private SparseArray<WeakReference<Fragment>> mPageReferenceMap = new SparseArray<WeakReference<Fragment>>();
private ArrayList<String> mTabTitles;
public abstract Fragment initFragment(int position);
public EmbeddedAdapter(FragmentManager fm, ArrayList<String> tabTitles) {
super(fm);
mTabTitles = tabTitles;
}
@Override
public Object instantiateItem(ViewGroup viewGroup, int position) {
mPageReferenceMap.put(Integer.valueOf(position), new WeakReference<Fragment>(initFragment(position)));
return super.instantiateItem(viewGroup, position);
}
@Override
public int getCount() {
return mTabTitles.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTabTitles.get(position);
}
@Override
public Fragment getItem(int pos) {
return getFragment(pos);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferenceMap.remove(Integer.valueOf(position));
}
public Fragment getFragment(int key) {
WeakReference<Fragment> weakReference = mPageReferenceMap.get(key);
if (null != weakReference) {
return (Fragment) weakReference.get();
} else {
return null;
}
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
어댑터를 사용하려면 다음을 수행해야합니다.
private void setAdapter() {
if(mAdapter == null) mAdapter = new EmbeddedAdapter(getActivity().getSupportFragmentManager(), mTabTitles) {
@Override
public Fragment initFragment(int position) {
Fragment fragment;
if(position == 0){
// A start fragment perhaps?
fragment = StartFragment.newInstance(mBlocks);
}else{
// Some other fragment
fragment = PageFragment.newInstance(mCategories.get((position)));
}
return fragment;
}
};
// Have to set the adapter in a handler
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
mViewPager.setVisibility(View.VISIBLE);
mPagerTabStrip.setVisibility(View.VISIBLE);
mAdapter.notifyDataSetChanged();
}
});
}
모든 조각은 다음을 사용합니다.
setRetainInstance(true);
문서에 따르면 : https://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager ()
중첩 조각을 관리하려면 getChildFragmentManager
대신을 사용해야 합니다 getFragmentManager
.
Instead of setting the adapter in AsyncTask or any Handler just write that part of code in onResume() section
Doing Such you will:
- Let the transition of the main fragment to complete.
- Display the child fragment without use of any background task.
The code of onResume() is as follows in your case:
@Override
public void onResume() {
super.onResume();
if(mViewPager.getAdapter()==null||mViewPager.getAdapter().getCount()==0)
mViewPager.setAdapter(mAdapter);
}
Also in onCreateView Instead of
mAdapter = new ViewPagerAdapter(getFragmentManager());
Replace with
mAdapter = new ViewPagerAdapter(getChildFragmentManager());
ReferenceURL : https://stackoverflow.com/questions/7700226/display-fragment-viewpager-within-a-fragment