북극곰의 개발일기

마스터/디테일 폴로





posted by purplebeen on Sat Feb 03 2018 22:55:08 GMT+0900 (KST) in Android


마스터/디테일 폴로 : 안드로이드의 인터페이스 디자인 개념으로, 우선 항목들의 리스트(마스터 리스트)를 사용자에게 보여준 뒤 리스트에서 항목을 선택하는 즉시 그 항목과 관련된 추가 정보가 디테일 패널에 나타나는 것을 말한다. 일반적으로 안드로이드에서 메일 앱과 같은 것이 대표적인 마스터/디테일 폴로 애플리케이션이라 볼 수 있다.

콜백메소드 : 액티비티가 싲가 또는 종료되거나 상태가 변할때 안드로이드 프레임워크가 호출하는 메소드

<Object Kind> ListActivity.java

  • 프로젝트의 메인 액티비티이며 마스터 리스트를 사용자에게 보여준다.
  • onItemSelected()콜백메소드 구현 : 사용자가 마스터 리스트의 항목을 선택하면 호출되어 디테일 패널의 인스턴스를 생성하고 보여주는 일

activity_<Object Kind> twopane.xml : 두 패널 모드를 지원할 만큼 큰 장치 화면에서 실행중일 때 사용

activity_<Object Kind>_list.xml : 두 패널 모드를 지원하기에는 화면이 너무 작은 장치에서 사용되는 마스터 리스트의 <Object Kind>_list 프래그먼트를 포함하는 XML 레이아웃 리소스

<Object Kind>ListFragment.java : 사용자가 마스터 리스트에서 현재 선택한 항목을 식별하고 처리하는 여러 메소드를 가지고 있음

<Object Kind> DetailActivity.java : 화면이 너무 작은 장치에서 사용할 디테일 패널의 액티비티를 나타내는 자바 클래스

activity_<ObjectKind>_detail.xml : 사용자 인터페이스 요소들이 추가되는 FrameLayout 인스턴스를 이 파일에서 기본적으로 포함

<Object Kind>DetailFragment.java : 마스터 리스트와 연관된 디테일 데이터를 로드하고 fragment_<Object Kind>_detail.xml 파일의 내용을 사용자에게 보여 준다.

<Object Kind>_detail.xml : 디테일 패널의 사용자 인터페이스

DummyContent.java : 템플릿의 샘플 데이터를 제공하기 위해 만든 클래스 파일

간단하게 리스트 뷰에서 선택을 하면 디테일뷰에서 web뷰로 홈페이지가 나오는 앱을 만들어 보자.

먼저 이를 위해서는 기본값에 해당되는 DummyContent를 수정해줘야 한다.

DummyContent 안에는 기본 클래스인 DummyContent와 DummyItem 이라는 Inner 클래스가 있는데,

이를 수정해서 기본적으로 받아오는 인자값에 website의 이름과 url을 받아오게 해주고

기본 아이템도 자동으로 추가되는 비어있는 것이 아니라 새로 추가해줘야 한다.

package com.example.baehy.masterdetailflow.dummy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DummyContent {
    
    public static final List<DummyItem> ITEMS = new ArrayList<DummyItem>();
    public static final Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
    private static final int COUNT = 25;

    static {
        addItem(new DummyItem("1", "amazon", "http://www.amazon.com"));
        addItem(new DummyItem("2", "ebookfrenzy", "http://www.ebookfrenzy.com"));
        addItem(new DummyItem("3", "WikiPedia", "http://www.wikipedia.org"));
    }

    private static void addItem(DummyItem item) {
        ITEMS.add(item);
        ITEM_MAP.put(item.id, item);
    }

    private static DummyItem createDummyItem(int position) {
        return new DummyItem(String.valueOf(position), "Item " + position, makeDetails(position));
    }

    private static String makeDetails(int position) {
        StringBuilder builder = new StringBuilder();
        builder.append("Details about Item: ").append(position);
        for (int i = 0; i < position; i++) {
            builder.append("\nMore details information here.");
        }
        return builder.toString();
    }
    public static class DummyItem {
        public final String id;
        public final String content;
        public final String details;

        public DummyItem(String id, String website_name, String website_url) {
            this.id = id;
            this.content = website_name;
            this.details = website_url;
        }

        @Override
        public String toString() {
            return content;
        }
    }
}

static 부분에서 아이템을 추가하면서 dummyItem 객체를 생성하였고,

인자값으로 id와 사이트명, 그리고 사이트의 url을 넘겨주었다.

그런데 기본적으로 마스터/폴로 뷰에서 제공하는 디테일뷰는 텍스트뷰이기 때문에

우리가 원하는 데로 웹사이트가 실행되도록 하기 위해서는 WebView로 이를 바꿔 주어야 한다.

<WebView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/website_detail"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

기존의 TextView 에서 WebView로 바꾸어주었고, 이제 이를 구현하는 프래그먼트에서도

Item객체의 url값을 저장하는 값인 details의 값을 이용하여 웹페이지를 띄울 수 있도록 해야 한다.

package com.example.baehy.masterdetailflow;

import android.app.Activity;
import android.support.design.widget.CollapsingToolbarLayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.TextView;

import com.example.baehy.masterdetailflow.dummy.DummyContent;

public class WebsiteDetailFragment extends Fragment {
    public static final String ARG_ITEM_ID = "item_id";
    private DummyContent.DummyItem mItem;
    public WebsiteDetailFragment() {
    }

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

        if (getArguments().containsKey(ARG_ITEM_ID)) {
            // Load the dummy content specified by the fragment
            // arguments. In a real-world scenario, use a Loader
            // to load content from a content provider.
            mItem = DummyContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID));

            Activity activity = this.getActivity();
            CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) 
activity.findViewById(R.id.toolbar_layout);
            if (appBarLayout != null) {
                appBarLayout.setTitle(mItem.content);
            }
        }
    }

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

        // Show the dummy content as text in a TextView.
        if (mItem != null) {
            ((WebView) rootView.findViewById(R.id.website_detail)).loadUrl(mItem.details);
        }

        return rootView;
    }
}

TextView를 WebView로 수정해주고 loadUrl()메소드를 이용하여 Item 객체에 있는 details(사이트 url 값)을 불러와 웹뷰로 로딩하게 하였다.

앱을 테스트 해보기 전에 설정해줘야 할 것이 하나 더 있다. 바로 매니페스트 퍼미션 설정이다.

우리가 설정하지 않는다면 안드로이드가 웹뷰의 설정 값을 가지고 있지 않기 때문에 이를 해결하기 위해서는 매니패스트 퍼미션 설정을 해줘야 한다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.baehy.masterdetailflow">

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".WebsiteListActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".WebsiteDetailActivity"
            android:label="@string/title_website_detail"
            android:parentActivityName=".WebsiteListActivity"
            android:theme="@style/AppTheme.NoActionBar">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.example.baehy.masterdetailflow.WebsiteListActivity" />
        </activity>
    </application>

</manifest>
<uses-permission android:name="android.permission.INTERNET" />

이 부분을 통해 인터넷 사용에 대한 권한을 앱에게 주었다. 그럼 이제 실행시켜보자.