2

タブ ナビゲーションとアクション モードを使用すると、ActionBarSherlock に奇妙な問題が発生します。

問題を繰り返すのは非常に簡単です。デモ コードを使用して、次のサンプル アクティビティを生成します。

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;

public class MainActivity extends SherlockFragmentActivity implements ActionBar.TabListener {
    private ActionMode actionMode = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setTheme(com.actionbarsherlock.R.style.Theme_Sherlock);
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        for (int i = 1; i <= 2; i++) {
            ActionBar.Tab tab = getSupportActionBar().newTab();
            tab.setText("Tab " + i);
            tab.setTabListener(this);
            getSupportActionBar().addTab(tab);
        }

        actionMode = startActionMode(new TestActionMode());
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub
    }


    private final class TestActionMode implements ActionMode.Callback {

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            menu.add("Add").setIcon(android.R.drawable.ic_input_add).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            menu.add("Search").setIcon(android.R.drawable.ic_search_category_default).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            // TODO Auto-generated method stub

        }

    }

}

Android 4.0 (実際のデバイスとエミュレーターでテスト済み) では正しく動作しますが、Jelly Bean (エミュレーターでのみテスト済み) では次のような動作をします。

  • アプリケーションを起動 (ポートレート モード) すると、正しく動作します。
  • アプリケーションをローテーションすると正しく動作します。
  • アプリケーションを再度回転すると、タブ ナビゲーションと ActionMode が重なっています ( http://i.stack.imgur.com/Zf1VG.png )。

場合によっては (まれに)、すべてが完全に機能することがあります。特に、Dev ですべてのアニメーションを有効にしている場合はそうです。設定(通常、すべてのアニメーションを無効にします)。

私は ActionBarSherlock 4.4 を使用しています。

どこで間違いを犯したのか本当にわからないので、どんな提案でも大歓迎です。

ありがとうございます。

4

1 に答える 1

1

I recently came across to the same issue. After wasting few days on it, found out that this weird behavior is caused by UX flaw described in this issue and, in fact, has nothing to do with ABS (action bar sherlock).

The most reliable workaround seems to be using reflection to control how action bar should be rendered:

/**
 * On Android 3.0 and above, while using the ActionBar tabbed navigation style, the tabs sometimes appear above the action bar.
 * This helper method allows you to control the 'hasEmbeddedTabs' behaviour.
 * A value of true will put the tabs inside the ActionBar, a value of false will put it above or below the ActionBar.
 *
 * You should call this method while initialising your ActionBar tabs.
 * Don't forget to also call this method during orientation changes (in the onConfigurationChanged() method).
 *
 * @param inActionBar
 * @param inHasEmbeddedTabs
 */
public static void setHasEmbeddedTabs(Object inActionBar, final boolean inHasEmbeddedTabs)
{
        // 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
        {
                // now call the method setHasEmbeddedTabs, this will put the tabs inside the ActionBar
                // if this fails, you're on you own <img src="http://www.blogc.at/wp-includes/images/smilies/icon_wink.gif" alt=";-)" class="wp-smiley"> 
                final Method method = actionBarClass.getDeclaredMethod("setHasEmbeddedTabs", new Class[] { Boolean.TYPE });
                method.setAccessible(true);
                method.invoke(inActionBar, new Object[]{ inHasEmbeddedTabs });
        }
        catch (NoSuchMethodException e)        {}
        catch (InvocationTargetException e) {}
        catch (IllegalAccessException e) {}
        catch (IllegalArgumentException e) {}
}

The above code was taken from this blog post.

于 2014-03-11T13:30:51.077 に答える