2012-01-29 11 views
6

コンテンツ削除ページを取得し、削除されます場合は(誰かがより多くの情報を必要とする、またはより良い説明を私に知らせた場合)Viewpager:ページが次のページのコンテンツは

こんにちは、私はここからviewPagerLibraryを含ま:http://viewpagerindicator.com/#introduction今日で私のプロジェクト。

いいえ、私は本当に奇妙な問題を抱えています: 私はサイトやページを追加して(それを次の数行でサイトに呼びましょう)、もう一度削除しても問題ありません。しかし、別のページを追加しようとすると(それらのページはBaseFragmentクラスを実装する異なるフラグメントです)、最初のページの内容が表示されます。 私はいくつかのページを追加し、それらのページの中に1つを削除すると同じことが起こります。削除されたページの後にあるページに、削除されたページのコンテンツが表示されます。

このバグの例: 問題は現在です。そのFragmentBの後にFragmentAを追加すると、FragmentAを削除し、FragmentBはFragmentAのビュー/コンテンツを取得します。奇妙なことは、オブジェクトが正しいものだからです(アダプタが正しいオブジェクトを返します)。タイトルも正しいものです。私のメインで

私はこの方法で私のポケットベル、インジケータやアダプタを作成します。

Cfg.mAdapter = new FragmentAdapter(getSupportFragmentManager()); 

    Cfg.mPager = (ViewPager)findViewById(R.id.pager); 
    Cfg.mPager.setAdapter(Cfg.mAdapter); 

    Cfg.mIndicator = (TabPageIndicator)findViewById(R.id.indicator); 
    Cfg.mIndicator.setViewPager(Cfg.mPager); 

    //We set this on the indicator, NOT the pager 
    Cfg.mIndicator.setOnPageChangeListener(TabHelper.onPageChangeListener); 

(CFGは、使用のためそれらのものを格納するための静的なファイルである)

私BaseFragmentは次のようになります。 :フラグメントの

public class BaseFragment extends Fragment{ 

    public static int FILE_FRAGMENT = 0; 
    public static int FTP_FRAGMENT = 1; 
    public static int ADDFTP_FRAGMENT = 2; 
    public static int PREVIEW_FRAGMENT = 3; 
    public static int CSS_FRAGMENT = 4; 
    public static int BOOKS_FRAGMENT = 5; 
    public static int SNIPPETS_FRAGMENT = 6; 

    //private int id; 
    private int typ; 
    private String title; 

    public int getTyp() { 
     return typ; 
    } 

    public void setTyp(int typ) { 
     this.typ = typ; 
    } 

    public String getTitle() { 
     return title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 
} 

一つは、(私は他のフラグメントは違いはありませんと思います)、次のようになります

public class FtpFragment extends BaseFragment { 
    private static RowLayout rowLayout_view; 

    public FtpFragment() { 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     init_data(); 
    } 

    public static void init_data() 
    { 
     //Remove child for update 
     rowLayout_view.removeAllViews(); 

     List<FtpData> ftps = FtpStorage.getInstance().getFtps(); 

     if (ftps != null) { 
      for (FtpData f : ftps) { 
       View inflatedView; 
       inflatedView = View.inflate(Cfg.ctx, R.layout.ftp, null); 
       inflatedView.setOnClickListener(button_ftp_listener); 
       inflatedView.setOnLongClickListener(button_ftp_longClickListener); 
       inflatedView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, Converter.convertFromDPtoPixel(160.0f))); 
       inflatedView.setTag(f); 
       inflatedView.findViewById(R.id.book_imageview).setBackgroundDrawable(
           Cfg.ctx.getResources().getDrawable(R.drawable.nopreview)); 


       ((TextView) inflatedView.findViewById(R.id.book_textview)).setText(f.nickname); 

       rowLayout_view.addView(inflatedView); 
      } 
     } 
    } 

    @Override 

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.fragment_ftp, container, false); 
    rowLayout_view = (RowLayout) v.findViewById(R.id.rowLayout_ftps); 
    return v; 
} 

@Override 
public String getTitle() { 
    return "FTPs"; 
} 

@Override 
public int getTyp() { 
    return BaseFragment.FTP_FRAGMENT; 
} 

@Override 
public void setTyp(int typ) { 
    super.setTyp(typ); 
} 

}

ページを削除または追加するには、私はこれを呼び出す:

public static void addNewTab(BaseFragment fragment) 
{ 
    Cfg.mAdapter.addItem(fragment); 
    Cfg.mPager.setCurrentItem(Cfg.mAdapter.getCount()); 
    Cfg.mIndicator.notifyDataSetChanged(); 
} 

public static void deleteActTab() 
{ 
    Cfg.mAdapter.removeItem(Cfg.mAdapter.getActPage()); 
    Cfg.mIndicator.notifyDataSetChanged(); 
} 

そして、それはアダプタです:

public class FragmentAdapter extends FragmentPagerAdapter implements TitleProvider{ 
    public List<BaseFragment> fragments = new LinkedList<BaseFragment>(); 

    private int actPage; 

    public FragmentAdapter(FragmentManager fm) { 
     super(fm); 
    } 


    public void setActPage(int actPage) { 
     Lg.d("setActPage: " + actPage + " : " + fragments.get(actPage).toString()); 
     this.actPage = actPage; 
    } 

    public void addItem(BaseFragment fragment) 
    { 
     Lg.d("addItem: " + fragment.toString()); 
     fragments.add(fragment); 
    } 

    public void removeItem(int index) 
    { 
     if(index < getCount()){ 
      Lg.d("RemoveItem: " + index + " : " + fragments.get(index).toString()); 
      fragments.remove(index); 
     } 
    } 

    public BaseFragment getActFragment() 
    { 
     return getItem(getActPage()); 
    } 

    public int getActPage() { 
     return actPage; 
    } 

    @Override 
    public BaseFragment getItem(int position) { 
     if(position < getCount()) 
     { 
      Lg.v("getItem: " + fragments.get(position)); 
      return fragments.get(position); 
     } 
     else 
      return null; 
    } 

    @Override 
    public int getCount() { 
     return fragments.size(); 
    } 

    @Override 
    public String getTitle(int position) { 
     Lg.v("Get Title: " + fragments.get(position).getTitle()); 
     return fragments.get(position).getTitle(); 
    } 

} 

うん、私は、誰かが私を助けることができると思います。

私は何かを忘れてしまった場合。事前に

おかげで、(mikepenzによって)あなたの答えで マイク

+0

ここに問題の言及に関する提案があります。http://stackoverflow.com/q/25159181/2624806 – CoDe

答えて

2

私は今、問題を解決しましたが、うんざりしています;)。誰かが私の解決策を改善できる場合は、私に知らせてください。私の新しいソリューションでは、CustomFragmentStatePagerAdapterを使用しますが、状態を保存せずにすべてのフラグメントをリストに保存します。これにより、通常のFragmentPagerAdapterのように、ユーザーが50を超えるフラグメントを持つとメモリの問題が発生する可能性があります。誰かが私の解決策を取り除くことなく私の解決策に状態を戻すことができれば幸いです。ありがとう。

は、だからここにここに私の通常の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; 
    } 
} 

だと、これは私がフラグメントを削除する方法です私の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); 
        } 
       } 
      } 
     } 
    } 
} 

です。 (私はそれがちょうど.remove()よりもはるかに多いことを知っています)。私のソリューションを改善するために自由に、あなたもアダプタのどこかにこのコードを追加することができます。これを実装しようとするのはユーザーの責任です。私はCFGの私のTabHelper.java(削除などのすべてのタブの操作を処理するクラスは、追加、...)

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(); 

説明でこれを使用しています。もの。これらのオブジェクトへの参照をcfgクラスに保存するので、いつも特別なFactory.javaを必要とせずに使用できます。

ええと。私は助けてくれることを願っています。私のコードを改善することができますので、私に教えてください。

ありがとうございました。

もし私がコードを見逃していたら私に知らせてください。


私の古い答えは、あなたが別の断片を持っている場合にのみ機能します。 FileFragment、WebFragment、...これらのフラグメントタイプのいずれかを2回使用しているわけではありません。

私は今のところ擬似的に働いています。それは本当に汚い解決策であり、私はまだより良いものを探しています。助けてください。このコードを向上させることができ、誰かが私に知らせた場合

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(); 
     } 

は、私は私はこの1つにタブを削除するコードを、変更しました。誰かがその問題の本当の答えを教えてくれれば。ここに追加してください。この問題を経験する多くの人がいます。私はそれを解決する人に50の評判を付けました。私はそれを解決する人にも寄付をすることができます。

おかげ

0

は、再度アダプタを設定する必要はありません。 notifyDataSetChangedを呼び出すことができます。

public static void deleteActTab(){ 

     //We set this on the indicator, NOT the pager 
     int act = Cfg.mPager.getCurrentItem(); 
     Cfg.mAdapter.removeItem(act);   


     if(act > 0) 
     { 
      Cfg.mPager.setCurrentItem(act-1); 
      Cfg.mIndicator.setCurrentItem(act-1); 
     } 
     //Also add conditions to check if there are any remaining fragments 


     Cfg.mIndicator.notifyDataSetChanged(); 
} 

パフォーマンスを向上させるためにHashMap<Integer, Fragment>ArrayAdapter<Fragment>を使用することを検討したり、すでにそれを使用していましたか? また、なぜBaseFragmentで静的メソッドを使用しますか?これらのメモリがリークした場合は、MATまたはlogcatを使用してメモリの使用状況を確認してください。

+0

私の元の質問で見ることができますが、私はあなたがここで言及したようにそれをしました。しかし、コンテンツが正しく更新されないため、このことは機能しません。 mPagerは正しいフラグメントを管理していないようです。 HashMapまたはArrayAdapterの意味をより高度なサンプルコードで伝えられますか?私はBaseFragmentを拡張する別のフラグメントを使用していることに注意してください。 – mikepenz

0

あなたはbackstackから指定されたフラグメントを削除する必要があり、この問題を回避するには。リストからフラグメントを削除するたびに、それはバックスタットに残り、内容はそのまま残ります。リストからフラグメントを削除する前に、FragmentTransactionを使用してページを削除する必要があります。それで、コードはこのようなものかもしれません。

public void removePage(int currentPage) { 
    for (int i = pageFragmentList.size() - 1; i >= currentPage; i--) { 
     ((MainActivity) context).getSupportFragmentManager().beginTransaction() 
       .remove(pageFragmentList.get(i)).commit(); 
    } 
    pageFragmentList.remove(currentPage); 
} 

あなたは、現在のページの後にインデックスを作成したすべてのページを削除し、のみbackstackから現在のページを削除しない場合は、例外をスローする可能性があります。

関連する問題