Skip to content

Most visited

Recently visited

navigation

적응형 UI 흐름 구현

현재 애플리케이션이 표시하는 레이아웃에 따라 UI 흐름이 다를 수 있습니다. 예를 들어 애플리케이션이 이중 창 모드일 경우 왼쪽 창에서 항목을 클릭하면 오른쪽 창에 콘텐츠가 표시됩니다. 단일 창 모드일 경우, 콘텐츠는 (다른 액티비티로) 단독 표시됩니다.

현재 레이아웃 확인

각 레이아웃 구현이 약간 다르므로 처음 수행해야 하는 작업은 사용자가 현재 보고 있는 레이아웃을 확인하는 것입니다. 예를 들어 사용자가 "단일 창" 모드인지 "이중 창" 모드인지 알고 싶을 수 있습니다. 특정 뷰가 존재하고 보이는 상태라면 쿼리로 이 작업을 수행할 수 있습니다.

public class NewsReaderActivity extends FragmentActivity {
    boolean mIsDualPane;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);

        View articleView = findViewById(R.id.article);
        mIsDualPane = articleView != null &&
                        articleView.getVisibility() == View.VISIBLE;
    }
}

이 코드가 "기사" 창을 이용할 수 있는지 여부에 대해 쿼리한다는 점에 유의하세요. 특정 레이아웃 쿼리를 하드코딩하는 것보다 더 유연합니다.

다양한 구성 요소의 존재에 적응할 수 있는 방법을 보여주는 다른 예시로는 구성 요소에서 작업을 수행하기 전에 이용 가능한지 확인하는 것이 있습니다. 예를 들어, News Reader 샘플 앱에는 메뉴를 여는 버튼이 있지만 이 버튼은 Android 3.0 이하 버전에서 실행될 때만 나타납니다(API 레벨 11 이상에서는 버튼 기능을 ActionBar가 대신하기 때문임). 이 버튼의 이벤트 리스너를 추가하려면 다음과 같이 수행할 수 있습니다.

Button catButton = (Button) findViewById(R.id.categorybutton);
OnClickListener listener = /* create your listener here */;
if (catButton != null) {
    catButton.setOnClickListener(listener);
}

현재 레이아웃에 따른 반응

현재 레이아웃에 따라 일부 동작은 다른 결과가 나올 수 있습니다. 예를 들어 News Reader 샘플에서 헤드라인 목록에서 헤드라인을 클릭하면 UI가 이중 창 모드일 경우 오른쪽에 기사가 열리고 UI가 단일 창 모드일 경우 별도 액티비티로 시작됩니다.

@Override
public void onHeadlineSelected(int index) {
    mArtIndex = index;
    if (mIsDualPane) {
        /* display article on the right pane */
        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    } else {
        /* start a separate activity */
        Intent intent = new Intent(this, ArticleActivity.class);
        intent.putExtra("catIndex", mCatIndex);
        intent.putExtra("artIndex", index);
        startActivity(intent);
    }
}

마찬가지로 앱이 이중 창 모드일 경우 내비게이션에 탭이 있는 작업 모음을 설정해야 하지만 앱이 단일 차창 모드일 경우 스피너 위젯이 있는 내비게이션을 설정해야 합니다. 그러므로 코드에서도 어느 경우가 적절한지 확인해야 합니다.

final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };

public void onCreate(Bundle savedInstanceState) {
    ....
    if (mIsDualPane) {
        /* use tabs for navigation */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
        int i;
        for (i = 0; i < CATEGORIES.length; i++) {
            actionBar.addTab(actionBar.newTab().setText(
                CATEGORIES[i]).setTabListener(handler));
        }
        actionBar.setSelectedNavigationItem(selTab);
    }
    else {
        /* use list navigation (spinner) */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
        SpinnerAdapter adap = new ArrayAdapter(this,
                R.layout.headline_item, CATEGORIES);
        actionBar.setListNavigationCallbacks(adap, handler);
    }
}

다른 액티비티에서 프래그먼트 재사용

여러 화면 디자인에서 반복적으로 나타나는 패턴은 일부 화면 구성에서는 창으로 구현되고 다른 구성에서는 별도 액티비티로 구현되는 인터페이스의 일부가 포함됩니다. 예를 들어 News Reader 샘플에서 뉴스 기사 텍스트는 큰 화면에서 오른쪽에 표시되지만 작은 화면에서 별도 액티비티로 나타납니다.

이 경우, 일반적으로 여러 액티비티에서 같은 Fragment 서브클래스를 다시 사용하여 코드 중복을 피할 수 있습니다. 예를 들어 ArticleFragment는 이중 창 레이아웃에 사용합니다.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>

작은 화면의 액티비티 레이아웃에서 (레이아웃 없이) 재사용됩니다(ArticleActivity).

ArticleFragment frag = new ArticleFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();

당연히 XML 레이아웃에서 프래그먼트를 선언하는 것과 같은 효과를 내지만, 이 경우 기사 프래그먼트가 이 액티비티의 유일한 구성 요소이므로 XML 레이아웃은 불필요한 작업입니다.

프래그먼트를 디자인할 때 유의해야 할 매우 중요한 한 가지는 특정 액티비티에 강한 커플링을 생성하지 않는 것입니다. 일반적으로 프래그먼트가 호스트 액티비티와 상호작용하는 데 필요한 모든 방법을 추상화하는 인터페이스를 정의하고 호스트 액티비티가 그 인터페이스를 구현함으로써 가능해집니다.

예를 들어, News Reader 앱의 HeadlinesFragment가 바로 그런 방식을 사용합니다.

public class HeadlinesFragment extends ListFragment {
    ...
    OnHeadlineSelectedListener mHeadlineSelectedListener = null;

    /* Must be implemented by host activity */
    public interface OnHeadlineSelectedListener {
        public void onHeadlineSelected(int index);
    }
    ...

    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
        mHeadlineSelectedListener = listener;
    }
}

사용자가 헤드라인을 선택하면 프래그먼트가 호스트 액티비티에서 지정된 리스너에게 알립니다(특정 하드코딩된 액티비티를 알리지 않음).

public class HeadlinesFragment extends ListFragment {
    ...
    @Override
    public void onItemClick(AdapterView<?> parent,
                            View view, int position, long id) {
        if (null != mHeadlineSelectedListener) {
            mHeadlineSelectedListener.onHeadlineSelected(position);
        }
    }
    ...
}

이 기술은 태블릿 및 헤드셋 지원 가이드에서 자세히 설명합니다.

화면 구성 변경 처리

별도 액티비티를 사용하여 인터페이스의 별도 부분을 구현한다면 인터페이스의 일관성을 유지하기 위해 특정 구성 변화(예: 회전 변화)에 반응하게 해야 할 수도 있습니다.

예를 들어 Android 3.0 이상이 실행되는 일반적 7인치 태블릿에서 News Reader 샘플은 세로 모드로 실행될 때 별도 액티비티를 사용하여 뉴스 기사를 표시하지만 가로 모드일 때는 창 두 개 레이아웃을 사용합니다.

사용자가 세로 모드이고 기사를 보는 액티비티가 화면에 있을 때, 방향이 가로로 변경되었는지 확인한 뒤에 콘텐츠가 창 두 개 레이아웃으로 표시되도록 액티비티를 종료하고 메인 액티비티로 돌아오는 방식으로 적절히 반응해야 합니다.

public class ArticleActivity extends FragmentActivity {
    int mCatIndex, mArtIndex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);

        // If should be in two-pane mode, finish to return to main activity
        if (getResources().getBoolean(R.bool.has_two_panes)) {
            finish();
            return;
        }
        ...
}
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

WeChat에서 Google Developers 팔로우하기

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience. (Dec 2017 Android Platform & Tools Survey)