requestFeature () deve ser chamado antes de adicionar conteúdo

135

Estou tentando implementar uma barra de título personalizada:

Aqui está a minha classe Helper:

import android.app.Activity;
import android.view.Window;

public class UIHelper {
    public static void setupTitleBar(Activity c) {
        final boolean customTitleSupported = c.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);

        c.setContentView(R.layout.main);

        if (customTitleSupported) {
            c.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.titlebar);
        }
    }
}

Aqui é onde eu chamo onCreate ():

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

private void setupUI(){
     setContentView(R.layout.main);
     UIHelper.setupTitleBar(this);
}

Mas eu recebo o erro:

requestFeature() must be called before adding content
Sheehan Alam
fonte

Respostas:

331

Bem, faça o que a mensagem de erro diz.

Não ligue setContentView()antesrequestFeature() .

Nota:

Como dito nos comentários, para ambos ActionBarSherlocke para a AppCompatbiblioteca, é necessário ligar requestFeature()antessuper.onCreate()

Otaviano A. Damiean
fonte
60
caramba, esta é uma resposta elegante.
Uma Pessoa
60
Para o ActionBarSherlock, também é necessário ligar requestFeature()antes super.onCreate(). Referência: github.com/JakeWharton/ActionBarSherlock/issues/…
Saran
1
E se você precisar mostrar um layout sem uma barra de título e depois mostrar um com uma barra de título? Você terá que usá requestWindowFeature(Window.FEATURE_NO_TITLE)-lo para ocultá-lo e, em seguida, setContentView()para o seu primeiro layout e requestWindowFeature(Window.FEATURE_CUSTOM_TITLE)para mostrar a barra de título novamente. Isso seria depois setContentView()da segunda vez.
msbg
35
É o mesmo caso na AppCompat como o @Saran disse. Você deve ligar para o seu requestFeatureantessuper.onCreate()
Jaison Brooks 27/10
7
Esta resposta não ajuda muito ... mas o que eu sei
Ojonugwa Jude Ochalifu 26/15/15
23

Sei que tem mais de um ano, mas ligar requestFeature()nunca resolveu meu problema. Na verdade, eu não chamo nada disso.

Foi um problema inflacionar a visão que suponho. Apesar de toda a minha pesquisa, nunca encontrei uma solução adequada até brincar com os diferentes métodos de inflar uma exibição.

AlertDialog.Builder é a solução fácil, mas requer muito trabalho se você usar o onPrepareDialog()para atualizar essa exibição.

Outra alternativa é aproveitar o AsyncTask para diálogos.

Uma solução final que usei está abaixo:

public class CustomDialog extends AlertDialog {

   private View content;

   public CustomDialog(Context context) {
       super(context);

       LayoutInflater li = LayoutInflater.from(context);
       content = li.inflate(R.layout.custom_view, null);

       setUpAdditionalStuff(); // do more view cleanup
       setView(content);           
   }

   private void setUpAdditionalStuff() {
       // ...
   }

   // Call ((CustomDialog) dialog).prepare() in the onPrepareDialog() method  
   public void prepare() {
       setTitle(R.string.custom_title);
       setIcon( getIcon() );
       // ...
   }
}

* Algumas notas adicionais:

  1. Não confie em esconder o título. Geralmente, há um espaço vazio, apesar do título não estar definido.
  2. Não tente criar sua própria vista com o rodapé do cabeçalho e a vista do meio. O cabeçalho, como indicado acima, pode não estar totalmente oculto, apesar de solicitar FEATURE_NO_TITLE.
  3. Não estilize sua exibição de conteúdo com atributos de cores ou tamanho de texto. Deixe a caixa de diálogo lidar com isso; caso contrário, você corre o risco de colocar texto em preto em uma caixa de diálogo em azul escuro porque o fornecedor inverteu as cores.
Cookster
fonte
Originalmente, publiquei setTitle () e setIcon () no método onCreate (), mas a edição o moveu para o método prepare () que é chamado durante o método onPrepareDialog ().
Cookster
2
Obrigado por compartilhar. Eu acho que a seguinte linha content = inflater.inflate(R.layout.custom_view, null);provavelmente deveria ser content = li.inflate(R.layout.custom_view, null);. Então, inflatertem que ser substituído por li.
aLearner
14

Eu estava estendendo um DialogFragment e a resposta acima não funcionou. Eu tive que usar getDialog () para conseguir remover o título:

getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
Argumento ilegal
fonte
@ojonugwaochalifu era um tempo atrás para que eu não me lembro exatamente, mas tenho a certeza que precisa ser feito antes setContentView método ()
Argumento Ilegal
1
para qualquer um que enfrenta o mesmo problema: eu adicionei esse código em onViewCreated ();
precisa saber é o seguinte
2

O erro não diz exatamente o que há de errado? Você está ligando requestWindowFeaturee setFeatureIntdepois de ligarsetContentView .

A propósito, por que você está ligando setContentViewduas vezes?

EboMike
fonte
2

Para o SDK versão 23 e posterior, a mesma RuntimeException será lançada se você estiver usando AppCompatActivity para estender sua atividade. Isso não acontecerá se sua atividade deriva diretamente da atividade.

Esse é um problema conhecido no Google, conforme mencionado em https://code.google.com/p/android/issues/detail?id=186440

A solução alternativa fornecida é usar o método supportRequestWindowFeature () em vez de usar requestFeature ().

Voto por favor, se resolver o seu problema.

Keshav Bansal
fonte
1

Altere a versão do SDK de compilação , a versão do SDK de destino para a versão Build Tools para 24.0.0 em build.gradle se você enfrentar um problema na solicitação

Jaichander
fonte
0

No meu caso eu mostrei DialogFragmentno Activity. Neste fragmento de diálogo, escrevi como em DialogFragment remove black border :

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(STYLE_NO_FRAME, 0)
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    super.onCreateDialog(savedInstanceState)

    val dialog = Dialog(context!!, R.style.ErrorDialogTheme)
    val inflater = LayoutInflater.from(context)
    val view = inflater.inflate(R.layout.fragment_error_dialog, null, false)
    dialog.setTitle(null)
    dialog.setCancelable(true)
    dialog.setContentView(view)
    return dialog
}

Remova setStyle(STYLE_NO_FRAME, 0)em onCreate()ou / remover Chande onCreateDialog. Porque as configurações da caixa de diálogo foram alteradas após a criação da caixa de diálogo.

CoolMind
fonte
0

Eu tive esse problema com o Dialogs com base em um DialogFragment estendido que funcionou bem em dispositivos executando a API 26, mas falhou com a API 23. As estratégias acima não funcionaram, mas resolvi o problema removendo o método onCreateView (que foi adicionado por mais modelo recente do Android Studio) do DialogFragment e criando a caixa de diálogo no onCreateDialog.

BillC
fonte