Android-実行時にカスタムタイトルビューを変更する
-
03-07-2019 - |
質問
アクティビティごとにアプリケーションでカスタムタイトルビューを使用しています。アクティビティの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
)は、 setFeatureInt
メソッドの LayoutInflater
で、 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開発者にこれを説明します;)
編集
コメントで指摘されているように、前述の回避策は理想的ではありません。 com.android.internal.R.id.title_container
定数に依存する代わりに、新しいカスタムタイトルを設定するたびに古いカスタムタイトルを単に非表示にすることができます。
2つのカスタムタイトルレイアウトがあるとします:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/custom_title_1" ...
and
<?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を見つけてそこからすべてのビューを削除するハックは修正されますが、推奨されません。
テキストの更新後、ビューを再描画するためにinvalidateまたはpostInvalidateを呼び出していますか?カスタムビューの場合、描画コードにブレークポイントを設定して、呼び出されることを確認できますか?
UIスレッドを使用している場合、そうでない場合は「invalidate」を呼び出すことができます。「postInvalidate」を呼び出す必要があります。そうしないと、ビューが再描画されません。
ちょうど私の2cの価値:
MapActivityで作業しているときに、カスタムタイトルを要求すると、タイトルがまったく表示されませんでした。
幸いなことに、私がしたかったのはタイトルテキストを別の方法で設定することだけでした。 >
申し訳ありませんが、今これをデバッグする時間がないので、何をしていたのがうまくいかなかったのか、なぜそれを変更してうまくいったのかを理解します。私が言ったように、これは誰かが道を行くのを助けるかもしれないと思っただけです。