0

我的应用程序有两个活动,一个DrawerLayout和一个NavigationView(android.support.design.widget.NavigationView)。

我使用带有 parent 的应用程序主题Theme.AppCompat.Light.DarkActionBar,对于我的 Lollipop 模拟器,没有问题。

但是对于我的 Jellybean 设备和模拟器,我有一个非常奇怪的行为:

项目的背景NavigationView有时呈现为浅灰色(这对我来说没问题),有时呈现为浅蓝色阴影(我认为这是 Theme Holo 的默认设置)。

对于我的“真实”应用程序,灰色总是出现在第一个抽屉上,而蓝色总是出现在另一个抽屉上。起初我认为差异可能是由于一些细节,比如第一个使用 anActionBarDrawerToggle而另一个没有,所以也许我不得不以某种方式android:listSelector只为第二个设置。

所以我创建了一个类似 MCVE 的示例,并注意到两个抽屉不时显示两种颜色。这是一个错误还是我错过了什么?

我该怎么做才能摆脱 Theme Holo?

截图:

主抽屉蓝色和灰色色调

顺便说一句,我对ActionButton背景有相同的随机行为:

MainActivity 蓝色和灰色操作按钮

我的代码(大约 95% 的代码适用于那些喜欢运行自己的测试的人):

activity_main.xml只是一个“空白活动”,中间有一个大的“Hello World”:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true">

    <TextView
        android:text="@string/hello_world"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>

activity_main_decor.xml

<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"/>

    <android.support.design.widget.NavigationView
        android:id="@+id/main_drawer"
        android:layout_width="@dimen/nav_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/menu_main_drawer"/>
</android.support.v4.widget.DrawerLayout>

activity_other.xml

<merge>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    <TextView
        android:text="Hello again!"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>
</merge>

activity_other_decor.xml

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout android:id="@+id/container"
             android:orientation="vertical"
             android:layout_width="fill_parent"
             android:layout_height="fill_parent">
        <include layout="@layout/activity_other"/>
    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/other_drawer"
        android:layout_width="@dimen/nav_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        app:menu="@menu/menu_other_drawer" />

</android.support.v4.widget.DrawerLayout>

MainActivity - 导航抽屉必须从左侧和上方出现ActionBar(顺便感谢@Peter Cai 提供了一些非常有用的行

public class MainActivity extends AppCompatActivity
{
private static final String             TAG = "StyleForDrawers main";
private static final String             DRAWER_OPEN = "main_drawer_open";

private DrawerLayout                    drawerLayout;
private NavigationView                  navigationView;
private ActionBarDrawerToggle           drawerToggle;
private boolean                         isDrawerOpen;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initNavDrawer();
}

private void initNavDrawer()
{
    final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(this);

    LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    drawerLayout = (DrawerLayout) inflater.inflate(R.layout.activity_main_decor, null);

    ViewGroup decor = (ViewGroup)activity.getWindow().getDecorView();
    View child = decor.getChildAt(0);
    decor.removeView(child);

    FrameLayout container = (FrameLayout)drawerLayout.findViewById(R.id.container);
    container.addView(child);
    decor.addView(drawerLayout);

    navigationView = (NavigationView) findViewById(R.id.main_drawer);
    navigationView.setItemTextColor(ContextCompat.getColorStateList(this, R.color.nav_item));
    navigationView.setItemTextAppearance(R.style.MyNavdrawerTextAppearance);
    View headerView = navigationView.inflateHeaderView(R.layout.navdrawer_list_header);

    // header View should appear below status bar, so set padding:
    (headerView.findViewById(R.id.nav_header_root)).setPadding(0, getStatusbarHeight(), 0, (int) getResources().getDimension(R.dimen.activity_vertical_margin));

    navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
    {
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem)
        {
            Intent intent = null;
            int id = menuItem.getItemId();

            if (id == R.id.action_other_activity)
            {
                intent = new Intent(MainActivity.this, OtherActivity.class);
            }
            // -- skipped some code for Help etc. --

            drawerLayout.closeDrawer(navigationView);
            isDrawerOpen = false;

            if (intent != null)
            {
                intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                startActivity(intent);
            }

            return true;
        }
    });

    drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.sDrawerOpen, R.string.sDrawerClose)
    {

        @Override
        public void onDrawerClosed(View drawerView)
        {
            super.onDrawerClosed(drawerView);
            sPrefs.edit().putBoolean(DRAWER_OPEN, false).apply();
        }

        @Override
        public void onDrawerOpened(View drawerView)
        {
            isDrawerOpen = true;
            super.onDrawerOpened(drawerView);
            sPrefs.edit().putBoolean(DRAWER_OPEN, true).apply();
        }
    };

    drawerLayout.setDrawerListener(drawerToggle);

    if (getSupportActionBar() != null)
    {
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.nav_drawer);
    }

    if (sPrefs.getBoolean(DRAWER_OPEN, true)) // open at first launch
    {
        drawerLayout.openDrawer(navigationView);
    }
    else
    {
        drawerLayout.closeDrawer(navigationView);
    }
}

@Override
protected void onPause()
{
    super.onPause();
    SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    sPrefs.edit().putBoolean(DRAWER_OPEN, isDrawerOpen).apply();
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    return drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}

public static int getStatusbarHeight()
{
    int retValue = 0;
    int resID = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resID > 0) {
        retValue = getResources().getDimensionPixelSize(resID);
    }
    return retValue;
}

}

OtherActivity - 抽屉就像一个上下文菜单,从右侧出现而不重叠ActionBar

public class OtherActivity extends AppCompatActivity
{
    private static final String             TAG = "StyleForDrawers other";
    private static final String             DRAWER_OPEN = "other_drawer_open";

    private DrawerLayout                    mDrawerLayout;
    private NavigationView                  mNavigationView;
    private boolean                         mIsDrawerOpen;


@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_other_decor);
    initMenuDrawer();
}

private void initMenuDrawer()
{
    final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(this);

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

    mNavigationView = (NavigationView) findViewById(R.id.other_drawer);
    mNavigationView.setItemTextColor(ContextCompat.getColorStateList(this, R.color.nav_item));
    mNavigationView.setItemTextAppearance(R.style.MyNavdrawerTextAppearance);

    mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
    {
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem)
        {
            int id = menuItem.getItemId();

            if (id == R.id.action_back_to_main)
            {
                finish();
            }
            // -- skipped some code for doing something (else) --
            mDrawerLayout.closeDrawer(mNavigationView);
            mIsDrawerOpen = false;
            return true;
        }
    });

    mDrawerLayout.setDrawerListener(new DrawerLayout.SimpleDrawerListener()
    {
        @Override
        public void onDrawerOpened(View drawerView)
        {
            super.onDrawerOpened(drawerView);
            mIsDrawerOpen = true;

            sPrefs.edit().putBoolean(DRAWER_OPEN, true).apply();
        }

        @Override
        public void onDrawerClosed(View drawerView)
        {
            super.onDrawerClosed(drawerView);
            mIsDrawerOpen = false;
            sPrefs.edit().putBoolean(DRAWER_OPEN, false).apply();
        }

    });

    if (sPrefs.getBoolean(DRAWER_OPEN, false)) // don't open at first launch
    {
        mDrawerLayout.openDrawer(mNavigationView);
    }
    else
    {
        mDrawerLayout.closeDrawer(mNavigationView);
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    getMenuInflater().inflate(R.menu.menu_other, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    int id = item.getItemId();

    if (id == R.id.action_opendrawer)
    {
        if (mIsDrawerOpen)
        {
            mDrawerLayout.closeDrawer(mNavigationView);
        }
        else
        {
            mDrawerLayout.openDrawer(mNavigationView);
        }
        return true;
    }
    return super.onOptionsItemSelected(item);
}
}

menu_main.xml不必要

menu_other.xml包含一个用于打开/关闭抽屉的操作按钮:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">

  <item android:id="@+id/action_opendrawer"
      android:title="open/close drawer"
      android:icon="@drawable/nav_drawer"
      android:orderInCategory="100"
      app:showAsAction="always"/>
</menu>

样式.xml

<resources>
    <color name="accent_orange">#ff6d00</color>
    <color name="my_background">#eeeeee</color>
    <color name="my_text">#311b92</color>
    <color name="my_sec_text">#B1311b92</color>
    <color name="my_actionbar">#1a237e</color>
    <color name="my_statusbar">#1a237e</color>

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

    <item name="colorPrimary">@color/my_actionbar</item>
    <item name="colorPrimaryDark">@color/my_statusbar</item>
    <item name="colorAccent">#ffc400</item>
    <item name="android:windowBackground">@color/my_background</item>
    <item name="android:textColorPrimary">@color/my_text</item>
    <item name="android:textColor">@color/my_text</item>
    <item name="android:textColorSecondary">@color/my_sec_text</item>
</style>

<style name="MyNavdrawerTextAppearance" parent="TextAppearance.AppCompat.Small">
    <item name="android:textStyle">bold</item>
</style>
</resources>

更新(2016 年 5 月)

同时,我也尝试为这些NavigationView项目设置自己的背景。背景发生了变化,但在触摸时,我仍然会得到 Lollipop 和更高版本的涟漪(没关系),不幸的是,Jellybean 上的交替效果仍然存在,可能来自某种我不知道如何操作的列表选择器。

更新 2(2016 年 9 月)

我安装了新版本的 Android Studio,正在使用最新版本的构建工具和所有库(分别为 24.0.2 和 24.2.0),甚至放弃ActionBarToolbar. 最后一点意味着我不必在 Main 中使用 hack 来让导航抽屉覆盖 . ActionBar,因此我不再在代码中使用 LayoutInflater。

但仍然没有运气:(

我很确定这一个错误:相同的代码从一个应用程序运行到下一个应用程序的行为不同,并且在同一次运行期间活动 MainOther 之间的不一致。

4

0 回答 0