Mau*_*ycy 43 android android-fragments android-viewpager
我已经实现了FragmentPagerAdapter和使用a List<Fragment>来保存所有片段以供我ViewPager显示.在addItem()我只是添加一个实例化Fragment然后调用notifyDataSetChanged().我不确定这是否有必要.
我的问题只是......从片段1开始
[Fragment 1]
Run Code Online (Sandbox Code Playgroud)
添加新的片段2
[Fragment 1] [Fragment 2]
Run Code Online (Sandbox Code Playgroud)
删除片段2
[Fragment 1]
Run Code Online (Sandbox Code Playgroud)
添加新的片段3
[Fragment 1] [Fragment 2]
Run Code Online (Sandbox Code Playgroud)
添加新片段时,一切看起来都很棒.删除片段然后添加新实例化的片段后,仍会显示旧片段.当我去.getClass.getName()它时,它给了我片段3的名字,但我仍然看到片段2.
我相信这可能是一个问题,instantiateItem()但我认为适配器是为我们处理.任何建议都会很棒.
适配器代码......
public class MyPagerAdapter extends FragmentPagerAdapter {
public final ArrayList<Fragment> screens2 = new ArrayList<Fragment>();
private Context context;
public MyPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
public void removeType(String name){
for(Fragment f: screens2){
if(f.getClass().getName().contains(name)){ screens2.remove(f); return; }
}
this.notifyDataSetChanged();
}
public boolean addSt(String tag, Class<?> clss, Bundle args){
if(clss==null) return false;
if(!clss.getName().contains("St")) return false;
if(!args.containsKey("cId")) return false;
boolean has = false;
boolean hasAlready = false;
for(Fragment tab: screens2){
if(tab.getClass().getName().contains("St")){
has = true;
if(tab.getArguments().containsKey("cId"))
if(tab.getArguments().getLong("cId") == args.getLong("cId")){
hasAlready = true;
}
if(!hasAlready){
// exists but is different so replace
screens2.remove(tab);
this.addScreen(tag, clss, args, C.PAGE_ST);
// if returned true then it notifies dataset
return true;
}
}
hasAlready = false;
}
if(!has){
// no st yet exist in adapter
this.addScreen(tag, clss, args, C.PAGE_ST);
return true;
}
return false;
}
public boolean removeCCreate(){
this.removeType("Create");
return false;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE; //To make notifyDataSetChanged() do something
}
public void addCCreate(){
this.removeCCreate();
Log.w("addding c", " ");
this.addScreen("Create C", CreateCFragment.class, null, C.PAGE_CREATE_C);
}
public void addScreen(String tag, Class<?> clss, Bundle args, int type){
if(clss!=null){
screens2.add(Fragment.instantiate(context, clss.getName(), args));
}
}
@Override
public int getCount() {
return screens2.size();
}
@Override
public Fragment getItem(int position) {
return screens2.get(position);
}
}
Run Code Online (Sandbox Code Playgroud)
我意识到代码使用了一些"贫民窟"来确定片段类型,但是我严格地编写了这段代码用于测试功能.任何帮助或想法都会很棒,因为似乎没有多少人冒险进入FragmentPagerAdapters 世界.
Ter*_*hih 33
我遇到了同样的问题,我的解决方案是覆盖了方法"destroyItem",如下所示.
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
FragmentManager manager = ((Fragment)object).getFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove((Fragment)object);
trans.commit();
}
Run Code Online (Sandbox Code Playgroud)
它对我有用,有没有人有另一种解决方案?
更新:
我发现那些代码片段删除了Fragment不必要,所以我添加了一个条件来避免它.
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (position >= getCount()) {
FragmentManager manager = ((Fragment) object).getFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove((Fragment) object);
trans.commit();
}
}
Run Code Online (Sandbox Code Playgroud)
更新了这篇文章并包含了我的解决方案(如果有人可以改进,请告诉我)
好吧,我现在以一种hackish的方式解决了我的问题,但是它正在工作;).如果有人可以改进我的解决方案,请告诉我.对于我的新解决方案,我现在使用CustomFragmentStatePagerAdapter,但它不会保存状态,并将所有片段存储在列表中.如果用户有超过50个片段,这可能会导致内存问题,就像普通的FragmentPagerAdapter一样.如果有人可以在不删除我的修复程序的情况下将State-thing添加回我的解决方案,那就太棒了.谢谢.
所以这是我的CustomFragmentStatePagerAdapter.java
package com.tundem.webLab.Adapter;
import java.util.ArrayList;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
public abstract class CustomFragmentStatePagerAdapter extends PagerAdapter {
private static final String TAG = "FragmentStatePagerAdapter";
private static final boolean DEBUG = false;
private final FragmentManager mFragmentManager;
private FragmentTransaction mCurTransaction = null;
public ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
public ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
private Fragment mCurrentPrimaryItem = null;
public CustomFragmentStatePagerAdapter(FragmentManager fm) {
mFragmentManager = fm;
}
/**
* Return the Fragment associated with a specified position.
*/
public abstract Fragment getItem(int position);
@Override
public void startUpdate(ViewGroup container) {}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
// DONE Remove of the add process of the old stuff
/* if (mFragments.size() > position) { Fragment f = mFragments.get(position); if (f != null) { return f; } } */
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
Fragment fragment = getItem(position);
if (DEBUG)
Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
if (mSavedState.size() > position) {
Fragment.SavedState fss = mSavedState.get(position);
if (fss != null) {
try // DONE: Try Catch
{
fragment.setInitialSavedState(fss);
} catch (Exception ex) {
// Schon aktiv (kA was das heißt xD)
}
}
}
while (mFragments.size() <= position) {
mFragments.add(null);
}
fragment.setMenuVisibility(false);
mFragments.set(position, fragment);
mCurTransaction.add(container.getId(), fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment) object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
mCurTransaction.remove(fragment);
/*if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object + " v=" + ((Fragment)
* object).getView()); while (mSavedState.size() <= position) { mSavedState.add(null); } mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
* mFragments.set(position, null); mCurTransaction.remove(fragment); */
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment) object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
}
mCurrentPrimaryItem = fragment;
}
}
@Override
public void finishUpdate(ViewGroup container) {
if (mCurTransaction != null) {
mCurTransaction.commitAllowingStateLoss();
mCurTransaction = null;
mFragmentManager.executePendingTransactions();
}
}
@Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment) object).getView() == view;
}
@Override
public Parcelable saveState() {
Bundle state = null;
if (mSavedState.size() > 0) {
state = new Bundle();
Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
mSavedState.toArray(fss);
state.putParcelableArray("states", fss);
}
for (int i = 0; i < mFragments.size(); i++) {
Fragment f = mFragments.get(i);
if (f != null) {
if (state == null) {
state = new Bundle();
}
String key = "f" + i;
mFragmentManager.putFragment(state, key, f);
}
}
return state;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
if (state != null) {
Bundle bundle = (Bundle) state;
bundle.setClassLoader(loader);
Parcelable[] fss = bundle.getParcelableArray("states");
mSavedState.clear();
mFragments.clear();
if (fss != null) {
for (int i = 0; i < fss.length; i++) {
mSavedState.add((Fragment.SavedState) fss[i]);
}
}
Iterable<String> keys = bundle.keySet();
for (String key : keys) {
if (key.startsWith("f")) {
int index = Integer.parseInt(key.substring(1));
Fragment f = mFragmentManager.getFragment(bundle, key);
if (f != null) {
while (mFragments.size() <= index) {
mFragments.add(null);
}
f.setMenuVisibility(false);
mFragments.set(index, f);
} else {
Log.w(TAG, "Bad fragment at key " + key);
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我正常的FragmentAdapter.java
package com.tundem.webLab.Adapter;
import java.util.LinkedList;
import java.util.List;
import android.support.v4.app.FragmentManager;
import com.tundem.webLab.fragments.BaseFragment;
import com.viewpagerindicator.TitleProvider;
public class FragmentAdapter extends CustomFragmentStatePagerAdapter implements TitleProvider {
public List<BaseFragment> fragments = new LinkedList<BaseFragment>();
private int actPage;
public FragmentAdapter(FragmentManager fm) {
super(fm);
}
public void setActPage(int actPage) {
this.actPage = actPage;
}
public void addItem(BaseFragment fragment) {
// TODO if exists don't open / change to that tab
fragments.add(fragment);
}
public BaseFragment getActFragment() {
return getItem(getActPage());
}
public int getActPage() {
return actPage;
}
@Override
public BaseFragment getItem(int position) {
if (position < getCount()) {
return fragments.get(position);
} else
return null;
}
@Override
public int getCount() {
return fragments.size();
}
@Override
public String getTitle(int position) {
return fragments.get(position).getTitle();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我删除片段的方式.(我知道它不仅仅是.remove()).可以自由地改进我的解决方案,你也可以在适配器的某处添加此代码,所以是的.这取决于试图实现此目的的用户.我在我的TabHelper.java中使用它(一个处理所有标签操作的类,如delete,add,...)
int act = Cfg.mPager.getCurrentItem();
Cfg.mPager.removeAllViews();
Cfg.mAdapter.mFragments.remove(act);
try {
Cfg.mAdapter.mSavedState.remove(act);
} catch (Exception ex) {/* Already removed */}
try {
Cfg.mAdapter.fragments.remove(act);
} catch (Exception ex) {/* Already removed */}
Cfg.mAdapter.notifyDataSetChanged();
Cfg.mIndicator.notifyDataSetChanged();
Run Code Online (Sandbox Code Playgroud)
制造商的描述.事情.我在cfg,类中保存对这些对象的引用,所以我总是可以使用它们而不需要特殊的Factory.java ...
是啊.我希望我能够提供帮助.随意改进这一点,但让我知道所以我也可以改进我的代码.
谢谢.
如果我错过了任何代码,请告诉我.
我的旧答案也有效但只有你有不同的碎片.FileFragment,WebFragment,...如果您使用其中一个片段类型,则不会.
我现在已经伪工作了.这是一个非常脏的解决方案,我仍然在寻找一个更好的解决方案.请帮忙.
我更改了代码,我在这里删除了一个标签:
public static void deleteActTab()
{
//We set this on the indicator, NOT the pager
int act = Cfg.mPager.getCurrentItem();
Cfg.mAdapter.removeItem(act);
List<BaseFragment> frags = new LinkedList<BaseFragment>();
frags = Cfg.mAdapter.fragments;
Cfg.mPager = (ViewPager)Cfg.act.findViewById(R.id.pager);
Cfg.mPager.setAdapter(Cfg.mAdapter);
Cfg.mIndicator.setViewPager(Cfg.mPager);
Cfg.mAdapter.fragments = frags;
if(act > 0)
{
Cfg.mPager.setCurrentItem(act-1);
Cfg.mIndicator.setCurrentItem(act-1);
}
Cfg.mIndicator.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)
如果有人可以改进此代码,请告诉我.如果有人能告诉我们这个问题的真实答案.请在这里添加.有很多人遇到过这个问题.我为解决它的人增加了50的声誉.我也可以为解决它的人捐款.
谢谢
| 归档时间: |
|
| 查看次数: |
34727 次 |
| 最近记录: |