2012-01-29 8 views
6

(किसी में अधिक जानकारी की जरूरत है, या एक बेहतर विवरण मुझे पता है तो)Viewpager: अगर पेज भी निकल जाते हैं अगले पृष्ठ सामग्री नष्ट कर पृष्ठों की सामग्री हो जाता है

हैलो मैं यहाँ से viewPagerLibrary शामिल: में http://viewpagerindicator.com/#introduction आज मेरी परियोजना।

नहीं मुझे वास्तव में एक अजीब समस्या मिलती है: यदि मैं कोई साइट या पेज जोड़ता हूं (चलिए इसे अगले कुछ पंक्तियों में साइट कहते हैं) और इसे फिर से हटा दें सब कुछ ठीक है। लेकिन अगर मैं एक अलग पृष्ठ जोड़ने की कोशिश करता हूं (वे पृष्ठ अलग-अलग फ्रेजमेंट हैं जो बेसफ्रैगमेंट क्लास लागू करते हैं) पहले पृष्ठ की सामग्री दिखायी जाती है। वही बात होती है यदि मैं कुछ पेज जोड़ता हूं और उन पृष्ठों के बीच एक को हटा देता हूं। हटाए गए पृष्ठ के बाद वाला पृष्ठ अब हटाए गए पृष्ठों की सामग्री दिखाता है।

इस बग का एक उदाहरण: समस्या अब है। अगर मैं उस 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); 

मेरे BaseFragment ऐसा दिखाई देता है (CFG एक स्थिर उपयोग के लिए उन चीजों को स्टोर करने के लिए फ़ाइल है) :

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

} 

हाँ मैं आशा कोई मेरी मदद कर सकते हैं।

अगर मैं कुछ भूल गया तो मुझे बताएं।

अग्रिम धन्यवाद, माइक

+0

समस्या का कोई सुझाव यहां उल्लेख किया गया है http://stackoverflow.com/q/25159181/2624806 – CoDe

उत्तर

2

ठीक है अब मैंने अपनी समस्या को हैकिश तरीके से हल कर लिया है, लेकिन हाँ यह काम कर रहा है;)। अगर कोई मेरा समाधान सुधार सकता है तो कृपया मुझे बताएं। मेरे नए समाधान के लिए अब मैं एक कस्टमफ्रैगमेंटस्टेट पेजर एडाप्टर का उपयोग करता हूं लेकिन यह राज्य को इस तरह से सहेजता नहीं है जैसे कि सभी टुकड़ों को सूची में रखना चाहिए और स्टोर करना चाहिए।यदि उपयोगकर्ता के पास 50 से अधिक टुकड़े हैं, जैसे सामान्य FragmentPagerAdapter करता है, तो यह स्मृति समस्या का कारण बन सकता है। यह बहुत अच्छा होगा अगर कोई मेरे फिक्स को हटाए बिना राज्य-चीज़ को मेरे समाधान में वापस जोड़ सके। धन्यवाद।

तो यहाँ मेरी 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); 
        } 
       } 
      } 
     } 
    } 
} 

है यहाँ मेरी सामान्य 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; 
    } 
} 

है और इस तरह मैं एक टुकड़ा हटाना है। (मुझे पता है कि यह केवल थोड़ी अधिक है .remove())। मेरे समाधान को बेहतर बनाने के लिए स्वतंत्र रहें, आप इस कोड को एडाप्टर में कहीं भी जोड़ सकते हैं ताकि हाँ। यह उस उपयोगकर्ता पर निर्भर है जो इसे लागू करने का प्रयास करता है। मैं अपने TabHelper.java में इस का उपयोग (एक वर्ग जो नष्ट की तरह सभी टैब संचालन संभालती है, जोड़, ...) cfg की

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

विवरण। चीज़। मैं उन वस्तुओं के संदर्भ को एक सीएफजी, कक्षा में सहेजता हूं ताकि मैं हमेशा उन्हें विशेष फैक्ट्री की आवश्यकता के बिना उपयोग कर सकूं। जावा ...

हाँ। मुझे उम्मीद है कि मैं मदद करने में सक्षम था। इसे बेहतर बनाने के लिए स्वतंत्र महसूस करें, लेकिन मुझे बताएं ताकि मैं अपना कोड भी सुधार सकूं।

धन्यवाद।

यदि मुझे कोई कोड याद आया तो मुझे बताएं।


मेरा पुराना उत्तर भी काम करता है लेकिन केवल तभी होता है जब आपके पास अलग-अलग टुकड़े हों। फ़ाइलफ्रेगमेंट, वेबफ्रैगमेंट, ... यदि आप दो बार उन खंडों में से एक का उपयोग नहीं करते हैं।

मुझे अब यह छद्म काम मिल गया है। यह वास्तव में गंदा समाधान है और मैं अभी भी एक बेहतर खोज रहा हूं। कृपया मदद करे। अगर किसी के लिए इस कोड में सुधार कर सकते मुझे पता है

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

:

मैं कोड है, जहां मैं इस एक के लिए किसी टैब को हटाने बदल दिया है। अगर कोई हमें उस समस्या के वास्तविक जवाब बता सकता है। कृपया इसे यहां जोड़ें। इस मुद्दे का अनुभव करने वाले बहुत से लोग हैं। मैंने इसे हल करने वाले व्यक्ति के लिए 50 की प्रतिष्ठा को जोड़ा। मैं इसे हल करने वाले व्यक्ति के लिए भी दान दे सकता हूं।

धन्यवाद

0

(mikepenz द्वारा) अपने जवाब में, आप एडाप्टर फिर से स्थापित करने की आवश्यकता नहीं है। आप 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> का उपयोग कर प्रदर्शन में सुधार करने या पहले से ही यह प्रयोग करने पर विचार? इसके अलावा, आप बेसफ्रैगमेंट में स्थिर विधि का उपयोग क्यों करते हैं? अगर इन रिसाव मेमोरी मेमोरी उपयोग की जांच करने के लिए कृपया MAT या logcat का उपयोग करने पर विचार करें।

+0

जैसा कि आप मेरे मूल प्रश्न में देख सकते हैं, मैंने ऐसा किया जैसा आपने यहां उल्लेख किया है।लेकिन यह बात काम नहीं कर रही है क्योंकि सामग्री सही अपडेट नहीं होगी। ऐसा लगता है कि mPager टुकड़ों को सही ढंग से प्रबंधित नहीं करता है। क्या आप हैश मैप या ऐरेएडाप्टर के साथ क्या मतलब है इसका एक और उन्नत उदाहरण कोड दे सकते हैं? कृपया ध्यान रखें कि मैं अलग-अलग टुकड़ों का उपयोग करता हूं जो मेरा बेसफ्रैगमेंट बढ़ाता है। – 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 से वर्तमान पृष्ठ निकालते हैं, यह एक अपवाद फेंक सकता है।

संबंधित मुद्दे