私のアプリには、DrawerLayout
とNavigationView
(android.support.design.widget.NavigationView) を使用した 2 つのアクティビティがあります。
親Theme.AppCompat.Light.DarkActionBar
でアプリのテーマを使用していますが、Lollipop エミュレーターでは問題ありません。
しかし、私の Jellybean デバイスとエミュレーターでは、非常に奇妙な動作をします。
アイテムの背景は、NavigationView
明るい灰色 (私には問題ありません) でレンダリングされることもあれば、明るい青色の色合いでレンダリングされることもあります (テーマ ホロのデフォルトだと思います)。
私の「実際の」アプリでは、灰色の色合いは常に最初の引き出しに表示され、青い色合いは常に他の引き出しに表示されます。最初は違いは、最初のものは anActionBarDrawerToggle
を使用し、他のものは使用しないなどの詳細が原因である可能性があると考えていたので、何らかの方法でandroid:listSelector
を 2 番目のもののみに設定する必要があったのかもしれません。
そこで、MCVE のようなサンプルを作成したところ、両方の引き出しが時々両方の色合いを示していることに気付きました。これはバグですか、それとも何か不足していますか?
Theme Holo を取り除くにはどうすればよいですか?
スクリーンショット:
ところで、私はActionButton
背景に対して同じランダムな振る舞いをしています:
私のコード(独自のテストを実行したい人のための〜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
アイテムの独自の背景を設定することも試みました。背景が変更されましたが、タッチすると、ロリポップ以上のリップルが表示されます (これは問題ありません)。残念ながら、おそらく操作方法がわからないある種のリストセレクターから、ジェリービーンに交互の効果が得られます。
更新 2 (2016 年 9 月)
Android Studio の新しいバージョンをインストールし、最新バージョンのビルド ツールとすべてのライブラリ (それぞれ 24.0.2 24.2.0) を使用ActionBar
し、Toolbar
. 最後の手段は、メインでハックを使用してナビゲーション ドロワーをカバーする必要がないことを意味するためActionBar
、コードで LayoutInflater を使用しなくなりました。
しかし、まだ運がありません:(
これはバグであると確信しています。同じコードがアプリの実行ごとに異なる動作をし、同じ実行中に Main アクティビティと Other アクティビティの間で一貫性がありません。