Skip to content

Most visited

Recently visited

navigation

Implementação de fluxos de interface do usuário adaptativa

Dependendo do layout do aplicativo exibido no momento, o fluxo da interface do usuário pode ser diferente. Por exemplo, se o aplicativo estiver no modo de painel duplo , clicar em um item no painel esquerdo exibirá o conteúdo no painel direito; se estiver no modo de painel único, o conteúdo será exibido sozinho (em uma atividade diferente).

Determinar o layout atual

Como a implementação de cada layout será um pouco diferente, uma das primeiras coisas a fazer é determinar o layout que o usuário está visualizando no momento. Por exemplo, descubra se o usuário está no modo “painel único" ou painel duplo". Isso é feito consultando se uma determinada exibição existe e está visível:

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;
    }
}

Observe que esse código consulta se o painel "article" está ou não disponível, o que é muito mais flexível do que codificar uma consulta para um layout específico.

Uma outra forma de se adaptar à existência de diferentes componentes é conferir se estão disponíveis antes de executar uma operação neles. Por exemplo, no aplicativo de exemplo News Reader, há um botão que abre um menu, mas esse botão só existe quando a execução é em versões superiores ao Android 3.0 (porque a função é assumida por ActionBar na API de nível 11+). Assim, para adicionar o ouvinte de evento para esse botão, você pode:

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

Reagir de acordo com o layout atual

Algumas ações podem ter um resultado diferente dependendo do layout atual. Por exemplo, no exemplo News Reader, clicar em uma notícia na lista de notícias abrirá o artigo no painel direito se a interface do usuário estiver no modo painel duplo, mas iniciará uma atividade separada se estiver no modo painel único:

@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);
    }
}

Da mesma forma, se o aplicativo estiver no modo painel duplo, ele deverá configurar a barra de ação com guias para navegação, enquanto que, se estiver no modo painel único, deverá definir a navegação com um widget giratório. Portanto, o código deve também verificar qual caso é mais adequado:

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);
    }
}

Reutilizar fragmentos em outras atividades

Um padrão recorrente na projeção de várias telas é ter parte da interface implementada como painel em algumas configurações de tela e como atividade separada em outras configurações. Por exemplo, no exemplo News Reader, o texto do artigo de notícias é apresentado no painel direito em telas grandes, mas é uma atividade separada em telas menores.

Nesses casos, é possível, normalmente, evitar a duplicação do código reutilizando a mesma subclasse Fragment em diversas atividades. Por exemplo, ArticleFragment é utilizado no layout de painel duplo:

<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>

E reutilizado (sem um layout) no layout de atividades para telas menores (ArticleActivity):

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

Naturalmente, isso tem o mesmo efeito que a declaração do fragmento em um layout XML , mas, nesse caso, um layout XML é desnecessário porque o fragmento do artigo é o único fragmento da atividade.

Um ponto muito importante a considerar ao projetar seus fragmentos é não criar um vínculo forte para uma atividade específica. Normalmente, isso é feito definindo uma interface que abstraia todas as formas com as quais o fragmento precisa interagir com a atividade host e, em seguida, ela implementa esta interface:

O HeadlinesFragment do aplicativo News Reader faz exatamente isto:

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;
    }
}

Assim, quando o usuário seleciona uma notícia, o fragmento notifica o ouvinte especificado pela atividade host (em vez de notificar uma atividade codificada específica):

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

Essa técnica é discutida mais detalhadamente no guia Suporte a tablets e celulares.

Tratar mudanças de configuração da tela

Se você estiver usando atividades distintas para implementar partes separadas da interface, será preciso considerar a possível necessidade de reagir a determinadas mudanças de configuração (como uma mudança de rotação) para manter a interface consistente.

Por exemplo, em um tablet comum de 7 polegadas executando o Android 3.0 ou posterior, o exemplo News Reader usa uma atividade separada para exibir o artigo de notícias no modo retrato, mas usa o layout com dois painéis no modo paisagem.

Isso significa que, quando o usuário está no modo retrato e a atividade para visualizar um artigo está na tela, é preciso detectar que a orientação mudou para paisagem e reagir de acordo, finalizando a atividade e voltando para a atividade principal, de forma que o conteúdo possa ser exibido no layout com dois painéis:

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!

Siga o Google Developers no WeChat

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)