MainActivity가 Fragment들을 Contain하시는건 이해하고 계시죠?
Fragment의 Transaction은 액티비티가 가지고있는 FragmentManager가 담당하구요.
//FragmentManager SupportFragmentManager 둘다 이하 FragmentManager라고 하겠습니다.
첫 Fragment1을 셋팅할때는
if(savedInstanceState==null){
getFragmentManager().beginTransaction().replace(R.id.content, new Fragment1()).commit();
}
이런식으로 셋팅하고 나서 Fragment1 내부에서 startActivity(Fragment.clas)호출처럼 Fragment2로의 전환작업이 이루어 지길 원하시는건가요?
제가 이해한게 맞다면 결론은 가능합니다.
옵저버패턴 이나 리플렉션을 이용하면 됩니다. 뭐... 혼합시켜서 프레임워크화 시켜도 되구요.
1. 옵저버패턴을 이용한 콜백 호출로 MainActivity에서 FragmentTransactoin을 호출하는 방법.
2. 리플렉션을 이용해서 startActivity처럼 Fragment.class를 기술해서 호출하는 방법.
3. 뭐 여러가지 응용 혼합...
2번이 뭔가 고객님께서 원하시는방법 같으니... 방법상 제일 쉽기도 하구요.
문제라면 중간 옵저버나 컨트롤매니저가 없어 다른 곳에서 컨트롤이 안된다는 점?
이쁘게 짠 소스는 아니지만 봐주시기 바랍니다...
1. 액티비티 레이아웃 파일입니다. 별거 없습니다. id를 content를 가진 프레임레이아웃 하나입니다.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.startfragmenttest.MainActivity" >
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
2. 모든 플래그먼트들이 상속하게될 최상위 부모 Fragment를 생성합니다. BaseFragment가 좋겠군요.
package com.example.startfragmenttest;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
public class BaseFragment extends Fragment {
protected void startFragment(FragmentManager fm, Class<? extends BaseFragment> fragmentClass) {
BaseFragment fragment = null;
try {
fragment = fragmentClass.newInstance();
} catch (java.lang.InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (fragment == null) {
throw new IllegalStateException("cannot start fragment. " + fragmentClass.getName());
}
getActivity().getSupportFragmentManager().beginTransaction().add(R.id.content, fragment).addToBackStack(null).commit();
}
protected void finishFragment() {
getFragmentManager().popBackStack();
}
public void onPressedBackkey() {
finishFragment();
}
}
3. 이제 BaseFragment를 상속한 DummyFragment를 만듭니다. 실제 구현되었을때 사용방법입니다.
자기 자신의 인스턴스된 횟수를 TextView에 표시하며, 다음 Fragment를 호출하는것과 자기자신을 종료하는 버튼을 가지고있습니다. 물론 addFragment에 add stack 해놓았으니 백키로도 스택 팝업이 됩니다.
onClickListener를 보면 startFragment와 finishFragment 항목이 보입니다. BaseFragment에서 구현한 것이지요.
package com.example.startfragmenttest;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class DummyFragment extends BaseFragment implements View.OnClickListener {
protected static volatile int instanceCount;
public DummyFragment() {
// TODO Auto-generated constructor stub
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
LinearLayout root = new LinearLayout(getActivity());
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(Color.GREEN);
TextView tv = new TextView(getActivity());
tv.setText("fragment " + instanceCount);
Button btnNew = new Button(getActivity());
Button btnFinish = new Button(getActivity());
btnNew.setId(0xA0A0);
btnFinish.setId(0xA0A1);
btnNew.setText("add fragment");
btnFinish.setText("finish");
btnNew.setOnClickListener(this);
btnFinish.setOnClickListener(this);
root.addView(tv);
root.addView(btnNew);
root.addView(btnFinish);
return root;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case 0xA0A0:
Log.i(getClass().getSimpleName(), "start");
startFragment(getFragmentManager(), DummyFragment.class);
break;
case 0xA0A1:
Log.i(getClass().getSimpleName(), "finish");
finishFragment();
break;
default:
break;
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
instanceCount++;
}
@Override
public void onDetach() {
super.onDetach();
instanceCount--;
}
}
4. 이제 액티비티에 셋팅합니다.
package com.example.startfragmenttest;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.content, new DummyFragment()).commit();
}
}
}
참 쉽죠?