【问题标题】:Toolbar (SupportActionBar) title changes to app name on orientation change工具栏 (SupportActionBar) 标题在方向更改时更改为应用程序名称
【发布时间】:2015-10-13 12:45:32
【问题描述】:

我的活动中有此代码:

protected void onCreate(Bundle savedInstanceState) {
    ...
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) {
      actionBar.setDisplayHomeAsUpEnabled(true);
    }
    ...
}

我正在从onResume() 中的各种片段更新 ActionBar 标题:

ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
    actionBar.setTitle(title);
}

这工作正常,但在方向更改后,标题再次更改为应用程序名称。我该如何克服这个问题?

编辑: 经过更多调查后,我尝试了这个并发现了这种奇怪的行为: 在我在 Fragments 中设置标题的地方添加了这段代码:

final ActionBar actionBar = ((AppCompatActivity)getActivity()).getSupportActionBar();
if (actionBar != null) {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d("SWAPNIL", "IN RUN BEFORE: " + actionBar.getTitle());
            actionBar.setTitle(title);
            Log.d("SWAPNIL", "IN RUN AFTER : " + actionBar.getTitle());
        }
    }, 3000);
}

这是日志:

10-13 10:27:04.526 3719-3719/com.example.xxxx D/SWAPNIL: onResumeHelp
10-13 10:27:07.528 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN BEFORE: MY APP NAME
10-13 10:27:07.528 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN AFTER : title
10-13 10:27:21.012 3719-3719/com.example.xxxx D/SWAPNIL: onResumeHelp
10-13 10:27:24.013 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN BEFORE: title
10-13 10:27:24.013 3719-3719/com.example.xxxx D/SWAPNIL: IN RUN AFTER : title

它已根据日志进行更改,但未反映在 UI 中。 请帮帮我!

【问题讨论】:

    标签: android android-fragments android-appcompat


    【解决方案1】:

    好吧,终于,在这个愚蠢的事情上花了 2 天后,我得到了解决方案(我想说的是解决方法)。

    这可能是一个嵌套的Fragment 错误。

    我有嵌套的片段结构。我们知道Fragment.getActivity() 返回父Activity。经过大量调试后,我观察到如果您在方向更改后调用getActivity()(即使在Fragment.onActivityCreated() 内部),它会返回旧Activity 的引用,但在最上面的父片段中它正确返回新创建的Activity

    所以我编写了这个方法来从任何Fragment 获取当前Activity

    /**
     * When inside a nested fragment and Activity gets recreated due to reasons like orientation
     * change, {@link android.support.v4.app.Fragment#getActivity()} returns old Activity but the top
     * level parent fragment's {@link android.support.v4.app.Fragment#getActivity()} returns current,
     * recreated Activity. Hence use this method in nested fragments instead of
     * android.support.v4.app.Fragment#getActivity()
     *
     * @param fragment
     *  The current nested Fragment
     *
     * @return current Activity that fragment is hosted in
     */
    public Activity getActivity(Fragment fragment) {
        if (fragment == null) {
            return null;
        }
        while (fragment.getParentFragment() != null) {
            fragment = fragment.getParentFragment();
        }
        return fragment.getActivity();
    }
    

    【讨论】:

    • 不确定我应该说做得好还是谢谢。这对每个 Android 开发者来说都是一个很好的教训。 Google 应该认真对待这些错误,而不是仅仅发布更多未完成的 Android 版本。
    • 将此标记为答案,因为它确实解决了问题。
    • @Sufian 谢谢 :) 当我有时间正确记录问题时,我肯定会在 Android 错误报告中提交此问题。
    • 你在哪里调用这个方法?
    • @LukeAllison 我有一个基础片段,我的所有片段都从该片段扩展。我在该基本片段中编写了上述方法,并在其他片段中调用它。所以我没有调用ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();,而是从所有片段中调用ActionBar actionBar = ((AppCompatActivity) getActivity(this)).getSupportActionBar();
    【解决方案2】:

    你需要在这里看到 sorianiv 写的答案: In android app Toolbar.setTitle method has no effect – application name is shown as title

    添加额外的toolbar.setTitle("") 为我解决了这个问题。

        Toolbar toolbar = (Toolbar) root.findViewById(R.id.toolbar);
        toolbar.setTitle("");
            ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
        toolbar.setTitle("Profiles");
    

    【讨论】:

    • 你提到的问题有点不同。我遇到了我发布的问题,因为当我在Fragment 内调用getActivity() 时,Android 正在返回我旧的Activity(旧的活动,因为方向变化等原因,活动被重新创建)。因此我的解决方案。
    • 您的解决方案肯定更完整,但我将这个链接传递给您,因为它解决了您遇到的确切症状,即您的工具栏在旋转后恢复为应用程序名称。这为我解决了这个问题。如果由于返回错误的活动而弹出更多问题,那么我将实施您的解决方案。
    • 这为我解决了类似的问题。我在AsyncTaskonPostExecute() 中调用setTitle()。看来您只需要在onCreate() 中调用setTitle("") 就可以使用getSupportActionBar().setTitle("..."); 进一步更改标题
    • 不需要调用此方法两次,只需使用一次getSupportActionBar().setTitle(),而不是引用工具栏视图,p.s.在 Kotlin 上是 supportActionBar?.title = "NAME"
    【解决方案3】:

    我刚刚遇到了同样的问题,我通过使用getSupportActionBar 而不是toolbar 解决了这个问题。

    getSupportActionBar().setTitle("...");
    

    【讨论】:

      【解决方案4】:

      旋转屏幕时会重新创建您的活动。所以 onCreate 又被调用了,你还没有在那里设置标题。

      将以下内容添加到您的 onCreate:

      actionBar.setTile("Enter title here")
      

      【讨论】:

      • 他在片段的onResume() 中设置标题。这很可能不起作用。
      • 是的,Fragment 的 onResume() 将在 Activity 的 onCreate() 之后被调用
      • 添加一些断点并进行调试,看看您的应用在轮换后经历了哪些步骤。然后你会知道你的 onResume() 是否被调用以及调用什么来改变你的操作栏标题
      • @RED_ 从我可以调试的地方,因为是系统将标题更改为应用程序名称。我所能做的就是检查是否在 Activity 的 onCreate() 发生后调用了 onResume()
      • @SwapnilBhoite 在片段和活动的不同方法中添加断点并转到 Run -> Debug 'myApp'(考虑到您使用的是 Android Studio)。如果您找到解决方案,请将其发布为答案,以便将来对某人有所帮助。 :)
      【解决方案5】:

      也许您可以在 Activity 的 onPostCreate() 方法中更改操作栏/工具栏。 代码很简单。我尝试多次更改我的模拟器/设备方向,它就像魅力一样..

      @Override
      protected void onPostCreate(Bundle savedInstanceState) {
          // TODO Auto-generated method stub
          super.onPostCreate(savedInstanceState);
          toolbar.setTitle(mTitle);
      }
      

      【讨论】:

        【解决方案6】:

        在清单文件中添加

        <activity
             android:name=".Activity"
             android:configChanges="orientation|screenSize|keyboardHidden"/>
        

        或 onConfigChange()中的代码

        if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
            // Set Title for Landscape
         }else{
           // Set Title for Portrait
        

        【讨论】:

        • Android documentation 说:“当您必须避免由于配置更改而重新启动时,这种技术应该被视为最后的手段,并且不建议用于大多数应用程序。”我认为这不是一个适当的解决方案,而是一种 hacky 方式。
        • 这种配置更改被推荐的太频繁了,而且永远不是解决方案。除非您希望在旋转后保持完全相同的布局,否则不要使用它。
        猜你喜欢
        • 1970-01-01
        • 2020-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多