4

Я работаю над разработкой приложения для Android, которое использует ActionBarSherlock и ViewPagerIndicator. Основное действие - это функция SherlockFragmentActivity, и пользователи перемещаются между фрагментами через вкладки на панели действий. Все вкладки - это SherlockListFragments, и большинство из них содержат только ListView. Однако один фрагмент (HeadlinesFragment) содержит ViewPager, CirclePageIndicator и ListView для планшетов и только ListView на телефонах. ViewPager имеет FragmentStatePagerAdapter, который возвращает элемент SherlockFragment для элементов.Фрагмент в ViewPager on Fragment не перезагружается при изменении ориентации

Проблема в том, что при изменении ориентации (или в любом изменении конфигурации) дочерние фрагменты внутри ViewPager не перезагружаются, а CirclePagerIndicator не отображает никаких указателей, как если бы ViewPager был пуст. Однако ListView действительно перезагружается. При начальной загрузке фрагмента ViewPager работает правильно, но не после изменения ориентации.

MainActivity.java

public class MainActivity extends SherlockFragmentActivity { 
    // =============== Variable Declaration ================ 
    private HashMap<Integer, String> tabData; 
    private HashMap<Integer, String> tabExtra; 
    private Fragment currentFragment = null; 
    private Fragment savedFragment = null; 
    public ActionBar mActionBar; 
    public MenuItem mRefresh; 
    public static int mCurrentPos; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     HashMap<String, Object> savedData = (HashMap<String, Object>) getLastCustomNonConfigurationInstance(); 
     if (savedData != null) { 
      tabData = (HashMap<Integer, String>) savedData.get("tabData"); 
      tabExtra = (HashMap<Integer, String>) savedData.get("tabExtra"); 
      savedFragment = (Fragment) savedData.get("currentFragment"); 
      mCurrentPos = ((Integer) savedData.get("pos")).intValue(); 
     } else { 
      tabData = (HashMap<Integer, String>) getIntent().getExtras().getSerializable("tabData"); 
      tabExtra = (HashMap<Integer, String>) getIntent().getExtras().getSerializable("tabExtra"); 
      mCurrentPos = 0; 
     } 

     mActionBar = getSupportActionBar(); 
     Const.IsTablet = Utils.isTablet(MainActivity.this); 
     //if (!Const.IsTablet) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

     TypedArray tabs = getResources().obtainTypedArray(R.array.TabBars); 
     Tab tab; 
     for (int i = 0; i < tabs.length(); i++) { 
      String tabInfo[] = getResources().getStringArray(tabs.getResourceId(i, 0)); 
      tab = mActionBar.newTab().setText(tabInfo[1]); 

      if (tabInfo[0].equalsIgnoreCase("customizedNewsPage")) { 
       tab.setTabListener(new MainTabListener<HeadlinesFragment>(MainActivity.this, i, HeadlinesFragment.class)); 
      } 
      mActionBar.addTab(tab); 
     } 
     tabs.recycle(); 
     mActionBar.selectTab(mActionBar.getTabAt(mCurrentPos)); 
     mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
     //set navbar for ICS+ devices 
     mActionBar.setBackgroundDrawable(getResources().getDrawable(R.drawable.navbar)); 
    } 

    @SuppressLint("HandlerLeak") 
    private Handler mHandler = new Handler() { 
     @Override 
     public void handleMessage(Message message) { 
      Bundle bundle = message.getData(); 
      if (bundle.getInt("result") == Activity.RESULT_OK && bundle.getString("data") != null) { 
       tabData.put(Integer.valueOf(bundle.getInt("tabPos")), bundle.getString("data")); 
       DataType type = DataType.values()[bundle.getInt("type")]; 
       switch (type) { 
        case Headlines: 
         ((HeadlinesFragment) currentFragment).setData(bundle.getString("data")); 
         break; 
       } 
       tabData.put(Integer.valueOf(bundle.getInt("tabPos")), bundle.getString("data")); 
       setRefreshActionButtonState(false); 
      } 
     } 
    }; 

    public Handler getHandler() { 
     return mHandler; 
    } 

    @Override 
    public Object onRetainCustomNonConfigurationInstance() { 
     final HashMap<String, Object> savedData = new HashMap<String, Object>(); 
     savedData.put("currentFragment", currentFragment); 
     savedData.put("tabData", tabData); 
     savedData.put("tabExtra", tabExtra); 
     savedData.put("pos", Integer.valueOf(mCurrentPos)); 
     return savedData; 
    } 

    private class MainTabListener<T extends Fragment> implements TabListener { 
     private Fragment mFragment; 
     private final SherlockFragmentActivity mActivity; 
     private final int mPos; 
     private final Class<T> mClass; 

     /** Constructor used each time a new tab is created. */ 
     public MainTabListener(SherlockFragmentActivity activity, int pos, Class<T> clz) { 
      mActivity = activity; 
      mPos = pos; 
      mClass = clz; 
     } 

     @Override 
     public void onTabSelected(Tab tab, FragmentTransaction ignoredFt) { 
      FragmentManager fragMgr = ((FragmentActivity) mActivity).getSupportFragmentManager(); 
      FragmentTransaction ft = fragMgr.beginTransaction(); 

      // Check if the fragment is already initialized 
      if (mFragment == null) { 
       // If not, instantiate and add it to the activity 
       mFragment = Fragment.instantiate(mActivity, mClass.getName()); 

       Bundle args = new Bundle(); 
       args.putString("data", tabData.get(mPos)); 
       args.putInt("pos", mPos); 
       mFragment.setArguments(args); 

       ft.add(android.R.id.content, mFragment); 
      } else { 
       ft.attach(mFragment); 
      } 
      currentFragment = mFragment; 
      mCurrentPos = mPos; 
      mRefresh = null; 

      ft.commit(); 
     } 

     @Override 
     public void onTabUnselected(Tab tab, FragmentTransaction ignoredFt) { 
      FragmentManager fragMgr = ((FragmentActivity) mActivity).getSupportFragmentManager(); 
      FragmentTransaction ft = fragMgr.beginTransaction(); 

      fragMgr.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 

      // Check if the fragment is already initialized 
      if (mFragment == null) { 
       mFragment = SherlockFragment.instantiate(mActivity, mClass.getName()); 
       ft.add(android.R.id.content, mFragment); 
      } else { 
       ft.detach(mFragment); 
      } 
      currentFragment = null; 

      ft.commit(); 
     } 

     @Override 
     public void onTabReselected(Tab tab, FragmentTransaction ignoredFt) { 
      onTabUnselected(tab, ignoredFt); 
      onTabSelected(tab, ignoredFt); 
     } 
    } 
} 

HeadlinesFragment.java

public class HeadlinesFragment extends SherlockListFragment implements SearchView.OnQueryTextListener, SearchView.SearchViewChangeMode, OnItemClickListener { 
    private static final String LOG_TAG = "Headlines Fragment"; 
    private JSONArray mHeadlines = new JSONArray(); 
    private JSONArray mHeadlinesTop = new JSONArray(); 
    private SearchView mSearchView; 
    private MenuItem mSearchItem; 
    private ViewPager mPager; 
    private CirclePageIndicator mIndicator; 
    private static int mPos; 
    private int mRotatorImageWidth; 
    private static HeadlinesFragment instance; 
    private Tracker tracker; 
    private Timer refreshTimer; 
    private int refreshTime = 0;; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 
     instance = this; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     mPos = getArguments().getInt("pos"); 
     TypedArray tabs = getResources().obtainTypedArray(R.array.TabBars); 
     String tabInfo[] = getResources().getStringArray(tabs.getResourceId(mPos, 0)); 
     mRotatorImageWidth = Integer.valueOf(tabInfo[7]).intValue(); 
     refreshTime = Integer.valueOf(tabInfo[4]).intValue(); 
     tabs.recycle(); 

     try { 
      mHeadlines = new JSONArray(getArguments().getString("data")); 
     } catch (NotFoundException e) { 
      Log.e(LOG_TAG, "Error loading data", e); 
     } catch (JSONException e) { 
      Log.e(LOG_TAG, "Error loading data", e); 
     } 

     return inflater.inflate(R.layout.activity_headlines, container, false); 
    } 

    @SuppressWarnings("deprecation") 
    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState) { 
     super.onViewCreated(view, savedInstanceState); 

     //if (Const.IsTablet) { 
     if (((SIDHelpApplication) getActivity().getApplicationContext()).isTablet()) { 
      try { 
       mHeadlinesTop = new JSONArray(); 
       JSONArray temp = new JSONArray(); 
       for (int i = 0; i < mHeadlines.length(); i++) { 
        if (i < 5) { 
         mHeadlinesTop.put(mHeadlines.get(i)); 
        } else { 
         temp.put(mHeadlines.get(i)); 
        } 
       } 
       mHeadlines = temp; 
      } catch (JSONException e) { 
       Log.e(LOG_TAG, "Error splitting off top 5", e); 
      } 

      mPager = (ViewPager) getActivity().findViewById(R.id.rotator); 
      mPager.setOffscreenPageLimit(4); 
      mPager.setAdapter(new RotatorAdapter(this, getActivity(), mHeadlinesTop, mRotatorImageWidth, mPos)); 
      if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { 
       mPager.getLayoutParams().height = (int) Math.floor((((float) getResources().getInteger(R.integer.NewsImageHeight)/(float) getResources().getInteger(R.integer.NewsImageWidth)) * (float) getActivity().getWindowManager().getDefaultDisplay().getWidth())); 
      } 

      mIndicator = (CirclePageIndicator) getActivity().findViewById(R.id.indicator); 
      mIndicator.setViewPager(mPager); 
     } 

     setListAdapter(new HeadlinesAdapter(getSherlockActivity(), mHeadlines)); 
     getListView().setOnItemClickListener(this); 
     getListView().setEmptyView(getActivity().findViewById(android.R.id.empty)); 
     setAutoRefresh(); 
    } 

    public void setData(String data) { 
     setData(data, false); 
    } 

    public void setData(String data, boolean search) { 
     try { 
      mHeadlines = new JSONArray(data); 
      if (((SIDHelpApplication) getActivity().getApplicationContext()).isTablet() && !search) { 
       mHeadlinesTop = new JSONArray(); 
       try { 
        JSONArray temp = new JSONArray(); 
        for (int i = 0; i < mHeadlines.length(); i++) { 
         if (i < 5) { 
          mHeadlinesTop.put(mHeadlines.get(i)); 
         } else { 
          temp.put(mHeadlines.get(i)); 
         } 
        } 
        mHeadlines = temp; 
       } catch (JSONException e) { 
        Log.e(LOG_TAG, "Error splitting off top 5", e); 
       } 

       ((RotatorAdapter) mPager.getAdapter()).setData(mHeadlinesTop); 
       mPager.setVisibility(View.VISIBLE); 
       mIndicator.setVisibility(View.VISIBLE); 
      } else { 
       getActivity().findViewById(android.R.id.empty).setVisibility(View.GONE); 
      } 

      if (search && mPager != null) { 
       mPager.setVisibility(View.GONE); 
       mIndicator.setVisibility(View.GONE); 
      } 

      ((HeadlinesAdapter) getListAdapter()).setData(mHeadlines); 
      setAutoRefresh(); 
     } catch (JSONException e) { 
      Log.e(LOG_TAG, "Setting Data", e); 
     } 
    } 

    public static HeadlinesFragment getInstance() { 
     return instance; 
    } 
} 

activity_headlines.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/llMainHeadline" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:focusable="false" 
    android:focusableInTouchMode="true" 
    android:background="@drawable/bg_img" > 

    <android.support.v4.view.ViewPager 
     android:id="@+id/rotator" 
     android:layout_width="match_parent" 
     android:layout_height="@dimen/headlines_rotator_height" 
     android:layout_alignParentTop="true" 
     android:background="@android:color/black" /> 

    <com.viewpagerindicator.CirclePageIndicator 
     android:id="@+id/indicator" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_below="@id/rotator" 
     android:background="@android:color/black" 
     android:padding="10dp" /> 

    <ListView 
     android:id="@android:id/list" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_alignParentBottom="true" 
     android:layout_below="@id/indicator" 
     android:cacheColorHint="#00000000" 
     android:listSelector="@color/TableCellSelection" /> 

    <TextView 
     android:id="@android:id/empty" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerInParent="true" 
     android:text="@string/noResults" 
     android:textSize="@dimen/noResult_text_size" 
     android:textStyle="bold" 
     android:visibility="gone" /> 

</RelativeLayout> 

RotatorAdapter.java

public class RotatorAdapter extends FragmentStatePagerAdapter { 
    private static final String LOG_TAG = "Rotator Adapter"; 
    private Context mContext; 
    private JSONArray mData; 
    private int mImageWidth; 
    private int mPos; 

    public RotatorAdapter(SherlockListFragment fragment, Context context, JSONArray data, int imageWidth, int pos) { 
     super(fragment.getChildFragmentManager()); 
     mContext = context; 
     mData = data; 
     mImageWidth = imageWidth; 
     mPos = pos; 
    } 

    @Override 
    public int getCount() { 
     return mData.length(); 
    } 

    @Override 
    public Fragment getItem(int pos) { 
     Fragment fragment = null; 
     Bundle args = new Bundle(); 
     try { 
      JSONObject hdata = mData.getJSONObject(pos); 
      args.putString("title", hdata.getString(mContext.getResources().getString(R.string.tag_title))); 
      args.putString("category", hdata.getString(mContext.getResources().getString(R.string.tag_category))); 
      args.putString("time", hdata.getString(mContext.getResources().getString(R.string.tag_time))); 
      args.putString("newsID", hdata.getString(mContext.getResources().getString(R.string.tag_newsID))); 
      args.putString("photoURL", hdata.getString(mContext.getResources().getString(R.string.tag_photoURL))); 
      args.putInt("imageWidth", mImageWidth); 
      args.putInt("pos", mPos); 
      fragment = Fragment.instantiate(mContext, RotatorFragment.class.getName(), args); 
     } catch (JSONException e) { 
      Log.e(LOG_TAG, "Error getting data", e); 
     } 

     return fragment; 
    } 

    public void setData(JSONArray data) { 
     mData = data; 
     notifyDataSetChanged(); 
    } 
} 

RotatorFragment.java

public class RotatorFragment extends SherlockFragment implements OnClickListener { 
    private static final String LOG_TAG = "Rotator Fragment"; 
    private String mNewsID; 
    private int mPos; 
    private ImageLoader imageLoader = ImageLoader.getInstance(); 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.activity_headlines_top_row, container, false); 

     // Set the image 
     ImageView image = (ImageView) view.findViewById(R.id.imgArticle); 
     String photoURL = getArguments().getString("photoURL").replaceAll(" ", "%20"); 
     imageLoader.displayImage(photoURL, image); 

     // Set title, category, and time 
     TextView headlineTitle = (TextView) view.findViewById(R.id.txtTitle); 
     TextView headlineCategory = (TextView) view.findViewById(R.id.txtCategory); 
     headlineTitle.setText(getArguments().getString("title")); 
     headlineCategory.setText(String.format("%s - %s", getArguments().getString("category"), getArguments().getString("time"))); 

     // Set article ID for onclick listener 
     mNewsID = getArguments().getString("newsID"); 
     mPos = getArguments().getInt("pos"); 
     view.setOnClickListener(this); 
     return view; 
    } 

    @Override 
    public void onClick(View v) { 
     // Load article data 
     Log.i(LOG_TAG, "Loading Article"); 
     Intent dataIntent = new Intent(getActivity(), DataLoader.class); 
     Messenger dataMessenger = new Messenger(HeadlinesFragment.mHandler); 
     dataIntent.putExtra("MESSENGER", dataMessenger); 
     dataIntent.putExtra("tabPos", mPos); 
     dataIntent.putExtra("type", DataType.HeadlinesArticle.ordinal()); 
     String params[] = new String[] {mNewsID}; 
     dataIntent.putExtra("params", params); 
     getActivity().startService(dataIntent); 
    } 

    @Override 
    public void onSaveInstanceState (Bundle outState) { 
     // Don't save the fragment state 
    } 
} 

ответ

1

Я понял вопрос. Проблема заключалась в изменении конфигурации, Android уничтожил и воссоздал Activity, но фрагменты не уничтожались. Они были добавлены обратно менеджеру и из-за кода были также воссозданы. Поэтому ViewPager, который не был создан при создании нового фрагмента, не ссылался на него правильно. Исправление для этого было в функции onTabSelected, я сделал чек для Фрагмента, уже существующего в менеджере, и просто использовал это вместо воссоздания. Мне также пришлось добавлять теги к каждому созданному фрагменту, чтобы я мог найти фрагмент, который я искал.

if (mCurrentTag != null && mCurrentTag.equalsIgnoreCase(mTag) && fragMgr.findFragmentByTag(mCurrentTag) != null) { 
    mFragment = fragMgr.findFragmentByTag(mCurrentTag); 
} 
+0

где положить этот код? –

+0

Я просто setRetainedInstance (true) и работает хорошо –

+0

Вы можете упростить свой код, просто позвонив mFragment = fragMrg.findFragmentByTag (mCurrentTag) и затем проверьте mFragment == null. –

Смежные вопросы