2013-06-26 74 views
0

我目前正在开发一款游戏,在实施Google Play游戏服务后,我发现自己需要动态选项菜单。我的整个游戏包含strings.xml和6个活动(不包括导入的库项目)。我只提到这一点,因为这意味着我在不使用layout.xml的情况下构建选项菜单。动态选项菜单使用invalidateOptionsMenu()

我想要完成的是根据用户登录状态更改我的登录和登出按钮的可见状态。目前,当用户登录菜单时自己正确更新,登录按钮被登出取代。但是,当单击注销按钮时,它会正确地将用户签出,但不会触发菜单更新。试图通过按钮再次退出会导致应用程序崩溃,因为我没有捕捉到异常,我稍后可以处理。如果您更改“活动”,菜单会正确更新。

到目前为止我有什么看起来非常相似,我发现here

这是我的扩展,它每隔类扩展到利用我的整个游戏常用的方法课,我已经剥离的项目无关菜单。

package com.domain.myapp; 

import android.annotation.SuppressLint; 
import android.content.Intent; 
import android.os.Build; 
import android.view.Menu; 
import android.view.MenuItem; 

public abstract class Extensions extends LicenseCheck { 
    private static final int SOM1= 1; 
    private static final int SOM2= 2; 
    private static final int SOM3= 3; 
    private static final int SOM4= 4; 
    private static final int SOM5= 5; 
    private static final int SOM6= 6; 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     if (Build.VERSION.SDK_INT >= 11) { 
      buildMenu(menu); 
     } 
     return true; 
    } 

    @Override 
    public boolean onPrepareOptionsMenu(Menu menu) { 
     if (Build.VERSION.SDK_INT < 11) { 
      buildMenu(menu); 
     } 
     return true; 
    } 

    private void buildMenu(Menu menu) { 
     menu.clear(); 
     menu.add(Menu.NONE, SOM1, Menu.NONE, "Instructions"); 
     menu.add(Menu.NONE, SOM2, Menu.NONE, "View Achievements"); 
     menu.add(Menu.NONE, SOM3, Menu.NONE, "View Leaderboard"); 
     menu.add(Menu.NONE, SOM4, Menu.NONE, "Sign In"); 
     menu.add(Menu.NONE, SOM5, Menu.NONE, "Sign Out"); 
     menu.add(Menu.NONE, SOM6, Menu.NONE, "Exit Game"); 
     if (isSignedIn()) { 
      menu.findItem(SOM4).setVisible(false); 
      menu.findItem(SOM5).setVisible(true); 
     } 
     if (!isSignedIn()) { 
       menu.findItem(SOM4).setVisible(true); 
       menu.findItem(SOM5).setVisible(false); 
     } 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
     case SOM1: 
      Intent nextInstructionScreen = new Intent(getApplicationContext(), InstructionScreen.class); 
      startActivity(nextInstructionScreen); 
      break; 
     case SOM2: 
      viewAchievements(); 
      break; 
     case SOM3: 
      viewLeaderboards(); 
      break; 
     case SOM4: 
      beginUserInitiatedSignIn(); 
      break; 
     case SOM5: 
      getGamesClient().signOut(); 
      menuRefresh(); 
      break; 
     case SOM6: 
      moveTaskToBack(true); 
      break; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    @SuppressLint("NewApi") 
    public void menuRefresh() { 
     if (Build.VERSION.SDK_INT >= 11) { 
      invalidateOptionsMenu(); 
     } 
    } 
} 

此外,我花了一些时间尝试使用onSignOutComplete(),但必须已经这样做是错误的。任何帮助将不胜感激。使用布尔值来跟踪登录状态也不会改变行为。我找不出为什么注销按钮在用于注销并使“登录”按钮可见时为何不会隐藏,而相反的功能工作正常。

回答

0

就个人而言,我坚持只使用onCreateOptionsMenu()并删除onPrepareOptionsMenu()方法。

onPrepareOptionsMenu()在每次显示菜单时被调用,而onCreateOptionsMenu()仅在最初创建菜单时以及手动调用invalidateOptionsMenu()时被调用。

此外,不是先添加两个菜单项然后删除/隐藏其中一个,我只是检查用户是否登录,然后添加相应的菜单。除此之外,虽然它确实与您的问题无关,但您应该使用字符串资源,而不是硬编码菜单项标题。检查您的res/values/strings.xml文件,然后在您的Java代码中使用getString(R.string.id_of_string)从那里获取字符串。

PS。我猜你的LicenseCheck课程延伸到Activity

+0

IIRC为3.0蜂巢(API 11)选项菜单始终是敞开的,一旦创建,所以onPrepareOptionsMenu()不会更新它,除非你先调用invalidateOptionsMenu()的 - 也是,我之所以同时添加,然后隐藏一个或其他则是让用户可以随意登录或退出我的应用程序。有时你不希望意外分享成就或分数来放弃你在游戏中花费的时间。当我的用户退出后,他们不再能够分享分数或提交给排行榜,并且在他们的下一次登录时将被授予成就。 – DRW

+0

要回答您的最后一个问题,我的类的继承链(对于我的MainActivity和其他三个在我的游戏中未命名的类)是MainActivity => Extensions => LicenseCheck => BaseGameActivity – DRW

+0

是的,onPrepareOptionsMenu()在您使选项菜单无效时调用,但onCreateOptionsMenu()也是如此。你只需要onCreateOptionsMenu(),所以删除另一个是安全的。 我仍然不明白为什么,因为我在问候的菜单项建议你可以这样做。只需在您的onCreateOptionsMenu()检查,每需要从“登录”到“退出”更改时间无效菜单。 –