setSupportActionBarについてちょっとハマったのでメモします
動的にタイトルを変えたいときに以下だと反映できません。
NG
setSupportActionBar(toolbar)
toolbar.setTitle("test")
ただ以下だと大丈夫です。
OK
toolbar.setTitle("test")
setSupportActionBar(toolbar)
OK
setSupportActionBar(toolbar)
supportActionBar?.setTitle("test")
なぜ?
setSupportActionBar()でToolbarWidgetWrapperがnewされます。
そのタイミングで以下のようにタイトルがあればmTitleSetがtrueになります。
あとからセットするため、最初はmTitleSetはfalseになります。このフラグが後から効いてきます。
public ToolbarWidgetWrapper(Toolbar toolbar, boolean style,
int defaultNavigationContentDescription, int defaultNavigationIcon) {
mToolbar = toolbar;
mTitle = toolbar.getTitle();
...
mTitleSet = mTitle != null;
setSupportActionBar()を呼んだ後、onCreate内でtoolbarにタイトルをセットしていたとしてもActivity#onPostCreate()
から呼ばれる一連の流れで、toolbarのsetTitle()が呼ばれます。
〜一連の流れ〜
@CallSuper
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
if (!isChild()) {
mTitleReady = true;
onTitleChanged(getTitle(), getTitleColor());
}
mCalled = true;
}
@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
@Override
void onTitleChanged(CharSequence title) {
...
peekSupportActionBar().setWindowTitle(title);
...
}
ToobarWidgetWrapperで mTitleSetがfalseであればtoolbarへActivityのタイトルのセットがされます。
ToolbarのsetTitleではなくToobarWidgetWrapperのsetTitleを呼ぶことで、mTitleSetがtrueになるので、これを阻止できます。つまりgetSupportActionBar().setTitle("test")
であれば阻止できます。
@Override
public void setWindowTitle(CharSequence title) {
// "Real" title always trumps window title.
if (!mTitleSet) {
setTitleInt(title);
}
}
...
@Override
public void setTitle(CharSequence title) {
mTitleSet = true;
setTitleInt(title);
}
private void setTitleInt(CharSequence title) {
mTitle = title;
if ((mDisplayOpts & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
mToolbar.setTitle(title);
}
}