방향 변경시 Fragment를 처리하는 확실한 방법


87
public class MainActivity extends Activity implements MainMenuFragment.OnMainMenuItemSelectedListener {

 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager
            .beginTransaction();

    // add menu fragment
    MainMenuFragment myFragment = new MainMenuFragment();
    fragmentTransaction.add(R.id.menu_fragment, myFragment);

    //add content
    DetailPart1 content1= new DetailPart1 ();
    fragmentTransaction.add(R.id.content_fragment, content1);
    fragmentTransaction.commit();

}
public void onMainMenuSelected(String tag) {
  //next menu is selected replace existing fragment
}

두 개의 목록보기를 나란히 표시해야합니다. 메뉴는 왼쪽에, 내용은 오른쪽에 있습니다. 기본적으로 첫 번째 메뉴가 선택되고 해당 내용이 오른쪽에 표시됩니다. 콘텐츠를 표시하는 Fragment는 다음과 같습니다.

public class DetailPart1 extends Fragment {
  ArrayList<HashMap<String, String>> myList = new ArrayList<HashMap<String, String>>();
  ListAdapter adap;
  ListView listview;

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

       if(savedInstanceState!=null){
        myList = (ArrayList)savedInstanceState.getSerializable("MYLIST_obj");
        adap = new LoadImageFromArrayListAdapter(getActivity(),myList );
        listview.setAdapter(adap);
       }else{
        //get list and load in list view
        getlistTask = new GetALLListTasks().execute();
    }


     @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.skyview_fragment, container,false);
           return v;
        }


     @Override
      public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
          outState.putSerializable("MYLIST_obj", myList );
        }
    }

onActivityCreated 및 onCreateView는 두 번 호출 됩니다 . 조각을 사용하는 많은 예제가 있습니다. 나는이 주제의 초보자이기 때문에 예제를 내 문제와 관련시킬 수 없습니다. 방향 변경을 처리하는 바보 증명 방법이 필요합니다. android:configChanges매니페스트 파일에 선언하지 않았습니다 . 가로 모드에서 다른 레이아웃을 사용할 수 있도록 활동을 파괴하고 다시 만들어야합니다.


일반적으로 조각 방향 변경은 아무것도 할 필요없이 처리됩니다. 그렇다면 방향을 바꿀 때 겪는 문제는 무엇입니까?
— Alexander Kulyakhtin 2012

Alex 세로 모드에서 listView로 레이아웃을 표시하고 가로 모드에서 Grid View로 레이아웃을 표시하려면 DetailPart1 클래스가 필요합니다.이를 위해 매번 조각을 다시 만들어야하지만 동일한 레코드를 다시로드하고 싶지 않습니다. 위의 코드는 두 번 DetailPart1을 재현 onSaveInstanceState 나누었다에 그들을 내가 원하는대로 작동하게 누락 된 코드를 알 필요가 저장
— user1811741

답변:


132

활동에서 화면을 돌릴 때마다 새 조각을 생성 onCreate();하지만 super.onCreate(savedInstanceState);. 따라서 태그를 설정하고 존재하는 경우 조각을 찾거나 null 번들을 super에 전달하십시오.

이것은 배우는 데 시간이 오래 걸렸고 뷰 페이저와 같은 작업을 할 때 정말 bi ****가 될 수 있습니다.

이 정확한 주제가 다루어 지므로 추가 시간 에 조각 에 대해 읽는 것이 좋습니다 .

다음은 일반적인 방향 변경시 조각을 처리하는 방법의 예입니다.

활동 :

public class MainActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            TestFragment test = new TestFragment();
            test.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().replace(android.R.id.content, test, "your_fragment_tag").commit();
        } else {
            TestFragment test = (TestFragment) getSupportFragmentManager().findFragmentByTag("your_fragment_tag");
        }
    }
}

조각 :

public class TestFragment extends Fragment {

    public static final String KEY_ITEM = "unique_key";
    public static final String KEY_INDEX = "index_key";
    private String mTime;

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

        if (savedInstanceState != null) {
            // Restore last state
            mTime = savedInstanceState.getString("time_key");
        } else {
            mTime = "" + Calendar.getInstance().getTimeInMillis();
        }

        TextView title = (TextView) view.findViewById(R.id.fragment_test);
        title.setText(mTime);

        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("time_key", mTime);
    }
}

노력에 대한 Warpzit에게 감사하지만, 당신이 당신의 요점에 대해 코드에서 설명해 주시면 기쁩니다. 조각을 다시로드하지 않고 방향 변경을 처리하도록 코드를 변경하는 방법.
— user1811741

1
따라서 방향에 따라 변경 될 조각의 레이아웃이 필요하지만 모든 레코드를 다시로드하고 싶지 않습니다. 1. 매니페스트에 android : configchanges = "orientation"을 추가합니다. 조각에서 onConfigurationChanged를 재정의하고 방향을 감지합니다. 방향에 따라 listview 또는 gridview를 숨기거나 표시합니다.
— user1811741

@ user1811741이 예제로 업데이트되었습니다. 나는 그것이 모든 것을 명확히하기를 바랍니다.
— Warpzit

@Warpzit ViewPager가 표시된 모든 fragment..any 제안을 처리하므로 ViewPager Fragment 구현의 경우 동일한 시나리오를 어떻게 처리 할 수 ​​있습니까?
— CoDe 2015

1
@Shubh 잘 나는 viewpager가 이것을 적절하게 처리한다고 믿습니다. 적절한 질문 : 넣어하지 않을 경우 희망, 올바른 방향을 지적하는
— Warpzit

21

방향 변경과 활동 레크리에이션 사이에 데이터를 유지하는 방법에 대한 좋은 지침은 안드로이드 지침에서 찾을 수 있습니다 .

요약:

  1. 조각을 유지 가능하게 만드십시오.

    setRetainInstance(true);
    
  2. 필요한 경우에만 새 조각을 만듭니다 (또는 최소한 여기에서 데이터 가져 오기).

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {
    

내 시간 Wah 절약
— Arjun saini
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.