アプリケーションで各アクティビティのカスタムタイトルビューを使用しています。アクティビティの1つで、ボタンのクリックに基づいて、カスタムタイトルビューを変更する必要があります。これで、setFeatureIntを呼び出すたびに正常に機能します。
しかし、カスタムタイトルのアイテムを更新しようとすると(ボタンのテキストやタイトルのテキストビューを変更するなど)、更新は行われません。
コードをデバッグすると、テキストビューとボタンのインスタンスがnullではなく、カスタムタイトルバーも表示されます。ただし、テキストビューまたはボタンのテキストは更新されません。他の誰かがこの問題に直面しましたか?どうすれば解決できますか?
ありがとう。
[〜#〜]編集[〜#〜]
これが私が試したものです。 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();
問題は、唯一の Window
実装( PhoneWindow
)が LayoutInflater
を使用することですsetFeatureInt
メソッド内で、 inflate
およびattachToRoot=true
を使用して新しいレイアウトをインスタンス化します。その結果、setFeatureInt
を呼び出すと、新しいレイアウトは置換ではなく内部タイトルコンテナーに添付され、したがって、互いの上に描画されます。
これを回避するには、setFeatureInt
の代わりに次のヘルパーメソッドを使用します。ヘルパーは、新しいカスタムタイトル機能が設定される前に、内部のタイトルコンテナーからすべてのビューを削除するだけです。
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..
}
}
現在のsetFeatureInt
の動作が意図したものであるかどうかはわかりませんが、どちらかといえば文書化されていないため、Android devs ;)
[〜#〜]編集[〜#〜]
コメントで指摘されているように、前述の回避策は理想的ではありません。 com.Android.internal.R.id.title_container
定数に依存する代わりに、新しいカスタムタイトルを設定するたびに、古いカスタムタイトルを単にhideすることができます。
2つのカスタムタイトルレイアウトがあるとします。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout Android:id="@+id/custom_title_1" ...
そして
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout Android:id="@+id/custom_title_2" ...
custom_title_1
をcustom_title_2
に置き換えたい場合は、前者を非表示にし、setFeatureInt
を使用して後者を追加できます。
findViewById(R.id.custom_title_1).setVisibility(View.GONE);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_2);
これを行う正しい方法は次のとおりです。
requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView( R.layout.my_layout );
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.my_custom_title );
super.onCreate( savedInstanceState );
これらのステートメントの順序は非常に重要であることに注意してください。
他のステートメントの前にsuper.onCreate()を呼び出すと、空白のタイトルバーが表示されます。タイトルバーIDを見つけてそこからすべてのビューを削除するハックは修正されますが、お勧めできません。
ちょうど私の2cの価値:
MapActivityで作業しているときに、カスタムタイトルをリクエストすると、タイトルがまったく表示されませんでした。
幸い、私がやりたかったのは、タイトルテキストを別の方法で設定することだけでしたが、すぐに、onCreate()内でsetTitle()を呼び出すだけでうまくいくことに気付きました(setContentView()を呼び出した後に呼び出しました)。
申し訳ありませんが、今これをデバッグして、なぜ私がやっていたことがうまくいかなかったのか、なぜそれを変更するとうまくいったのかを理解する時間はありません。私が言ったように、これは将来誰かを助けるかもしれないと思っただけです。
テキストを更新した後、ビューを再描画するためにinvalidateまたはpostInvalidateを呼び出していますか?カスタムビューの場合、描画コードにブレークポイントを設定して、それが確実に呼び出されるようにできますか?
UIスレッドを使用している場合は、 'invalidate'を呼び出すことができます。そうでない場合は、 'postInvalidate'を呼び出す必要があります。そうしないと、ビューが再描画されません。