O Android 8.0 introduziu uma nova arquitetura da informação para o app Configurações para: simplificar a maneira como as configurações são organizadas e facilitar para os usuários encontrar rapidamente as configurações para personalizar os dispositivos Android. O Android 9 introduziu algumas melhorias para oferecer funcionalidade de configurações e implementação facilitada.
Exemplos e origem
A maioria das páginas em "Configurações" está implementada usando o novo framework. Uma boa
exemplo é DisplaySettings:
packages/apps/Settings/src/com/android/settings/DisplaySettings.java
Os caminhos de arquivos para componentes importantes estão listados abaixo:
- CategoryKey:
packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
- DashboardFragmentRegistry:
packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
- DashboardFragment:
packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
- BackgroundPreferenceController:
frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
- BasePreferenceController (introduzido no Android 9):
packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java
Implementação
Recomendamos que os fabricantes de dispositivos adaptem as informações das configurações
e inserir páginas de configuração adicionais conforme necessário para acomodar
recursos específicos do parceiro. Como mover preferências da página legada (implementado como
SettingsPreferencePage
) para uma nova página (implementada usando
DashboardFragment
) pode ser complicado. A preferência do parâmetro
página legada provavelmente não foi implementada com um PreferenceController
.
Portanto, ao mover as preferências de uma página legada para uma nova, é necessário criar um
PreferenceController
e mova o código para o controle antes
instanciando-o no novo DashboardFragment
. As APIs que
As exigências de PreferenceController
estão descritas no nome e
documentadas no Javadoc.
É altamente recomendável adicionar um teste de unidade para cada PreferenceController
.
Se a mudança for enviada ao AOSP, será necessário um teste de unidade.
Para mais informações sobre como criar testes baseados no Robolectric, consulte a
arquivo readme packages/apps/Settings/tests/robotests/README.md
.
Arquitetura da informação de estilo de plug-in
Cada item de configurações é implementado como uma Preferência. Uma preferência pode ser movidos de uma página para outra.
Para facilitar a movimentação de várias configurações, o Android 8.0 introduziu um fragmento de host estilo plug-in que contém itens de configuração. Os itens de configuração são modelados como controladores de estilo de plug-in. Portanto, uma página de configurações é construída por um fragmento de host único e vários controladores de configuração.
DashboardFragment
O DashboardFragment
é o host de controladores de preferência do estilo de plug-in.
O fragmento é herdado de PreferenceFragment
e tem hooks para
expandir e atualizar as listas de preferências estáticas e as listas de preferências dinâmicas.
Preferências estáticas
Uma lista de preferências estáticas é definida em XML usando a tag <Preference>
. Um
A implementação de DashboardFragment
usa as
método getPreferenceScreenResId()
para definir qual arquivo XML contém
a lista estática de preferências a serem exibidas.
Preferências dinâmicas
Um item dinâmico representa um bloco com intent, levando a uma atividade externa ou interna
Atividade. Normalmente, a intent leva a uma página de configuração diferente. Por exemplo:
a página de configuração na página inicial "Configurações" é um item dinâmico. Dinâmico
itens são definidos em AndroidManifest
(discutidos abaixo) e carregados
usando um FeatureProvider
(definido como
DashboardFeatureProvider
).
As configurações dinâmicas são mais pesadas do que as configuradas estaticamente configurações. Portanto, normalmente os desenvolvedores devem implementar a configuração como estática. No entanto, a configuração dinâmica pode ser útil quando alguma das seguintes condições é verdadeira:
- A configuração não é implementada diretamente no app Configurações (como injetando uma configuração implementada por apps de OEM/operadora).
- A configuração deve aparecer na página inicial de Configurações.
- Você já tem uma atividade para a configuração e não quer implementar a configuração extra estática.
Para definir uma atividade como dinâmica, faça o seguinte:
- Marque a atividade como uma configuração dinâmica adicionando um filtro de intent à atividades.
- Informe ao app Configurações a que categoria ele pertence. A categoria é uma constante,
definido em
CategoryKey
. - Opcional: adicione um texto de resumo quando a configuração for exibida.
Aqui está um exemplo retirado do app Configurações de DisplaySettings
.
<activity android:name="Settings$DisplaySettingsActivity" android:label="@string/display_settings" android:icon="@drawable/ic_settings_display"> <!-- Mark the activity as a dynamic setting --> <intent-filter> <action android:name="com.android.settings.action.IA_SETTINGS" /> </intent-filter> <!-- Tell Settings app which category it belongs to --> <meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.ia.homepage" /> <!-- Add a summary text when the setting is displayed --> <meta-data android:name="com.android.settings.summary" android:resource="@string/display_dashboard_summary"/> </activity>
No momento da renderização, o fragmento solicita uma lista de preferências da API
Configurações dinâmicas e XML definidas em AndroidManifest
. Seja
PreferenceController
s são definidas em código Java ou em XML.
O DashboardFragment
gerencia a lógica de processamento de cada configuração.
usando PreferenceController
(discutidos abaixo). Então, eles são
exibida na interface como uma lista mista.
PreferenceController
Há diferenças entre a implementação de PreferenceController
no Android 9 e no Android 8.x, conforme descrito neste
nesta seção.
PreferenceController na versão do Android 9
Uma PreferenceController
contém toda a lógica para interagir com o
preferência, incluindo exibição, atualização, indexação de pesquisas etc.
A interface de PreferenceController
é definida como
BasePreferenceController
. Por exemplo, consulte o código em
packages/apps/Settings/src/com/android/settings/core/
BasePreferenceController.java
Há várias subclasses de BasePreferenceController
, cada uma
o mapeamento para um estilo de interface específico que tem suporte do app Configurações por padrão. Para
Por exemplo, TogglePreferenceController
tem uma API que mapeia diretamente
de como o usuário deve interagir com uma interface de preferências baseadas em alternância.
BasePreferenceController
tem APIs como
getAvailabilityStatus()
, displayPreference()
handlePreferenceTreeClicked(),
etc. Documentação detalhada para cada
A API está na classe de interface.
Uma restrição na implementação de BasePreferenceController
(e
das subclasses, como TogglePreferenceController
) é que
A assinatura do construtor precisa corresponder a um dos seguintes itens:
public MyController(Context context, String key) {}
public MyController(Context context) {}
Ao instalar uma preferência para o fragmento, o painel fornece um método para
anexar um PreferenceController
antes do tempo de exibição. No momento da instalação,
o controlador está conectado ao fragmento para que todos os eventos futuros relevantes sejam
são enviadas ao controlador.
DashboardFragment
mantém uma lista de
PreferenceController
na tela. No módulo
onCreate()
, todos os controladores são invocados para a
método getAvailabilityStatus()
e, se retornar verdadeiro,
displayPreference()
é invocado para processar a lógica de exibição.
getAvailabilityStatus()
também é importante para informar as configurações
quais itens ficam disponíveis durante a pesquisa.
PreferenceController nas versões do Android 8.x
Uma PreferenceController
contém toda a lógica para interagir com o
preferência, incluindo exibição, atualização e indexação de pesquisas. etc.
A interface de
PreferenceController
tem as APIs isAvailable()
,
displayPreference()
, handlePreferenceTreeClicked()
etc., de acordo com as interações de preferência.
A documentação detalhada de cada API pode ser encontrada na classe de interface.
Ao instalar uma preferência para o fragmento, o painel fornece um método para
anexar um PreferenceController
antes do tempo de exibição. No momento da instalação,
o controlador está conectado ao fragmento para que todos os eventos futuros relevantes sejam
enviados ao controlador.
DashboardFragment
mantém uma lista de PreferenceControllers
na tela. No onCreate()
do fragmento, todos
são invocados para o método isAvailable()
e, se ele
retorna verdadeiro, displayPreference()
é invocado para processar a exibição
lógica.
Usar o DashboardFragment
Mover uma preferência da página A para B
Se a preferência estiver estaticamente listada no XML de preferências da página original siga o procedimento de movimentação Estática para o seu Android versão abaixo. Caso contrário, siga o procedimento de movimento Dinâmico para sua versão do Android.
Movimento estático no Android 9
- Encontrar os arquivos XML de preferência para a página original e o destino
página. Você pode encontrar essas informações na página
getPreferenceScreenResId()
. - Remova a preferência do XML da página original.
- Adicione a preferência ao XML da página de destino.
- Remova o
PreferenceController
dessa preferência do implementação Java da página original. Normalmente, é emcreatePreferenceControllers()
: O controlador pode ser declarado em XML diretamente.Observação: a preferência pode não ter um
PreferenceController
- Instancie o
PreferenceController
no elementocreatePreferenceControllers()
. Se oPreferenceController
é definido em XML na página antiga, defina-o em XML para a nova página também.
Movimento dinâmico no Android 9
- Descubra qual categoria hospeda a página original e a de destino. Você pode
encontrar essa informação em
DashboardFragmentRegistry
. - Abra o arquivo
AndroidManifest.xml
que contém a configuração que você precisa se mover e encontrar a entrada Activity que representa essa configuração. - Defina o valor de metadados da atividade para
com.android.settings.category
à chave de categoria da nova página.
Movimento estático nas versões do Android 8.x
- Encontre os arquivos XML de preferências para a página original e a página de destino. Você encontra essas informações no método
- Remova a preferência no XML da página original.
- Adicione a preferência ao XML da página de destino.
- Remova o
PreferenceController
dessa preferência no implementação Java da página original. Normalmente, é emgetPreferenceControllers()
: - Instancie o
PreferenceController
no elementogetPreferenceControllers()
.
getPreferenceScreenResId()
da página.
Observação: é possível que a preferência não tenha
PreferenceController
Movimento dinâmico nas versões do Android 8.x
- Descubra qual categoria hospeda a página original e a de destino. Você pode encontrar
essas informações em
DashboardFragmentRegistry
. - Abra o arquivo
AndroidManifest.xml
que contém a configuração que você precisa se mover e encontrar a entrada Activity que representa essa configuração. - Mude o valor de metadados da atividade para
com.android.settings.category
. defina o ponto de valor como a chave de categoria da nova página.
Criar uma nova preferência em uma página
Se a preferência estiver estaticamente listada no XML de preferências da página original siga o procedimento estático abaixo. Caso contrário, siga as dynamic.
Criar uma preferência estática
- Encontre os arquivos XML de preferência para a página. Você pode encontrar essas informações do método getPreferenceScreenResId() da página.
- Adicione um novo item de preferência no XML. Verifique se ele tem um
android:key
exclusivo. -
Defina um
PreferenceController
para essa preferência no elementogetPreferenceControllers()
.- No Android 8.x e, opcionalmente, no Android 9,
instanciar um
PreferenceController
para essa preferência no métodocreatePreferenceControllers()
da página.Se essa preferência já existia em outros lugares, é possível já um
PreferenceController
para isso. É possível reutilizar oPreferenceController
sem criar uma nova. -
A partir do Android 9, é possível declarar os
PreferenceController
em XML ao lado da preferência. Por exemplo:<Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" settings:controller="com.android.settings.system.ResetPreferenceController"/>
- No Android 8.x e, opcionalmente, no Android 9,
instanciar um
Criar uma preferência dinâmica
- Descubra qual categoria hospeda a página original e a de destino. Você pode encontrar
essas informações em
DashboardFragmentRegistry
. - Criar uma nova atividade em
AndroidManifest
- Adicione os metadados necessários à nova atividade para definir a configuração. Defina o
o valor de metadados de
com.android.settings.category
para o mesmo valor definido na etapa 1.
Criar nova página
- Crie um novo fragmento, herdado de
DashboardFragment
. - Defina a categoria no
DashboardFragmentRegistry
.Observação:esta etapa é opcional. Se você não precisar preferências dinâmicas nesta página, não será necessário fornecer uma chave de categoria.
- Siga as etapas para adicionar as configurações necessárias a essa página. Para mais mais informações, consulte a seção Implementação.
Validação
- Execute os testes Robolectric nas Configurações. Todos os testes novos e existentes precisam passar.
- Crie e instale as Configurações e abra manualmente a página que está sendo modificada. A página será atualizada imediatamente.