2013-08-06 34 views
28

tôi đang làm việc trên ứng dụng Android có chứa ViewPager với Fragment s, như thế này:mảnh ViewPager biến mất khi thay đổi màn hình xoay

MainActivity (MainActivityFragment (screenSlideViewPager (Fragment s))), có nghĩa là:

ActivitychứaFragmentchứaViewPagerchứaFragment s

Bây giờ vấn đề của tôi là khi xoay thiết bị hoặc thay đổi xoay màn hình, tất cả các Phân đoạn trong ViewPager sẽ biến mất.

bất kỳ ý tưởng nào để giải quyết vấn đề này?

EDIT 1

MainActivity.java:

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

    if (getSupportFragmentManager().findFragmentByTag(TAG) == null) { 
     final FragmentTransaction ft = getSupportFragmentManager() 
       .beginTransaction(); 
     ft.add(android.R.id.content, new MainActivityFragment(), TAG); 
     ft.commit(); 
    } 
} 

MainActivityFragment.java:

public class MainActivityFragment extends Fragment { 
    private ViewPager mPager = null; 
    private PagerAdapter mPageAdapter = null; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     final View reVal = inflater.inflate(R.layout.activity_main, container, false); 
     mPager = (ViewPager) reVal.findViewById(R.id.pagerMainContent); 
     mPageAdapter = new ScreenSlidePagerAdapter(getActivity().getFragmentManager()); 
     mPager.setAdapter(mPageAdapter); 
     return reVal; 
    } 

    private MainGridViewFragment mainGridFragment; 
    private AlphabetGridViewFragment alphabetGridFragment; 

    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { 
     public ScreenSlidePagerAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public android.app.Fragment getItem(int position) { 
      switch (position) { 
       case 1: 
        mainGridFragment = new MainGridViewFragment(); 
        return mainGridFragment; 
       case 0: 
        alphabetGridFragment = new AlphabetGridViewFragment(); 
        return alphabetGridFragment; 
       default: 
        return null; 
      } 
     } 

     @Override 
     public int getCount() { 
      return 2; 
     } 
    } 
} 

EDIT 2 The Activity After Screen Rotation

Rõ ràng là MainActivityMainActivityFragment được tải và chứng minh là ActionBar, cũng thông báo rằng ViewPager cũng được tải vì bạn vẫn có thể điều hướng giữa các trang (đèn xanh lam nghĩa là máy nhắn tin đã đến trang cuối) nhưng bạn không thể xem nội dung của nó.

+0

Câu hỏi hay, nhưng chúng tôi cần thêm mã để giúp bạn! –

+0

Khi có xoay màn hình trong Android, hoạt động của bạn bị hủy và tái tạo. Vì vậy, bạn cần phải lưu trạng thái của các biến của bạn và như vậy để bạn có thể "tiếp tục nơi bạn rời đi". Điều này có thể giúp http://developer.android.com/training/basics/activity-lifecycle/recreating.html –

+1

Tôi biết, tôi đã lưu trạng thái hoạt động, nhưng điều này không phá hủy vấn đề, Mọi thứ sẽ biến mất ngay cả các chế độ xem, tôi nghĩa là tôi đang phải đối mặt với màn hình trắng khi xoay thiết bị thay đổi (không có ngoại lệ) – MoHaKa

Trả lời

17

Có vẻ như hoạt động chính của bạn đang sử dụng getSupportFragmentManager() trong khi đoạn của bạn đang sử dụng getFragmentManager().

Không chắc chắn điều này có xứng đáng với bài đăng trả lời hay không nhưng xếp hạng của tôi quá thấp để trả lời theo bất kỳ cách nào khác. :)

Chỉnh sửa: Tôi tin rằng bạn cũng có thể cần mở rộng FragmentActivity bằng thư viện hỗ trợ.

Xem: https://stackoverflow.com/a/10609839/2640693

Chỉnh sửa 2:

public class MainActivityFragment extends FragmentActivity { 
    private ViewPager mPager = null; 
    private PagerAdapter mPageAdapter = null; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     final View reVal = inflater.inflate(R.layout.activity_main, container, false); 
     mPager = (ViewPager) reVal.findViewById(R.id.pagerMainContent); 
     mPageAdapter = new ScreenSlidePagerAdapter(getChildFragmentManager()); 
     mPager.setAdapter(mPageAdapter); 
     return reVal; 
    } 

    private MainGridViewFragment mainGridFragment; 
    private AlphabetGridViewFragment alphabetGridFragment; 

    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { 
     public ScreenSlidePagerAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public Fragment getItem(int position) { 
      switch (position) { 
       case 1: 
        mainGridFragment = new MainGridViewFragment(); 
        return (Fragment)mainGridFragment; 
       case 0: 
        alphabetGridFragment = new AlphabetGridViewFragment(); 
        return (Fragment)alphabetGridFragment; 
       default: 
        return null; 
      } 
     } 

     @Override 
     public int getCount() { 
      return 2; 
     } 
    } 
} 
+0

liên kết của bạn là hữu ích, nhưng nó giải thích một vấn đề khác – MoHaKa

+0

Có bình thường để sử dụng cả hai quản lý Fragment? Tôi đã ấn tượng rằng bạn sẽ nhận được hai đối tượng riêng biệt làm như vậy. Do đó, đoạn đầu tiên của bạn sẽ sử dụng bộ phận hỗ trợ và người quản lý không hỗ trợ thứ hai sẽ bị mất khi bạn tạo một hoạt động mới. – Jon

+0

Tôi đang sử dụng 'getFragmentManager()' vì trả về 'android.app.FragmentManager' và' getSupportFragmentManager() 'vì nó trả về' android.support.v4.app.FragmentManager' có nghĩa là không trả về cùng vật. Tôi sẽ sử dụng cái nào ?? – MoHaKa

0

Tránh tạo ViewPager một lần nữa. Đặt mã onCreateView trong onCreate(). Và làm cho đoạn của bạn sử dụng onRetainInstance (đúng). Do đó, điều này sẽ không tái tạo lại phân đoạn và một lần nữa vì khung nhìn nằm trong onCreate(), nó sẽ không được gọi lại.

Kiểm tra chế độ onCreateView() cho dù chế độ xem có tồn tại hay không, nếu có thì hãy xóa chế độ xem đó. Snippets:

//creates the view 
private View createView(Bundle savedInstanceState) { 
    View view = getActivity().getLayoutInflater().inflate(your_layout, null, false); 

    //viewpager 

    return view; 
} 

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

    //retains fragment instance across Activity re-creation 
    setRetainInstance(true); 

    viewRoot = createView(savedInstanceState); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 

    if (viewRoot != null && viewRoot.getParent() != null) { 
     ViewGroup parent = (ViewGroup) viewRoot.getParent(); 
     parent.removeView(viewRoot); 

     Log.i("Test", "**************view.getParent(): " + viewRoot.getParent() + " " + viewRoot); 
    } 

    return viewRoot; 
} 
+0

Tôi không biết liệu điều này có thể giúp ích hay không, nhưng hãy thử điều này. cho đến lúc đó tôi đang giải quyết vấn đề của bạn –

0

Bạn khá nên sử dụng một getChildFragmentManager() thay vì getFragmentManager(). Bạn sử dụng

mPageAdapter = new ScreenSlidePagerAdapter(getActivity().getFragmentManager()); 

nó cần phải có được

mPageAdapter = new ScreenSlidePagerAdapter(getActivity().getChildFragmentManager()); 

trong đoạn của bạn

+0

getActivity(). getChildFragmentManager() không tồn tại .. –

+1

Điều này thực sự đúng, ngoại trừ getAcitivity(). getChildFragmentManager() không tồn tại. Nó không nên bị bỏ phiếu. – chubbsondubs

0

tôi đã cùng một vấn đề chính xác này. Nó rất khó hiểu, nhưng chủ đề này đã giúp tôi, ngoại trừ câu trả lời không thực sự giải thích tại sao nó hoạt động.

Khắc phục sự cố này là sử dụng Fragment.getChildFragmentManager(). Điều gây nhầm lẫn là API android có Activity.getFragmentManager(), nhưng nếu bạn đang cố gắng hỗ trợ các thiết bị cũ hơn, bạn cần sử dụng Activity.getSupportFragmentManager(). Tuy nhiên, vấn đề cụ thể này không phải là về việc hỗ trợ các API cũ hơn.

Vấn đề là bạn có Hoạt động có Phân đoạn sở hữu ViewPager sở hữu một số Phân đoạn. Bạn có Fragments trong Fragments! Thiết kế ban đầu của Fragments đã không thực sự xử lý trường hợp sử dụng này và sau đó được cập nhật để xử lý nó. Khi bạn có Những mảnh vỡ trong Những mảnh vỡ bạn cần sử dụng:

Fragment.getChildFragmentManager()

Từ bên trong một Fragment bạn có thể lựa chọn Fragment.getFragmentManager() mà trả về FragmentManager của Activity vs Fragment.getChildFragmentManager() mà trả về FragmentManager cho Fragment này mà đúng phạm vi các Fragment s trong số Fragment của bạn.

2

Đối với những người đang gặp vấn đề với điều này bạn có thể thử này:

private void InitializeUI(){ 
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); 
mViewPager = (ViewPager) findViewById(R.id.container); 
mViewPager.setAdapter(mSectionsPagerAdapter); 

} 

@Override 
public void onConfigurationChanged(Configuration newConfig) { 
super.onConfigurationChanged(newConfig); 
setContentView(R.layout.activity_exame2); 
InitializeUI(); 
} 

tôi đã dành 2 ngày xung quanh vấn đề này đó là điều duy nhất mà làm việc cho tôi, hãy nhớ để thêm android: configChanges =" screenSize | orientation "đến hoạt động của bạn trong tệp kê khai

3

Tôi đã thử nhiều giải pháp nhưng có được thành công trong bất kỳ giải pháp nào. Cuối cùng tôi cố định như sau:

  • Sử dụng getActivity() getSupportFragmentManager() chứ không phải là getChildFragmentManager()

  • Override getItemId phương pháp (int position) trong lớp ViewPagerAdapter của bạn như dưới đây:.

    @Override 
    public long getItemId(int position) { 
        return System.currentTimeMillis(); 
    } 
    

Đối với tôi, nó hoạt động như sự quyến rũ, vui lòng cũng nhận xét ở đây chế độ xem của bạn.

+0

Ghi đè getItemId đã giúp tôi vô cùng. Tôi chưa bao giờ nghĩ ra điều đó. Tôi đoán ViewPager phải cache các mảnh dựa trên ID bằng cách nào đó. Dù bằng cách nào, cảm ơn bạn. –

Các vấn đề liên quan