安卓操作栏 onNavigationItemSelected

13
我正在开发适用于Android 3+的应用程序。
在我的操作栏中,我有一个下拉列表(请参见如何在Android 3上隐藏/显示操作栏列表?以获取我打算使用的下拉列表)。问题是,当用户选择某个选项时,我需要执行某个特定的操作,但Android在绘制视图时立即调用onNavigationItemSelected(),因此实际上没有进行任何选择。
如何检测用户是否实际按下了某个按钮,而不是来自Android的伪造调用?
public class ListDittaListener implements OnNavigationListener{

    private BaseActivity activity;

    private ListDittaListener()
    {

    }

    public ListDittaListener(BaseActivity activity)
    {
        this.activity = activity;
    }

    @Override
    public boolean onNavigationItemSelected(int itemPosition, long itemId)
    {
        MyApp appState = ((MyApp)this.activity.getApplicationContext());
        appState.setDittaSelezionata( (int) itemId);

        SharedPreferences settings = this.activity.getSharedPreferences(MyApp.PREFS_NAME, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt("ditta_id_selezionata", (int) itemId);

            ////////restart activity this.activity.recreate();

        return false;
    }

}
5个回答

16

如果你愿意,可以轻松地忽略对 onNavigationItemSelected 的第一次调用:

public class Whatever implements OnNavigationListener {
    private boolean synthetic = true;

    @Override
    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
        if (synthetic) {
            synthetic = false;
            return true;
        }

        // do whatever you really wanted here 
    }
}

1
谢谢,但正如我在悬赏描述中写的,“我想避免使用计数器并忽略第一次调用”,这似乎更像是一个hack,我想了解为什么首先会发生这种情况。 - max4ever
3
我有同样的问题,用这种方式来处理非常让人烦恼。这种行为是否有特定的目的? - Michał Klimczak
我使用了这个解决方案来防止屏幕方向改变时片段被不必要地重新创建两次并丢失它们的状态。点击这里查看详情。 - XåpplI'-I0llwlg'I -
如果您忽略了第一个调用,当您在下拉菜单中选择项目时将不会有后续的调用。 - IgorGanapolsky
如果您忽略第一个调用,则不会有具有相同索引的第二个调用。 - Marcos Vasconcelos

4

无论如何,操作栏都会调用onNavigationItemSelected(int itemPosition, long itemId)方法。

你可能想要做的是告诉操作栏在第一次调用时应该传递哪个itemPosition给这个方法。(换句话说,告诉操作栏在活动创建后应该设置哪个导航项)。以下是代码:

mActionBarMenuSpinnerAdapter = ...;
mActionBar = getActionBar();
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
mActionBar.setListNavigationCallbacks(mActionBarMenuSpinnerAdapter, this);
mActionBar.setSelectedNavigationItem(###your_default_navigation_item_here###);

在这样做之后,您可以通过在onNavigationItemSelected(int itemPosition, long itemId)中应用更改来解决问题,但仅当itemPosition不同时才能这样做。


2
Android系统会在Activity设置完成后调用onNavigationItemSelected(0, 0)方法。这意味着该方法被调用的时机晚于onResume()方法。
正如其他人所建议的那样,最好不要忽略第一次调用,否则当你选择第一个索引时,Android系统将不会再次调用onNavigationItemSelected()方法(系统认为第一个项目已经被选中)。
我的解决方案是在设置actionbar之后调用actionbar.setSelectedNavigationItem(你想要的实际项号),然后系统将会调用onNavigationItemSelected()两次。首先调用onNavigationItemSelected(0, 0),然后调用onNavigationItemSelected(实际项号)。

起初您说最好不要忽略第一个调用,但是当 onNavigationItemSelected(0, 0) 被调用时该怎么办? - skywall

0
我有一个带有片段的ViewPager,我需要为Pager中的每个片段设置自定义操作栏。 在所需页面上,我有导航列表,当我滑动页面时,片段会自动触发onNavigationItemSelected事件,我想避免这种行为,并仅在手动选择导航项时运行任务。
public class MyFragment extends Fragment implements ActionBar.OnNavigationListener {

    private boolead fireReady = false;

     @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        // every time make it false, this method invoked on swipe action
        fireReady = false; 

        if (isVisibleToUser) {
            // setup actionbar, you also can setup action bar in activity
            String[] array = getActivity().getResources().getStringArray(R.array.users_order);
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, array);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

            getActivity().getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
            getActivity().getActionBar().setListNavigationCallbacks(adapter, this);
        }

    }

     @Override
    public boolean onNavigationItemSelected(int itemPosition, long itemId) {

        if (fireReady) {
            // task fire only when you directly press navigation item
            UsersTask task = new UsersTask(getActivity());
            task.setTaskListener(this);
            task.execute(usersUrls[itemPosition]);
        } else {
            // make it true first time when page displayed
            fireReady = true;
        }
        return false;
    }

}

}

0

我看不出你当前的代码有什么问题。

你是如何创建下拉菜单元素的?在视图创建后,Android 选择了哪个元素作为“select”?在 onCreate 方法中初始化 ActionBar 时,你在做什么?

我按照这里的说明操作,成功了: http://developer.android.com/guide/topics/ui/actionbar.html#Dropdown


在onCreate中,我通常只是调用与其他相关问题链接的代码(基本上只是action_bar.setNavigationMode和action_bar.setListNavigationCallbacks),它会“选择”下拉元素的第一项。 - max4ever
从你的角度来看,你做得一切都正确。你旋转了屏幕吗?我在这里找到了一个类似的问题:https://dev59.com/9mox5IYBdhLWcg3wr2Po - Moritz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接