片段上的ViewPager中的片段在方向更改时不会重新加载 [英] Fragment in ViewPager on Fragment doesn't reload on orientation change

本文介绍了片段上的ViewPager中的片段在方向更改时不会重新加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发使用ActionBarSherlock和ViewPagerIndicator的Android应用程序。主要活动是SherlockFragmentActivity,用户可通过操作栏上的选项卡在片段之间导航。所有选项卡都是SherlockListFragments,并且大多数仅包含ListView。但是,一个片段(HeadlinesFragment)包含一个ViewPager,CirclePageIndicator和一个用于平板电脑的ListView,而在手机上仅包含一个ListView。 ViewPager有一个FragmentStatePagerAdapter,它返回这些项目的SherlockFragment。

I am working on developing an Android application which uses ActionBarSherlock and ViewPagerIndicator. The main activity is a SherlockFragmentActivity and users navigate between the fragments via tabs on the action bar. All of the tabs are SherlockListFragments and most only contain a ListView. However, one fragment (HeadlinesFragment) contains a ViewPager, CirclePageIndicator, and a ListView for tablets, and only a ListView on phones. The ViewPager has a FragmentStatePagerAdapter which returns a SherlockFragment for the items.

问题是,在方向更改(或实际上是任何配置更改)时,ViewPager中的子片段会执行不会重新加载,并且CirclePagerIndicator不会显示任何指示符,就好像ViewPager为空。 ListView确实可以正确地重新加载。在片段的初始加载时,ViewPager可以正常工作,但在方向更改后无法正常工作。

The issue is, on orientation change (or any configuration change really), the child fragments inside the ViewPager do not get reloaded and the CirclePagerIndicator does not show any indictors as if the ViewPager is empty. The ListView does get reloaded properly however. On the initial load of the fragment, the ViewPager works correctly, but not after the orientation change.

MainActivity.java

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

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

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

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

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
    }
}


推荐答案

我发现了问题所在。问题是当配置更改时,Android会销毁并重新创建Activity,但Fragments没有被销毁。它们被重新添加到管理器中,并且由于代码的缘故,它们也被重新创建。因此创建新的Fragment时未重新创建的ViewPager无法正确引用它。解决此问题的方法是在onTabSelected函数中,我检查了管理器中已经存在的Fragment,只是使用它代替了重新创建它。我还必须向创建的每个片段中添加标签,以便找到所需的片段。

I figured out the issue. The problem was when the configuration changed, Android would destroy and recreate the Activity, but the Fragments were not being destroyed. They were added back to the manager and due to the code were also being recreated. So the ViewPager which wasn't recreated when the new Fragment was created didn't reference it correctly. The fix for this was in the onTabSelected function I did a check for the Fragment already existing in the manager, and just used that instead of recreating it. I also had to add tags to every Fragment that was created so I could find the Fragment that I was looking for.

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

这篇关于片段上的ViewPager中的片段在方向更改时不会重新加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆