Adding and Removing Fragments with Device Orientation
fragments를 사용할 때 가장 큰 잇점 중의 하나는 디바이스를 가로 세로 방향으로 돌려서 볼 때 쉽게 fragment를 넣고 뺄 수 있어서 적당한 layout의 view를 사용자에게 보여질 수 있도록 하는 것입니다. 그럼 이렇게 만들기 위해 이전 글에서 다뤘던 소스들을 약간 수정해 보겠습니다. (안드로이드 전화기에서 세웠을 때는 한개의 fragment만 보여지도록요.)
activity_foreground_fragment.xml 에서 두번째 fragment 부분을 주석 처리 합니다.
<LinearLayout 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"
android:orientation="horizontal" >
<fragment
android:name="com.androidtablet.foregroundfragmentapp.Fragment1Activity"
android:id="@+id/fragment1"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<!-- <fragment
android:name="com.androidtablet.foregroundfragmentapp.Fragment2Activity"
android:id="@+id/fragment2"
android:layout_weight="0"
android:layout_width="wrap_content"
android:layout_height="match_parent" /> -->
</LinearLayout>
이렇게 하는 이유는 오직 1개의 fragment만 화면에 표시하기 위해서죠. 이 경우는 안드로이드 전화기가 세워졌을 때 뿐입니다. 눕혀졌을 때나 태블릿 일 경우에는 두개의 fragments들이 좌우로 배치되어야 하겠죠.
그러면 이런 경우를 위해서 어떤 작업을 해야 합니다. 우선 res 폴더 아래에 layout-land 폴더를 생성하세요. 그리고 그 폴더에 activity_foreground_fragment.app 을 복사해 넣으세요.
전화기가 세워졌다가 옆으로 뉘여졌을 때 이 activity는 layout-land 에 있는 layout xml 파일을 사용해서 화면에 표시해 줄 겁니다. 전화기가 다시 세워지면 layout 폴더 안에 있는 xml 을 사용해서 화면을 갱신시킬거구요.
layout_land 폴더에 있는 activity_foreground_fragment.xml 파일에서는 위에 있는 주석을 풀어 주시면 됩니다.
그 다음에는 Fragment1Activity.java 파일을 수정하시면 됩니다.
public class Fragment1Activity extends Fragment {
OnOptionSelectedListener myListener;
boolean large, xlarge;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Context c = getActivity().getApplicationContext();
View vw = inflater.inflate(R.layout.fragment1, container, false);
String[] products={"Camera", "Laptop", "Watch", "Smartphone", "Television"};
large = ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
xlarge =((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);
ListView productsList = (ListView) vw.findViewById(R.id.products_list);
ArrayAdapter<String> arrayAdpt= new ArrayAdapter<String> (c, R.layout.list_item, products);
productsList.setAdapter(arrayAdpt);
productsList.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id){
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE || large || xlarge){
myListener.onOptionSelected(((TextView) v).getText().toString());
} else {
Intent intent = new Intent(getActivity().getApplicationContext(), DisplayItemActivity.class);
intent.putExtra("item", ((TextView) v).getText().toString());
startActivity(intent);
}
}
});
return vw;
}
public interface OnOptionSelectedListener {
public void onOptionSelected(String message);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
myListener = (OnOptionSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnItemClickListener");
}
}
}
위의 굵은 글씨체가 추가된 부분입니다. 리스트뷰의 아이템이 클릭 됐을 때 onItemClick() 메소드를 보면 우선 device가 landscape 이거나 large 혹은 xlarge 즉 태블릿인 경우를 체크합니다. 만약에 그렇다면 fragment2를 보여줍니다. 즉 그럴 경우 onOptionSelected() 메소드가 호출되고 이때 선택된 아이템의 이름이 파라미터로 전달 되는 겁니다. 그러면 Fragment2에서 이 파라미터를 받아서 화면에 출력하겠죠.
위 경우가 아니라면 즉 디바이스가 전화기이고 세워진 상태라면 (Portrait orientation) fragment2는 호출 되지 않을 겁니다. 리스트뷰에 있는 아이템이 선택 됐으면 그 이름이 다른 화면에 표시 되어야 합니다. 다른 화면에 표시된다는 얘기는 다른 activity가 필요하다는 얘기입니다. 그리고 다른 activity로 옮길 경우에는 Intent를 사용해야 되구요. 이 경우 현재의 Context를 같이 보내 주어야 합니다. getActivity().getApplicationContext(). 그리고 불려질 Activity를 정해주고 (DisplayItemActivity.class) 그리고 추가적으로 데이터를 넣어서 이것을 전달합니다. 마지막으로 startActivity() 를 하면 다음 화면이 불려 오겠죠.
그러면 이제 할 일을 DisplayItemActivity.java 를 만들어야 겠네요.
소스 코드는 아래와 같습니다.
public class DisplayItemActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
setContentView(R.layout.fragment2);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String selectedItem = extras.getString("item");
TextView selectedOpt = (TextView) findViewById(R.id.selectedopt);
selectedOpt.setText("You have selected "+selectedItem);
}
}
}
onCreate() 만 있죠? 맨 처음에 이 기계가 Landscape 모드이면 그냥 끝내고 return 을 해 버립니다. 그리고 난 후 fragment2.xml 을 view로 세팅하죠.
그리고 나서 이전 파일에서 전달해 준 데이터를 체크합니다. getExtra()가 그 일을 합니다. 그리고 item이란 key 값을 이용해서 그 value 값을 selectedItem에 담구요. 그 값을 텍스트뷰에 넣어 줍니다.
이렇게 하면 완성된 겁니다.
그런데 한가지 더 해야 될 게 있는데요.
DisplayItemActivity 라는 Activity가 새로 생겼으면 이것을 AndroidManifest.xml 에 신고를 해야 합니다.
<activity android:name=".DisplayItemActivity" android:label="@string/app_name" /> 을 추가해야 하는데요.
혹시 Manifest 파일에 액티비티 추가하는 방법을 모르시면 관련 글을 보시고 참고하시기 바랍니다.
그리고 한가지 더 해야 할 일이 있는데요.
현재 layout과 layout-land 폴더에만 xml layout 파일이 있습니다. 이건 전화기에만 해당되는데요. 태블릿에도 적용시키기 위해서 두개의 폴더를 더 만듭니다. layout-sw600dp 와 layout-sw720dp 폴더를요. 그리고 이 앱에서는 전화기의 landscape 인 경우와 7인치 10인치 태블릿의 landscape, portrait orientation 모두 그 구성이 같습니다. 그러니까 lauout-land 에 있는 activity_foreground_fragment_app.xml 파일을 복사해서 위 두 폴더 밑에 넣습니다.
이제 이 앱을 돌리면 안드로이드 전화기인 경우에는 Portrait orientation인 경우 첫화면에는 리스트뷰만 표시되고 그 리스트 뷰의 아이템을 클릭했을 때 그 이름이 두번째 화면에서 표시되게 됩니다. landscape orientation으로 바뀌게 되면 태블릿과 마찬가지로 두개의 fragment들이 좌우로 배치되고 좌측의 리스트뷰 아이템을 클릭하면 그 이름이 우측의 텍스트 뷰에 출력되게 됩니다.
'WEB_APP > Android' 카테고리의 다른 글
[CookBook] Fragments 이해하기 -8- (0) | 2013.09.30 |
---|---|
[CookBook] Fragments 이해하기 -7- (0) | 2013.09.30 |
[CookBook] Fragments 이해하기 -6- (0) | 2013.09.29 |
[CookBook] Fragments 이해하기 -5- (0) | 2013.09.28 |
[CookBook] Fragments 이해하기 -4- (1) | 2013.09.27 |
[CookBook] Fragments 이해하기 -2- (0) | 2013.09.26 |
[CookBook] Fragments 이해하기 -1- (0) | 2013.09.25 |
[Cookbook] 안드로이드 Cores 와 Threads 이해하기 -5- (0) | 2013.09.25 |
[Cookbook] 안드로이드 Cores 와 Threads 이해하기 -4- (0) | 2013.09.24 |
[Cookbook] 안드로이드 Cores 와 Threads 이해하기 -3- (0) | 2013.09.24 |