Skip to content

Latest commit

ย 

History

History
383 lines (280 loc) ยท 17.1 KB

FlexibleUI.md

File metadata and controls

383 lines (280 loc) ยท 17.1 KB

flexible UI

๋ฐœํ‘œ์ž : ์†ก์‹œ์€

๋ฐœํ‘œ์ฃผ์ œ : ๋ ˆ์ด์•„์›ƒ ๋ถ„๊ธฐ

๋ฐœํ‘œ์ผ์ž : 2018-09-07

[TOC]

0. ์ฐธ๊ณ ๋ฌธ์„œ

1. ๋ฆฌ์†Œ์Šค ๋ถ„๊ธฐ

์•ˆ๋“œ๋กœ์ด๋“œ ํ”„๋กœ์ ํŠธ์—์„œ ์•„์ด์ฝ˜์ด ์žˆ๋Š” mipmap ๋””๋ ‰ํ„ฐ๋ฆฌ๋Š” ๊ธฐ๊ธฐ์˜ ๋ฐ€๋„(density)์— ๋”ฐ๋ผ ๋ถ„๊ธฐํ•˜๋„๋ก ๋˜์–ด์žˆ๋‹ค. ์•ฑ์ด ์‹คํ–‰๋  ๋•Œ ๊ธฐ๊ธฐ์˜ ๋ฐ€๋„์— ๋”ฐ๋ผ ํ•ด๋‹น ํด๋”์˜ ์•„์ด์ฝ˜์ด ์„ ํƒ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

๋ ˆ์ด์•„์›ƒ๋„ ์ด๋Ÿฐ์‹์œผ๋กœ ๋ถ„๊ธฐํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

2. ๋ ˆ์ด์•„์›ƒ ๋ถ„๊ธฐ

2.1. ์‹ค์Šต

  1. ๋ ˆ์ด์•„์›ƒ ๋ถ„๊ธฐ๋ฅผ ์œ„ํ•ด res ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ์„ ๋ˆ„๋ฅด๊ณ  [New -> Android resource directory]๋ฅผ ํด๋ฆญํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค
  2. New Resource Directory ์ฐฝ์—์„œ Resource type:์€ 'layout'์„ ์„ ํƒํ•˜๊ณ , ์™ผ์ชฝ ํ•˜๋‹จ์— Available qualifiers ์ƒ์ž์—์„œ 'Orientation'์„ ์„ ํƒํ•œ ๋‹ค์Œ, ๊ฐ€์šด๋ฐ์— ์žˆ๋Š” >> ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ๋‹ค.
  3. Screen orientation: ํ•ญ๋ชฉ์—์„œ 'Landscape'๋ฅผ ์„ ํƒํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด Directory name:์ด layout-land๋กœ ์„ค์ •๋˜๋ฉฐ, ์ด ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์žˆ๋Š” ๋ ˆ์ด์•„์›ƒ XML์€ ๊ฐ€๋กœ ๋ชจ๋“œ์— ์šฐ์„ ์œผ๋กœ ์ ์šฉ๋˜๋Š” ๋ ˆ์ด์•„์›ƒ์ด ๋œ๋‹ค.
  4. layout/activity_main.xml ํŒŒ์ผ์„ layout-land ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋ณต์‚ฌํ•ด์„œ ๋ถ™์—ฌ๋„ฃ๋Š”๋‹ค.
  5. ๊ฐ€๋กœ ๋ชจ๋“œ์™€ ์„ธ๋กœ ๋ชจ๋“œ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์„ค์ •ํ•œ๋‹ค.

๋ ˆ์ด์•„์›ƒ ๋ถ„๊ธฐ๋ฅผ ํ”„๋ž˜๊ทธ ๋จผํŠธ์™€ ์กฐํ•ฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ํ™”๋ฉด ๊ตฌ์„ฑ์„ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ์œ ์—ฐํ•œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์ถ•

ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ํ™”๋ฉด ํฌ๊ธฐ๋ฅผ ์ง€์›ํ•˜๋Š” ์•ฑ์„ ๋งŒ๋“ค ๋•Œ, ํ™”๋ฉด ํฌ๊ธฐ๋‚˜ ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ์žฌํ™œ์šฉํ•˜์—ฌ ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ํƒœํ”Œ๋ฆฟ๊ณผ ํ•ธ๋“œํฐ์„ ๋™์‹œ์— ์ง€์›ํ•˜๋Š” ์•ฑ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.

์˜ˆ์‹œ)

FragmentManager ํด๋ž˜์Šค ๋Ÿฐํƒ€์ž„์— ๋™์ ์œผ๋กœ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ์ถ”๊ฐ€๋‚˜ ์‚ญ์ œ, ๋˜๋Š” ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณต

3.1. ์‹ค์Šต

์ž‘์„ฑํ•  ์˜ˆ์ œ์˜ ๋™์ž‘์„ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์‹œ์ž‘ํ•˜๋ฉด HeadlinesFragment๋ฅผ ๋™์  ์ถ”๊ฐ€ํ•œ๋‹ค.
  2. HeadlinesFragment์—์„œ ์•„์ดํ…œ์ด ์„ ํƒ๋˜๋ฉด onHeadlineSelected ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋œ๋‹ค.
  3. ์•กํ‹ฐ๋น„ํ‹ฐ์—์„œ ArticleFragment๋กœ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๊ต์ฒดํ•œ๋‹ค.
  4. ํ”„๋ž˜๊ทธ๋จผํŠธ๊ฐ€ ๊ต์ฒด๋˜๊ธฐ ์ „์— ๋ฐฑ์Šคํƒ์— ์ €์žฅํ•จ์œผ๋กœ์จ ๋’ค๋กœ ๊ฐ€๊ธฐ๋กœ HeadlinesFragment๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

์ œ๋ชฉ์„ ๋ˆ„๋ฅด๋ฉด ๋‚ด์šฉ์„ ํ‘œ์‹œํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์•ฑ์˜ ์ƒ˜ํ”Œ์„ ์ž‘์„ฑํ•  ๊ฒƒ์ด๋‹ค.

ํ”„๋ž˜๊ทธ๋จผํŠธ A์— ์ œ๋ชฉ ๋ฆฌ์ŠคํŠธ๊ฐ€ ํ‘œ์‹œ๋˜๊ฒŒ ํ•˜๊ณ , ์ œ๋ชฉ์„ ํด๋ฆญํ•˜๋ฉด ํ”„๋ž˜๊ทธ๋จผํŠธ B์— ๋‚ด์šฉ์ด ๋ณด์ด๊ฒŒ ํ•  ๊ฒƒ์ด๋‹ค.

์ด๋ฅผ ์œ„ํ•ด Article ํด๋ž˜์Šค๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

public class Articles {
    // ์ œ๋ชฉ
    static String[] Headlines = {
            "์ œ๋ชฉ 1", "์ œ๋ชฉ 2"
    };
    // ๋‚ด์šฉ
    static String[] Articles = {
            "์ด๊ฒƒ์€ ์ œ๋ชฉ1์˜ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.",
            "์ด๊ฒƒ์€ ์ œ๋ชฉ2์˜ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค."
    };
}

3.1.1. ํ™”๋ฉด์ด ์ž‘์€ ๊ธฐ๊ธฐ์—์„œ์˜ ๋™์ž‘

ํ™”๋ฉด์ด ์ž‘์€ ๊ธฐ๊ธฐ์™€ ํฐ ๊ธฐ๊ธฐ(7์ธ์น˜ ์ด์ƒ ํƒœ๋ธ”๋ฆฟ)์—์„œ ๋ ˆ์ด์•„์›ƒ๊ณผ ์•ฑ์˜ ๋™์ž‘์ด ๋‹ค๋ฅด๊ฒŒ ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

ํ•ธ๋“œํฐ์ฒ˜๋Ÿผ ํ™”๋ฉด ํฌ๊ธฐ๊ฐ€ 7์ธ์น˜ ๋ฏธ๋งŒ์ธ ๊ธฐ๊ธฐ์—์„œ๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ A์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ํด๋ฆญํ•˜๋ฉด ํ”„๋ž˜๊ทธ๋จผํŠธ B์˜ ๋‚ด์šฉ์ด ํ‘œ์‹œ๋˜๊ฒŒ ํ•˜๊ณ , ํƒœ๋ธ”๋ฆฟ์ฒ˜๋Ÿผ ํฐ ๊ธฐ๊ธฐ์—์„œ๋Š” ํ•œ ํ™”๋ฉด์— ํ”„๋ž˜๊ทธ๋จผํŠธ A์™€ B๊ฐ€ ๊ฒฐํ•ฉ๋˜์–ด ๋ฆฌ์ŠคํŠธ์™€ ๋‚ด์šฉ์ด ๋ชจ๋‘ ํ‘œ์‹œ๋˜๊ฒŒ ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

  1. ํ”„๋ž˜๊ทธ๋จผํŠธ A์— ํ•ด๋‹นํ•˜๋Š” HeadlinesFragment๋ฅผ ์ž‘์„ฑํ•œ๋‹ค - ์ œ๋ชฉ์„ ํ‘œ์‹œํ•˜๋Š” ๋ฆฌ์ŠคํŠธ๋ฅผ ํ‘œ์‹œ

    /**
     * ์ œ๋ชฉ์„ ํ‘œ์‹œํ•  ๋ฆฌ์ŠคํŠธ ํ”„๋ž˜๊ทธ๋จผํŠธ
     */
    public class HeadlinesFragment extends ListFragment {
        // ์ด ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ํฌํ•จํ•˜๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ๋Š” ๋ฐ˜๋“œ์‹œ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ
        interface OnHeadlineSelectedListener {
            // ์ œ๋ชฉ์ด ์„ ํƒ๋˜์—ˆ์„ ๋•Œ ํ˜ธ์ถœ๋จ
            void onHeadlineSelected(int position);
        }
        private OnHeadlineSelectedListener mListener;
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            // Articles ์˜ Headlines ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ ๋ทฐ๋ฅผ ์œ„ํ•œ ArrayAdapter ๋ฅผ ์ƒ์„ฑ
            setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, Articles.Headlines));
        }
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            // ์ด ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ํฌํ•จํ•˜๋Š” Context ๋Š” ๋ฐ˜๋“œ์‹œ OnHeadlineSelectedListener ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.
            // ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ClassCastException ์ด ๋ฐœ์ƒํ•˜๊ณ  ์•ฑ์„ ์ข…๋ฃŒํ•œ๋‹ค.
            try {
                mListener = (OnHeadlineSelectedListener) context;
            }catch (ClassCastException e){
                throw new ClassCastException(context.toString() + " must implement OnHeadlineSelectedListener");
            }
        }
        @Override
        public void onListItemClick(ListView l, View v, int position, long id){
            super.onListItemClick(l, v, position, id);
            // ์„ ํƒ๋œ ์œ„์น˜๋ฅผ ์•กํ‹ฐ๋น„ํ‹ฐ์— ์•Œ๋ ค ์คŒ
            if (mListener != null) {
                mListener.onHeadlineSelected(position);
            }
        }
    }

    ์ด ํ”„๋ž˜๊ทธ๋จผํŠธ๋Š” ListFragment๋ฅผ ์ƒ์†ํ•˜๋ฉฐ ์ œ๋ชฉ์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์ œ๋ชฉ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ์ด ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ์— ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•˜๋„๋ก ๋˜์–ด์žˆ๋‹ค. ์ด ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ํฌํ•จํ•  ์•กํ‹ฐ๋น„ํ‹ฐ๋Š” ๋ฐ˜๋“œ์‹œ OnHeadlineSelectedListener ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก onAttach() ๋ฉ”์„œ๋“œ์—์„œ ๊ฐ•์ œ๋กœ ์•กํ‹ฐ๋น„ํ‹ฐ์™€ ์—ฐ๊ฒฐํ•˜๊ณ  ์žˆ๋‹ค.

  2. ํ”„๋ž˜๊ทธ๋จผํŠธ์˜ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์„ ์ค€๋น„ fragment_article

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <TextView
        android:id="@+id/article_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    </LinearLayout>
  3. ํ”„๋ž˜๊ทธ๋จผํŠธ B์— ํ•ด๋‹นํ•˜๋Š” ArticleFragment ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค - ๋‚ด์šฉ์„ ํ…์ŠคํŠธ๋ทฐ์— ํ‘œ์‹œ

    /**
     * HeadlinesFragment ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ์ œ๋ชฉ๋ฅผ ํ‘œ์‹œํ•  ํ”„๋ž˜๊ทธ๋จผํŠธ
     */
    
    public class ArticleFragment extends Fragment {
        public static final String ARG_POSITION = "position";
        private int mCurrentPosition = -1;
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            // ํ™”๋ฉด์ด ํšŒ์ „๋˜๋ฉด ์ด์ „์— ์„ ํƒ๋œ ์œ„์น˜๋ฅผ ๋ณต์›
            if (savedInstanceState != null) {
                mCurrentPosition = savedInstanceState.getInt(ARG_POSITION);
            }
            // ํ™”๋ฉด ๋ ˆ์ด์•„์›ƒ์€ TextView ํ•˜๋‚˜๋งŒ ์žˆ๋Š” ๋ ˆ์ด์•„์›ƒ์„ ์‚ฌ์šฉ
            return inflater.inflate(R.layout.fragment_articles, container, false);
        }
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Bundle args = getArguments();
            if (args != null) {
                // ํ”„๋ž˜๊ทธ๋จผํŠธ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์„ ๊ฒฝ์šฐ
                updateArticleView(args.getInt(ARG_POSITION));
            } else if (mCurrentPosition != -1) {
                // ํ™”๋ฉด ํšŒ์ „ ๋“ฑ์˜ ๊ฒฝ์šฐ
                updateArticleView(mCurrentPosition);
            }
        }
    
        // ์„ ํƒ๋œ ์ œ๋ชฉ์˜ ๋‚ด์šฉ์„ ํ‘œ์‹œ
        public void updateArticleView(int position) {
            TextView article = (TextView) getView().findViewById(R.id.article_text);
            article.setText(Articles.Articles[position]);
            mCurrentPosition = position;
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            // ํ™”๋ฉด์ด ํšŒ์ „๋  ๋•Œ, ์„ ํƒ๋œ ์œ„์น˜๋ฅผ ์ €์žฅ
            outState.putInt(ARG_POSITION, mCurrentPosition);
        }
    }

    ์ด ํ”„๋ž˜๊ทธ๋จผํŠธ๋Š” ๋ช‡ ๋ฒˆ์งธ ์ œ๋ชฉ์ด ์„ ํƒ๋˜์—ˆ๋Š”์ง€์— ๋”ฐ๋ผ์„œ ํ•ด๋‹น ์ œ๋ชฉ์˜ ๋‚ด์šฉ์„ Articles.Articles ๋ฐฐ์—ด์—์„œ ๊ฐ€์ ธ์™€์„œ ํ…์ŠคํŠธ๋ทฐ์— ํ‘œ์‹œํ•œ๋‹ค.

    ํ”„๋ž˜๊ทธ๋จผํŠธ๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ ์ƒ๋ช…์ฃผ๊ธฐ์™€ ์—ฐ๊ด€๋œ ๋ณต์žกํ•œ ์‚ฌ์ •์œผ๋กœ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ์ด ๊ธˆ์ง€๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง€๋Š” ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค๋ฉด ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค๊ฐ€ ๋นจ๊ฐ„ ์ค„๋กœ ํ‘œ์‹œํ•  ๊ฒƒ์ด๋‹ค. ๋Œ€์‹  Bundle ๊ฐ์ฒด๋ฅผ Argument๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ์ฒ˜์Œ ์ƒ์„ฑํ–ˆ์„ ๋•Œ๋Š” Argument๋กœ ์ œ๋ชฉ ๋ฒˆํ˜ธ๋ฅผ ์ „๋‹ฌ๋ฐ›์•„์„œ ์ œ๋ชฉ์„ ํ‘œ์‹œํ•˜๊ณ , ํ™”๋ฉด์ด ํšŒ์ „ํ•˜๋ฉด ๋งˆ์ง€๋ง‰์— ์„ ํƒ๋œ ๊ธฐ์‚ฌ ๋ฒˆํ˜ธ๋ฅผ onSavedInstanceState() ๋ฉ”์„œ๋“œ์—์„œ ์ €์žฅํ•˜๊ณ  onCreateView() ๋ฉ”์„œ๋“œ์—์„œ ๋ณต์›ํ•œ๋‹ค.

  4. ๋‘ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ํฌํ•จํ•  ์•กํ‹ฐ๋น„ํ‹ฐ์ธ MainActivity์ธ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.

    <?xml version="1.0" encoding="utf-8"?>
    <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=".MainActivity">
    
    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    </RelativeLayout>

    ๋ ˆ์ด์•„์›ƒ์˜ ๋‚ด๋ถ€์—๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ํ‘œ์‹œํ•  ์˜์—ญ์ธ FrameLayout์„ ๋ฐฐ์น˜ํ•˜์˜€๊ณ  id๋ฅผ ๋ถ€์—ฌํ–ˆ๋‹ค.

    ์ด ์˜์—ญ์— ์ตœ์ดˆ์—๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ A๋ฅผ ํ‘œ์‹œํ•˜๊ณ , ์ œ๋ชฉ์„ ์„ ํƒํ•˜๋ฉด ํ”„๋ž˜๊ทธ๋จผํŠธ B๋กœ ๊ต์ฒดํ•  ๊ฒƒ์ด๋‹ค.

  5. MainActivity ์ž‘์„ฑ

    public class MainActivity extends AppCompatActivity implements HeadlinesFragment.OnHeadlineSelectedListener {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // ํ™”๋ฉด ํšŒ์ „ ์‹œ HeadlinesFragment ๊ฐ€ ์žฌ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ ๋ฐฉ์ง€
            if (savedInstanceState == null) {
                HeadlinesFragment headlinesFragment = new HeadlinesFragment();
                // headlinesFragment ๋ฅผ R.id.fragment_container ์˜์—ญ์— ์ถ”๊ฐ€
                getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, headlinesFragment)
                    .commit();
            }
        }
    
        // HeadlinesFragment ์˜ ์ œ๋ชฉ์ด ์„ ํƒ๋˜์—ˆ์„ ๋•Œ ํ˜ธ์ถœ
        @Override
        public void onHeadlineSelected(int position) {
            // ArticleFragment ํ”„๋ž˜๊ทธ๋จผํŠธ ์ƒ์„ฑ
            ArticleFragment newArticleFragment = new ArticleFragment();
            // Argument ๋กœ ์ œ๋ชฉ ๋ฒˆํ˜ธ ์ „๋‹ฌ
            Bundle args = new Bundle();
            args.putInt(ArticleFragment.ARG_POSITION, position);
            newArticleFragment.setArguments(args);
            // R.id.fragment_container ์•„์ด๋””๋ฅผ ๊ฐ€์ง„ ์˜์—ญ์˜ 
            //ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ articleFragment ๋กœ ๊ต์ฒดํ•˜๊ณ 
            // ํ”„๋ž˜๊ทธ๋จผํŠธ ๋งค๋‹ˆ์ €์˜ BackStack ์— ์Œ“๋Š”๋‹ค
            getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, newArticleFragment)
                .addToBackStack(null)
                .commit();
        }
    }

    MainActivity๋ฅผ ์‹คํ–‰ ์‹œ HeadlinesFragment๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์ œ๋ชฉ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ onHeadlineSelected() ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋˜๋ฉฐ, ArticleFragment๋กœ ๊ต์ฒด๋œ๋‹ค.

    ์ฃผ์˜ํ•ด์„œ ๋ณผ ๋ถ€๋ถ„์€ onCreate() ๋ฉ”์„œ๋“œ์—์„œ savedInstanceState == null ์ผ ๋•Œ๋งŒ HeadlinesFragment๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ๋‹ค. ์ด ์กฐ๊ฑด์ด ์—†๋‹ค๋ฉด ํ™”๋ฉด์ด ํšŒ์ „๋  ๋•Œ๋งˆ๋‹ค ๊ธฐ์กด HeadlinesFragment๊ฐ€ ์œ ์ง€๋˜๋ฉฐ ์ƒˆ๋กœ์šด HeadlinsFragment๊ฐ€ ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋“œ์‹œ savedInstanceState๊ฐ€ null์ธ์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ๋กœ์ง์„ ์žŠ์œผ๋ฉด ์•ˆ๋œ๋‹ค. ์ด์œ ๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ๋ฅผ ํšŒ์ „ํ•˜์—ฌ ๊ฐ•์ œ๋กœ ์žฌ์ƒ์„ฑํ•ด๋„ ํ”„๋ž˜๊ทธ๋จผํŠธ๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ ๋งค๋‹ˆ์ €๊ฐ€ ๋ณ„๋„๋กœ ๊ด€๋ฆฌํ•˜๋ฉฐ ์žฌ์ƒ์„ฑ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    onHeadlineSelected() ์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ์—์„œ ๊ธฐ์‚ฌ์˜ ๋‚ด์šฉ์„ ํ‘œ์‹œํ•˜๋Š” ArticleFragment๋กœ ๊ต์ฒดํ•  ๋•Œ addToBackStack(null) ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ํ”„๋ž˜๊ทธ๋จผํŠธ์˜ ๋ฐฑ์Šคํƒ์— ์ถ”๊ฐ€ํ•œ๋‹ค. ๋ฐฑ์Šคํƒ(BackStack)์ด๋ž€, ํ”„๋ž˜๊ทธ๋จผํŠธ ๋งค๋‹ˆ์ €๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์Šคํƒ์ด๋‹ค.

3.1.2. ํ™”๋ฉด์ด ํฐ ๊ธฐ๊ธฐ๋ฅผ ์œ„ํ•œ ๊ตฌํ˜„ ์ถ”๊ฐ€

์•ˆ๋“œ๋กœ์ด๋“œ์˜ ๋ ˆ์ด์•„์›ƒ์€ ํ™”๋ฉด ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋ถ„๊ธฐํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ธฐ๋ณธ ๋ ˆ์ด์•„์›ƒ์˜ ๊ฒฝ๋กœ๋Š” layout/activity_main.xml์ด์ง€๋งŒ, layout-large.activity_main.xml์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” layout ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ XML ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜๊ณ , ํ™”๋ฉด์ด 7์ธ์น˜ ์ด์ƒ์œผ๋กœ ํฐ ๊ธฐ๊ธฐ์—์„œ๋Š” layout_large ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ XML ํŒŒ์ผ์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. 7์ธ์น˜ ์ด์ƒ์˜ ๋ ˆ์ด์•„์›ƒ์„ ์œ„ํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

  2. layout-large ์— activity_main.xml์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

    <?xml version="1.0" encoding="utf-8"?>
    <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">
    
        <fragment
            android:id="@+id/headlines_fragment"
            android:name="com.example.user.dynamicuiexam.HeadlinesFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            tools:layout="@android:layout/simple_list_item_1" />
    
        <fragment
            android:id="@+id/article_fragment"
            android:name="com.example.user.dynamicuiexam.ArticleFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            tools:layout="@layout/fragment_articles" />
    </LinearLayout>
  3. MainActivity ์ฝ”๋“œ ์ˆ˜์ •

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // layout-large ์˜ ๋ ˆ์ด์•„์›ƒ์—๋Š” fragment_container ๊ฐ€ ์—†์Œ
            if (findViewById(R.id.fragment_container) != null) {
                // ํ™”๋ฉด ํšŒ์ „ ์‹œ HeadlinesFragment ๊ฐ€ ์žฌ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ ๋ฐฉ์ง€
                if (savedInstanceState == null) {
                    HeadlinesFragment headlinesFragment = new HeadlinesFragment();
                    // headlinesFragment ๋ฅผ R.id.fragment_container ์˜์—ญ์— ์ถ”๊ฐ€
                    getSupportFragmentManager().beginTransaction()
                            .add(R.id.fragment_container, headlinesFragment)
                            .commit();
                }
            }
        }

    onCreate() ์—์„œ layout-large์ธ์ง€ ์•„๋‹Œ์ง€์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌ

    layout-large์˜ ๋ ˆ์ด์•„์›ƒ์€ ๋ฏธ๋ฆฌ ๋‘ ๊ฐœ์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ๊ฐ€ ์œ„์น˜ ํ•ด ์žˆ์œผ๋ฏ€๋กœ ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    @Override
        public void onHeadlineSelected(int position) {
            ArticleFragment articleFragment = (ArticleFragment) getSupportFragmentManager().findFragmentById(R.id.article_fragment);
            // layout-large ์˜ ๊ฒฝ์šฐ null ์ด ์•„๋‹˜
            if (articleFragment == null) {
                // ArticleFragment ํ”„๋ž˜๊ทธ๋จผํŠธ ์ƒ์„ฑ
                ArticleFragment newArticleFragment = new ArticleFragment();
                // Argument ๋กœ ๊ธฐ์‚ฌ ๋ฒˆํ˜ธ ์ „๋‹ฌ
                Bundle args = new Bundle();
                args.putInt(ArticleFragment.ARG_POSITION, position);
                newArticleFragment.setArguments(args);
                // R.id.fragment_container ์•„์ด๋””๋ฅผ ๊ฐ€์ง„ ์˜์—ญ์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ articleFragment ๋กœ ๊ต์ฒดํ•˜๊ณ 
                // ํ”„๋ž˜๊ทธ๋จผํŠธ ๋งค๋‹ˆ์ €์˜ BackStack ์— ์Œ“๋Š”๋‹ค
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.fragment_container, newArticleFragment)
                        .addToBackStack(null)
                        .commit();
            } else {
                articleFragment.updateArticleView(position);
            }
        }
    }

    ๊ธฐ์กด์˜ articleFragment๋ผ๋Š” ๋ณ€์ˆ˜๋ช…์„ newArticleFragment๋กœ ์ˆ˜์ •ํ•˜์˜€๊ณ , layout-large์˜ ๊ฒฝ์šฐ์—๋Š” article_fragment ์•„์ด๋””๋กœ ์ด๋ฏธ ArticleFragment๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ์ด๊ฒƒ์ด null์ธ์ง€ ์•„๋‹Œ์ง€์— ๋”ฐ๋ผ์„œ ์•„๋ฅธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ๋‹ค. ๋งŒ์•ฝ layout-large์™€ ๊ฐ™์ด ArticleFragment๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค๋ฉด ๊ทธ ํ”„๋ž˜๊ทธ๋จผํŠธ์˜ ๊ธฐ์‚ฌ๋งŒ updateArticleView()๋ฅผ ํ†ตํ•ด ๊ฐฑ์‹ ํ•˜๋ฉด ๋œ๋‹ค.