다중 창 레이아웃을 간단하게 실현하는 방법

18303 단어 Android

개시하다


다중 창 레이아웃에 대한 설명은 생략합니다.
http://developer.android.com/design/patterns/multi-pane-layouts.html
다중 창 레이아웃에서 왼쪽 창을 Master/Detail 모드라고 합니다.
이 마스터/Detail 모드의 다중 창 설치는 SlidingPaneLayout 를 사용합니다.

SlidingPaneLayout

SlidingPaneLayout는 r18부터 SupportLibrary에 포함된 비교적 새로운 ViewGroup입니다.
https://developer.android.com/reference/android/support/v4/widget/SlidingPaneLayout.html
기능은 대체로 다음과 같다.
  • 두 아이 뷰를 병렬할 때 화면에 들어가면 바로 표시
  • 첫 번째 View를 슬라이드 메뉴처럼 자동으로 초대
  • SlidingPaneLayout만 사용하면 최소한의 다중 창 대응이 가능합니다.
    하지만 자동화는 정말 최소한의 일일 뿐이다.

    외관


    세로 화면

    수평 화면

    첫 번째 그림에서 세부 패널이 회색으로 바뀌었습니다. 이것은 SlidingPaneLayout 자동 필터입니다.

    이루어지다


    우선, 배치는 다음과 같다.
    목록 영역과 내용 영역에 각각 지정android:layout_width하여 터미널의 너비가 합계 이상인 경우 나란히 표시하고 부족한 경우 슬라이드 디스플레이를 전환할 수 있습니다.
    내용 영역에 지정android:layout_weight을 통해 터미널의 폭이 580dp보다 크면 내용 영역을 공백 부분으로 확장할 수 있습니다.
    또한 컨텐츠 영역에 android:background가 지정되어 있지만 슬라이드에 숨겨진 그림자 묘사가 이상하게 변하는 경우가 있으므로 무언가를 지정하는 것이 좋습니다.
    fragment_slidingpanel.xml
    <android.support.v4.widget.SlidingPaneLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/sliding_pane_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ListView
            android:id="@android:id/list"
            android:layout_width="280dp"
            android:layout_height="wrap_content" />
    
        <FrameLayout
            android:id="@+id/content"
            android:layout_width="300dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@android:color/white" />
    
    </android.support.v4.widget.SlidingPaneLayout>
    
    
    Fragment 설치는 목록 측면SlidingPaneLayout 측면에만 표시됩니다.
    자세한 패널의 이동 처리만 쓰고 이동할 때 메뉴 옆의 처리를 닫습니다.
    기타 다중 창과 슬라이드 애니메이션 등SlidingPaneLayout은 자동으로 진행됩니다.SlidingPaneLayout와 리스트 패널의 설치가 같다Fragment는 간소화의 비결이다.
    SlidingPanelFragment.java
    public class SlidingPanelFragment extends Fragment {
    
        SlidingPaneLayout mSlidingPaneLayout;
    
    
        public SlidingPanelFragment() {
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
    
    
            View view = inflater.inflate(R.layout.fragment_slidingpanel, container, false);
            mSlidingPaneLayout = (SlidingPaneLayout) view.findViewById(R.id.sliding_pane_layout);
    
            // 適当にリストビューの設定
            ListView listView = (ListView) mSlidingPaneLayout.findViewById(android.R.id.list);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
    
                    // 詳細側Fragmentの遷移処理
                    DetailFragment fragment = new DetailFragment();
                    // パラメータが必要な場合はsetArgumentsする
    
                    FragmentTransaction ft = getFragmentManager().beginTransaction();
                    ft.replace(R.id.content, fragment);
                    ft.addToBackStack(null);
                    ft.commit();
    
                    // パネルを閉じる
                    if (mSlidingPaneLayout.isSlideable() && mSlidingPaneLayout.isOpen()) {
                        mSlidingPaneLayout.closePane();
                    }
                }
            });
    
            return view;
        }
    
    }
    
    
    이만 마치겠습니다.
    네, 간단하죠?

    주의점


    실시SlidingPaneLayout에 있어서 매우 큰 주의점이 있다.SlidingPaneLayout 패널의 상태에 따라 메뉴의 표시/숨김을 전환하지 않기 때문에 제어 메뉴의 처리를 직접 작성해야 합니다.
    이 패널의 상태, 즉 곡자에 따라 처음 보일 때의 레이아웃ViewTreeObserver.OnGlobalLayoutListener과 패널 슬라이드를 받을 때의 호출SlidingPaneLayout.PanelSlideListener을 조합해서 실시해야 한다.
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
    
    
            View view = inflater.inflate(R.layout.fragment_slidingpanel, container, false);
            mSlidingPaneLayout = (SlidingPaneLayout) view.findViewById(R.id.sliding_pane_layout);
    
            // パネルの状態に応じてメニュー制御を行う
            mSlidingPaneLayout.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() {
                @Override
                public void onPanelSlide(View view, float v) {
                }
    
                @Override
                public void onPanelOpened(View view) {
                    panelOpened();
                }
    
                @Override
                public void onPanelClosed(View view) {
                    panelClosed();
                }
            });
    
            // 初回のみ、レイアウト状態に応じてメニュー制御を行う必要がある
            mSlidingPaneLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @SuppressWarnings("deprecation")
                @Override
                public void onGlobalLayout() {
                    if (mSlidingPaneLayout.isSlideable()) {
                        // パネルがスライド可能な場合、状態に応じてメニュー変更
                        if (mSlidingPaneLayout.isOpen()) {
                            panelOpened();
                        } else {
                            panelClosed();
                        }
                    }
                    // 初回のみわかれば良いのでリスナー解除
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
                        mSlidingPaneLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    else
                        mSlidingPaneLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                }
            });
    
    
            // 以下略
        }
    
        /**
         * パネルが閉じられた時の処理
         */
        private void panelClosed() {
    
            // リスト側メニューを無効化、詳細側メニューを有効化
            setHasOptionsMenu(false);
            if (getChildFragmentManager().findFragmentById(R.id.content) != null) {
                getChildFragmentManager().findFragmentById(R.id.content).setHasOptionsMenu(true);
            }
        }
    
        /**
         * パネルが開かれた時の処理
         */
        private void panelOpened() {
    
            // リスト側メニューを有効化、詳細側メニューを有効化
            setHasOptionsMenu(true);
            if (getChildFragmentManager().findFragmentById(R.id.content) != null) {
                getChildFragmentManager().findFragmentById(R.id.content).setHasOptionsMenu(false);
            }
        }
    
    

    총결산


    간단하긴 하지만 메뉴를 사용할 때 한꺼번에 귀찮게 하기는 어렵다.
    그럼에도 불구하고 애니메이션화된 다중화면을 디자인할 수 있어서 다행이다.
    레이아웃 파일로 멀티플렉스를 하는 게 좋을지 판단하기 어려워요.

    좋은 웹페이지 즐겨찾기