Pergunta

Eu estou usando uma visão título personalizado no meu aplicativo para cada atividade. Em uma das atividades, com base em cliques de botão eu preciso mudar o ponto de vista título personalizado. Agora isso funciona bem cada vez que eu faço uma chamada para setFeatureInt.

Mas se eu tentar atualizar quaisquer itens no título personalizado (digamos alterar o texto de um botão ou uma exibição de texto no título), a atualização não ocorrer.

Depuração através dos programas de código que a exibição de texto e ocorrências de botão não são nulos e eu também pode ver a barra de título personalizado. Mas o texto na vista de texto ou o botão não é atualizado. Tem mais alguém enfrentou esse problema? Como posso resolver isso?

Graças.

Editar

Aqui está o que eu tentei. não é atualizado, mesmo em chamar postInvalidate.

    getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.text_title);

    TextView databar = (TextView) findViewById(R.id.title_text);
    databar.setText("Some Text");
    databar.postInvalidate();

    Button leftButton = (Button) findViewById(R.id.left_btn);
    leftButton.setOnClickListener(mLeftListener);
    leftButton.setText("Left Btn");
    leftButton.postInvalidate();

    Button rightBtn = (Button) findViewById(R.id.right_btn);
    rightBtn.setOnClickListener(mRightListener);
    rightBtn.postInvalidate();
Foi útil?

Solução

O problema é que a única Window implementação ( PhoneWindow ) usa um LayoutInflater em seu método setFeatureInt e instancia o novo layout com inflate attachToRoot=true. Consequentemente, quando você chamar setFeatureInt, os novos layouts não são substituir e anexado para o recipiente título interno e, assim, desenhado em cima uns dos outros.

Você pode resolver isso usando o seguinte método auxiliar em vez de setFeatureInt. O auxiliar simplesmente remove todas as vistas a partir do recipiente título interno antes do novo recurso título personalizado está definido:


private void setCustomTitleFeatureInt(int value) {
    try {
        // retrieve value for com.android.internal.R.id.title_container(=0x1020149)
        int titleContainerId = (Integer) Class.forName(
            "com.android.internal.R$id").getField("title_container").get(null);

        // remove all views from titleContainer
        ((ViewGroup) getWindow().findViewById(titleContainerId)).removeAllViews();

        // add new custom title view 
        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, value);

    } catch(Exception ex) {
        // whatever you want to do here..
    }
}

Eu não tenho certeza se o comportamento setFeatureInt atual se destina, mas certamente não está documentado de uma forma ou outra razão pela qual eu vou levar isso para os desenvolvedores Android;)

Editar

Como apontado nos comentários, a solução alternativa acima mencionada não é o ideal. Em vez de depender da constante com.android.internal.R.id.title_container você poderia simplesmente hide o título antigo costume sempre que você definir um novo.

Vamos supor que você tem layouts título dois personalizados:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/custom_title_1" ...

e

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/custom_title_2" ...

e você deseja substituir custom_title_1 com custom_title_2, que poderia se esconder primeiro e uso setFeatureInt para adicionar o último:

findViewById(R.id.custom_title_1).setVisibility(View.GONE);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_2);

Outras dicas

A maneira correta de fazer isso é o seguinte:

requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView( R.layout.my_layout );
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.my_custom_title );
super.onCreate( savedInstanceState );

Por favor note que a ordem dessas declarações é muito importante.

Se você chamar super.onCreate () antes de qualquer uma das outras declarações que você terá uma barra de título em branco, o que o hack de encontrar o ID de barra de título e remoção de todas as vistas a partir dele vai resolver, mas não é recomendado.

Você está chamando invalidar ou postInvalidate para redesenhar a vista depois de atualizar o texto? Se é um costume View, você pode colocar um ponto de interrupção no código empate para se certificar de que está sendo chamado?

Se você está no segmento interface do usuário, você pode chamar de 'invalidar' se você não for, você deve chamar 'postInvalidate' ou a vista não irá redesenhar próprio.

Apenas meu valor 2c:

Ao trabalhar em um MapActivity, solicitando um título personalizado resultou em nenhum título em tudo que está sendo mostrado.

Felizmente, tudo que eu queria fazer era para definir o texto de título diferente, e logo percebi que apenas chamando setTitle () dentro de onCreate () trabalhou para mim (eu o chamei após I chamado setContentView ())

Desculpe, mas eu não tenho tempo agora para depurar isso mais e descobrir por que eu estava fazendo não funcionou, e por que mudá-lo feito o trabalho. Como eu disse, apenas pensei que isso pode ajudar alguém no caminho.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top