Android 如何在操作栏下拉导航中设置活动项?

Android 如何在操作栏下拉导航中设置活动项?,android,android-actionbar,android-spinner,Android,Android Actionbar,Android Spinner,我正试图通过在方向更改时重新启动活动来解决此问题 我有一个带有下拉列表导航的ActionBar,每次旋转后,该列表的第一个元素都会被激活。保留fragment内容并不困难,但我不知道如何设置活动列表项 以下是ActionBar的定义: getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); ArrayAdapter<CharSequence> list = ArrayAdapter .createFr

我正试图通过在方向更改时重新启动活动来解决此问题

我有一个带有下拉列表导航的
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);

我不确定这是不是最好的解决方案。

我刚刚找到了这个函数。是的

在列表或选项卡式导航模式中设置选定的导航项

例如:

actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setListNavigationCallbacks(adapter, this);
actionBar.setSelectedNavigationItem(position);

我也遇到了同样的问题。通过大量研究,我在这里找到了解决方案:

-->在提示5下

实现OnPageChangeListener,并在onPageSelected(int位置)中如下调用此方法:

@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();
    }
  }
@覆盖
已选择页面上的公共无效(内部位置){
mActionBar.setSelectedNavigationItem(位置);
选择pinnerifpresent(位置,true);
}
私有void selectInSpinnerIfPresent(整型位置,布尔动画){
试一试{
ActionBar actionBarView=mActionBar;
类actionBarViewClass=actionBarView.getClass();
字段mTabScrollViewField=actionBarViewClass.getDeclaredField(“mTabScrollView”);
mTabScrollViewField.setAccessible(true);
对象mTabScrollView=mTabScrollViewField.get(actionBarView);
如果(mTabScrollView==null){
返回;
}
字段mTabSpinnerField=mTabScrollView.getClass().getDeclaredField(“mTabSpinnerField”);
MTAbsp InnerField.setAccessible(true);
对象MTABSSInner=MTABSSInnerField.get(mTabScrollView);
如果(MTABSSINERN==null){
返回;
}
方法setSelectionMethod=MTABPSInner.getClass().getSuperclass().getDeclaredMethod(“setSelection”,Integer.TYPE,Boolean.TYPE);
setSelectionMethod.invoke(MTABsp内部、位置、动画);
方法requestLayoutMethod=MTABPSInner.getClass().getSuperclass().getDeclaredMethod(“requestLayout”);
requestLayoutMethod.invoke(MTABSSInner);
}捕获(例外e){
e、 printStackTrace();
}
}
我希望这也能帮助其他人。


@覆盖
公共无效onPageScrollStateChanged(int状态){
}
@凌驾
已滚动页面上的公共无效(int-position、float-positionOffset、int-positionOffsetPixels){
}
@凌驾
已选择页面上的公共无效(内部位置){
actionBar.setSelectedNavigationItem(位置);
选择pinnerifpresent(位置,true);
}
/**
*利用ActionBarSherlock和本机接口之间的接口奇偶性到达内部的黑客
*如果显示溢出选项卡微调器,则要手动选择适当选项卡微调器位置的类。
* 
*相关问题:https://github.com/JakeWharton/ActionBarSherlock/issues/240 和
* https://android-review.googlesource.com/#/c/32492/
* 
*@作者toulouse@crunchyroll.com
*/
私有void selectInSpinnerIfPresent(整型位置,布尔动画){
试一试{
视图操作栏视图=findViewById(R.id.abs\u操作栏);
if(actionBarView==null){
intid=getResources().getIdentifier(“操作栏”、“id”、“android”);
actionBarView=findViewById(id);
}
类actionBarViewClass=actionBarView.getClass();
字段mTabScrollViewField=actionBarViewClass.getDeclaredField(“mTabScrollView”);
mTabScrollViewField.setAccessible(true);
对象mTabScrollView=mTabScrollViewField.get(actionBarView);
如果(mTabScrollView==null){
返回;
}
字段mTabSpinnerField=mTabScrollView.getClass().getDeclaredField(“mTabSpinnerField”);
MTAbsp InnerField.setAccessible(true);
对象MTABSSInner=MTABSSInnerField.get(mTabScrollView);
如果(MTABSSINERN==null){
返回;
}
方法setSelectionMethod=MTABPSInner.getClass().getSuperclass().getDeclaredMethod(“setSelection”,Integer.TYPE,Boolean.TYPE);
setSelectionMethod.invoke(MTABsp内部、位置、动画);
方法requestLayoutMethod=MTABPSInner.getClass().getSuperclass().getDeclaredMethod(“requestLayout”);
requestLayoutMethod.invoke(MTABSSInner);
}捕获(IllegalArgumentException e){
e、 printStackTrace();
}捕获(非法访问例外e){
e、 printStackTrace();
}捕获(无此字段例外){
e、 printStackTrace();
}捕获(无此方法例外){
e、 printStackTrace();
}捕获(调用TargetException e){
e、 printStackTrace();
}
}


这个针对Android官方Bug的黑客攻击为我做到了,上面的代码片段没有://

从支持库v7开始,您只需要保存/恢复ActionBar的状态:

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());
}

这个实现对我有效(@mohitum007响应的修改版本):

publicstaticvoid选择pinnerifpresent(对象不活动栏,
int位置,布尔值(动画){
//获取ActionBar类
类actionBarClass=inActionBar.getClass();
//如果它是一个Jelly Bean实现(ActionBarImplJB),请获取超级
//类(ActionBarImplICS)
if(“android.support.v7.app.ActionBarImplJB”。等于(actionBarClass
.getName()){
actionBarClass=actionBarClass.getSuperclass();
}
试一试{
//尝试获取mActionBar字段,因为当前的ActionBar是
//可能只是一个包装类
//如果失败了,不用担心,这将是本机的一个实例
//ActionBar类或来自ActionBarImplBase类
最终字段actionBarField=actionBarClass
.getDeclaredField(“mActionBar”);
actionBarField.setAccessible(true);
inActionBar=actionBarField.get(inActionBar);
actionBarClass=inActionBar.getClass();
}捕获(非法访问例外e){
}捕获(IllegalArgumentException e){
}捕获(无此字段例外)
@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 toulouse@crunchyroll.com
 */
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();
    }
}
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());
}
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) {
    }
}