Как установить активный элемент в раскрывающемся меню панели действий?

Я пытаюсь решить проблему с перезапуском активности при изменении ориентации.

У меня есть ActionBar с навигацией по выпадающему списку, и после каждого поворота активируется первый элемент этого списка. Сохранение содержимого fragment было несложным, но я не знаю, как установить активный элемент списка.

Вот определение ActionBar:

getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
ArrayAdapter<CharSequence> list = ArrayAdapter
    .createFromResource(this, R.array.action_list, android.R.layout.simple_dropdown_item_1line);
list.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
getActionBar().setListNavigationCallbacks(list, this);

И вот мой обходной путь:

@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
    if (!application.isRotated) {
        application.activePosition = itemPosition;
        application.activeId = itemId;
        getFragmentManager().beginTransaction()
            .replace(android.R.id.content, MyFragment.newInstance(itemPosition))
            .commit();
    } else {
        application.isRotated = false;
        this.onNavigationItemSelected(application.activePosition, application.activeId);            
    }
    return true;
}

@Override
protected void onStop() {
    super.onStop();
    application.isRotated = true;
}

Хотя я не уверен, что это лучшее решение.


person Roman    schedule 27.01.2012    source источник


Ответы (5)


Я только что нашел эту функцию. Это setSelectedNavigationItem(int position).

Установите выбранный элемент навигации в списке или в режимах навигации с вкладками.

Пример:

actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setListNavigationCallbacks(adapter, this);
actionBar.setSelectedNavigationItem(position);
person Community    schedule 28.01.2012
comment
Не могли бы вы опубликовать пример того, как вы заставили это работать? Я пробовал что-то вроде getActionBar().setSelectedNavigationItem(1), но это не дало никакого эффекта.. (Кто-то еще с такой же проблемой здесь: stackoverflow.com/questions/8487425/) - person brk3; 11.02.2012
comment
Конечно, обновил мой ответ. Кроме того, вы можете взглянуть на исходный код моего приложения, чтобы увидеть, как я его использую. github.com/Tsukanov/ Simple-Counter/blob/master/src/me/tsukanov/ - person Roman; 11.02.2012
comment
Спасибо, это работает! Я предполагаю, что я, должно быть, делал неправильно, вызывая setSelectedNavigationItem перед добавлением адаптера. Я был уверен, что пробовал это раньше, но да ладно, теперь работает :) - person brk3; 11.02.2012
comment
Извини за это. Этот должен работать даже после внесения каких-либо изменений. - person Roman; 01.02.2013

Что касается библиотеки поддержки v7, вам просто нужно сохранить/восстановить состояние панели действий:

private static final String STATE_SELECTED_NAVIGATION_ITEM = "selectedNavItem";

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Restore the previously serialized current dropdown position.
    if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
        getSupportActionBar().setSelectedNavigationItem(
                savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    // Serialize the current dropdown position.
    outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getSupportActionBar()
            .getSelectedNavigationIndex());
}
person David Chandler    schedule 04.04.2014

Я также столкнулся с той же проблемой. Проведя много исследований, я нашел решение здесь:

http://mohitum.wordpress.com/tutorials/android/ -->под советом 5 .

Реализуйте OnPageChangeListener и в onPageSelected(int position) вызовите этот метод следующим образом:

@Override
public void onPageSelected(int position) {
  mActionBar.setSelectedNavigationItem(position);
  selectInSpinnerIfPresent(position, true);
}
private void selectInSpinnerIfPresent(int position, boolean animate) {
  try {
    ActionBar actionBarView = mActionBar;
    Class<?> actionBarViewClass = actionBarView.getClass();
    Field mTabScrollViewField = actionBarViewClass.getDeclaredField(“mTabScrollView”);
    mTabScrollViewField.setAccessible(true);
    Object mTabScrollView = mTabScrollViewField.get(actionBarView);
    if (mTabScrollView == null) {
      return;
    }
    Field mTabSpinnerField = mTabScrollView.getClass().getDeclaredField(“mTabSpinner”);
    mTabSpinnerField.setAccessible(true);
    Object mTabSpinner = mTabSpinnerField.get(mTabScrollView);
    if (mTabSpinner == null) {
      return;
    }
    Method setSelectionMethod = mTabSpinner.getClass().getSuperclass().getDeclaredMethod(“setSelection”, Integer.TYPE, Boolean.TYPE);
    setSelectionMethod.invoke(mTabSpinner, position, animate);
    Method requestLayoutMethod = mTabSpinner.getClass().getSuperclass().getDeclaredMethod(“requestLayout”);
    requestLayoutMethod.invoke(mTabSpinner);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

Я надеюсь, что это может помочь кому-то еще.

person mohitum    schedule 02.04.2013

Фрагмент кода в Gist


@Override
public void onPageScrollStateChanged(int state) {
}


@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}


@Override
public void onPageSelected(int position) {
    actionBar.setSelectedNavigationItem(position);

    selectInSpinnerIfPresent(position, true);
}


/**
 * Hack that takes advantage of interface parity between ActionBarSherlock and the native interface to reach inside
 * the classes to manually select the appropriate tab spinner position if the overflow tab spinner is showing.
 * 
 * Related issues: https://github.com/JakeWharton/ActionBarSherlock/issues/240 and
 * https://android-review.googlesource.com/#/c/32492/
 * 
 * @author [email protected]
 */
private void selectInSpinnerIfPresent(int position, boolean animate) {
    try {
        View actionBarView = findViewById(R.id.abs__action_bar);
        if (actionBarView == null) {
            int id = getResources().getIdentifier("action_bar", "id", "android");
            actionBarView = findViewById(id);
        }

        Class<?> actionBarViewClass = actionBarView.getClass();
        Field mTabScrollViewField = actionBarViewClass.getDeclaredField("mTabScrollView");
        mTabScrollViewField.setAccessible(true);

        Object mTabScrollView = mTabScrollViewField.get(actionBarView);
        if (mTabScrollView == null) {
            return;
        }

        Field mTabSpinnerField = mTabScrollView.getClass().getDeclaredField("mTabSpinner");
        mTabSpinnerField.setAccessible(true);

        Object mTabSpinner = mTabSpinnerField.get(mTabScrollView);
        if (mTabSpinner == null) {
            return;
        }

        Method setSelectionMethod = mTabSpinner.getClass().getSuperclass().getDeclaredMethod("setSelection", Integer.TYPE, Boolean.TYPE);
        setSelectionMethod.invoke(mTabSpinner, position, animate);

        Method requestLayoutMethod = mTabSpinner.getClass().getSuperclass().getDeclaredMethod("requestLayout");
        requestLayoutMethod.invoke(mTabSpinner);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

этот хак вокруг официальной ошибки Android сделал это для меня, код выше не сделал :/

person martyglaubitz    schedule 21.04.2013

Эта реализация работает для меня (измененная версия ответа @mohitum007):

public static void selectInSpinnerIfPresent(Object inActionBar,
        int position, boolean animate) {
    // get the ActionBar class
    Class<?> actionBarClass = inActionBar.getClass();

    // if it is a Jelly Bean implementation (ActionBarImplJB), get the super
    // class (ActionBarImplICS)
    if ("android.support.v7.app.ActionBarImplJB".equals(actionBarClass
            .getName())) {
        actionBarClass = actionBarClass.getSuperclass();
    }
    try {
        // try to get the mActionBar field, because the current ActionBar is
        // probably just a wrapper Class
        // if this fails, no worries, this will be an instance of the native
        // ActionBar class or from the ActionBarImplBase class
        final Field actionBarField = actionBarClass
                .getDeclaredField("mActionBar");
        actionBarField.setAccessible(true);
        inActionBar = actionBarField.get(inActionBar);
        actionBarClass = inActionBar.getClass();
    } catch (IllegalAccessException e) {
    } catch (IllegalArgumentException e) {
    } catch (NoSuchFieldException e) {
    }
    try {
        Field mTabScrollViewField = actionBarClass
                .getDeclaredField("mTabScrollView");
        mTabScrollViewField.setAccessible(true);
        Object mTabScrollView = mTabScrollViewField.get(inActionBar);
        if (mTabScrollView == null) {
            return;
        }
        Field mTabSpinnerField = mTabScrollView.getClass()
                .getDeclaredField("mTabSpinner");
        mTabSpinnerField.setAccessible(true);
        Object mTabSpinner = mTabSpinnerField.get(mTabScrollView);
        if (mTabSpinner == null) {
            return;
        }
        Method setSelectionMethod = mTabSpinner
                .getClass()
                .getSuperclass()
                .getDeclaredMethod("setSelection", Integer.TYPE,
                        Boolean.TYPE);
        setSelectionMethod.invoke(mTabSpinner, position, animate);
        Method requestLayoutMethod = mTabSpinner.getClass().getSuperclass()
                .getDeclaredMethod("requestLayout");
        requestLayoutMethod.invoke(mTabSpinner);
    } catch (NoSuchMethodException | InvocationTargetException
            | IllegalAccessException | IllegalArgumentException | NoSuchFieldException e) {
    }
}
person Kyle Jahnke    schedule 15.09.2014