サポートライブラリのNavigation Drawerパターンを使用しています: http://developer.Android.com/training/implementing-navigation/nav-drawer.html
私はそれをタブレットで常に開くように設定しようとしていました(サイドメニューとして)
それは現在の実装で何か可能ですか、それとも同じコードを再利用する代わりにリストビューで新しいレイアウトと新しい構造を作成する必要がありますか?
より大きなデバイスが異なるレイアウトファイルを持つ可能性があるという考えに基づいて、次のプロジェクトを作成しました。
https://github.com/jiahaoliuliu/ABSherlockSlides
HighLights:
大きなデバイスの引き出しは常に見えるので、引き出しを用意する必要はありません。代わりに、同じ名前の2つの要素を持つLinearLayoutで十分です。
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="horizontal">
<ListView
Android:id="@+id/listview_drawer"
Android:layout_width="@dimen/drawer_size"
Android:layout_height="match_parent"
Android:layout_gravity="start"
Android:choiceMode="singleChoice"
Android:divider="@Android:color/transparent"
Android:dividerHeight="0dp"
Android:background="@color/drawer_background"/>
<FrameLayout
Android:id="@+id/content_frame"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_marginLeft="@dimen/drawer_content_padding"
/>
</LinearLayout>
レイアウトファイルに引き出しがないため、アプリがレイアウト内の要素を見つけようとすると、nullが返されます。そのため、使用しているレイアウトを確認するためにブール値を追加する必要はありません。
DrawerLayout mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
if (mDrawerLayout != null) {
// Set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// Enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// ActionBarDrawerToggle ties together the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
// Set the title on the action when drawer open
getSupportActionBar().setTitle(mDrawerTitle);
super.onDrawerOpened(drawerView);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
以下にブール値として使用する例を示します。
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
if (mDrawerLayout != null) {
mDrawerToggle.syncState();
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mDrawerLayout != null) {
// Pass any configuration change to the drawer toggles
mDrawerToggle.onConfigurationChanged(newConfig);
}
}
CommonsWareの答えに基づいて、いくつかの調整でこれを行うことができます。 1つ目は、次の3行を設定することです。
_drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
drawerLayout.setScrimColor(getResources().getColor(R.color.drawerNoShadow));
isDrawerLocked = true;
_
DrawnNoShadowの色は、アルファなしの色(0x00000000など)にすることができます。これにより、背景オーバーレイのない開いた引き出しが得られます。
次に行う必要があるのは、FrameLayoutのpadding_left値を調整することです。この目的のために、これを制御するディメンションを設定できます(デフォルトでは0dp)-この例ではR.dimen.drawerContentPaddingです。また、DrawerLayoutの幅になるR.dimen.drawerSize値も必要です。
これにより、FrameLayoutのpaddingLeft値を確認してこれらの行を呼び出すことができます。
_FrameLayout frameLayout = (FrameLayout)findViewById(R.id.content_frame);
if(frameLayout.getPaddingLeft() == (int)getResources().getDimension(R.dimen.drawerSize) {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
drawerLayout.setScrimColor(getResources().getColor(R.color.drawerNoShadow));
isDrawerLocked = true;
}
_
その後、有効にしたくないすべての機能をif(!isDrawerLocked)
ステートメントでラップできます。これには以下が含まれます。
drawerLayout.setDrawerListener(drawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
最後に、静的な引き出しを使用してビューの代替レイアウトをセットアップする必要があります。例は次のとおりです。
_<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.v4.widget.DrawerLayout
Android:id="@+id/drawer_layout"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<!-- The navigation drawer -->
<ListView
Android:id="@+id/left_drawer"
Android:layout_width="@dimen/drawerSize"
Android:layout_height="match_parent"
Android:layout_gravity="start"
Android:choiceMode="singleChoice"
Android:divider="@Android:color/transparent"
Android:dividerHeight="0dp"
Android:background="#111"/>
</Android.support.v4.widget.DrawerLayout>
<FrameLayout
Android:id="@+id/content_frame"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_marginLeft="@dimen/drawerContentPadding"/>
_
ここでの美しさは、ターゲットとするデバイスの代替dimen.xmlファイルを設定することですべてのロジックを制御でき、変更する必要があるのは、drawerContentPaddingの値と変更されたレイアウトを提供することだけです。
注:新しいレイアウトではドロワーにオーバーレイするため、padding_leftの代わりにmargin_leftを使用することになりました。 http://derekrwoods.com/2013/09/creating-a-static-navigation-drawer-in-Android/ で、このテクニックに関する詳細なブログ投稿を参照してください。
setDrawerLockMode()
を試して、大画面デバイスでドロワーを開いてロックします。
コメントで述べたように、DrawerLayout
はあなたのシナリオ用に設計されているとは思いません(悪い考えではありませんが、私見)。同じListView
とコンテンツをホストする別のレイアウトを使用するか、大画面のデバイスで、開いたときに重複するのではなくコンテンツをスライドさせるDrawerLayout
の独自のコピーをダウンロードして変更するそれ。
タブレット用の代替レイアウトファイルを提供するだけです。このようにして、NavigationView
のデフォルトの動作をすべて保存できます。
タブレットデバイス用にこれに似た代替レイアウトファイルを作成し、_layout-w600dp-land
_リソースディレクトリに配置します。
_<?xml version="1.0" encoding="utf-8"?>
<Android.support.v4.widget.DrawerLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools"
Android:id="@+id/drawer_layout"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true"
tools:openDrawer="start">
<!--
NavigationView and the content is placed in a horizontal LinearLayout
rather than as the direct children of DrawerLayout.
This makes the NavigationView always visible.
-->
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal">
<Android.support.design.widget.NavigationView
Android:id="@+id/nav"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer"/>
<include
layout="@layout/app_bar_main"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</LinearLayout>
</Android.support.v4.widget.DrawerLayout>
_
この手順では、引き出しの開閉がタブレット以外のデバイスでのみ機能するように、十分な変更を行います。
次のコンテンツをvaluesディレクトリの新しい値リソースファイルに追加し、_config_ui.xml
_という名前を付けます
_<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isDrawerFixed">false</bool>
</resources>
_
それは非タブレットデバイス用でした。タブレットデバイスの場合、同じ名前の別のデバイスを作成し、_values-w600dp-land
_に配置します。
_<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="isDrawerFixed">true</bool>
</resources>
_
引き出しが属するアクティビティのクラスに新しいフィールドを作成します
_private boolean isDrawerFixed;
_
そしてそれを次のように初期化しますisDrawerFixed = getResources().getBoolean(R.bool.isDrawerFixed);
。
これで、デバイスがif (isDrawerFixed){}
のような単純なテーブル型か非タブレット型かを確認できます。
このようなif
ステートメントでアクションバーのトグルボタンを設定するコードをラップします。
_if (!isDrawerFixed) {
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
}
_
このような別のif
ステートメントでアイテムがクリックされたときに引き出しを閉じるコードをラップします。
_if (!isDrawerFixed) {
drawer.closeDrawer(GravityCompat.START);
}
_
最終結果は、このようになります。
以前の回答は良いのですが、プロジェクトに実装するときにいくつかの問題に直面したため、ソリューションを共有したいと思います。まず、カスタムドロワーを定義する必要があります。
public class MyDrawerLayout extends DrawerLayout {
private boolean m_disallowIntercept;
public MyDrawerLayout (Context context) {
super(context);
}
@Override
public boolean onInterceptTouchEvent(final MotionEvent ev) {
// as the drawer intercepts all touches when it is opened
// we need this to let the content beneath the drawer to be touchable
return !m_disallowIntercept && super.onInterceptTouchEvent(ev);
}
@Override
public void setDrawerLockMode(int lockMode) {
super.setDrawerLockMode(lockMode);
// if the drawer is locked, then disallow interception
m_disallowIntercept = (lockMode == LOCK_MODE_LOCKED_OPEN);
}
}
次に、次のような基本的なアクティビティレイアウト(前の回答からの任意のレイアウトなし)に配置します。
<MyDrawerLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools"
Android:id="@+id/drawer_layout"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true"
tools:openDrawer="start">
<!--We must define left padding for content-->
<FrameLayout
Android:id="@+id/content_frame"
Android:paddingStart="@dimen/content_padding"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
<Android.support.design.widget.NavigationView
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:layout_gravity="start"
Android:fitsSystemWindows="true"
app:menu="@menu/menu_nav" />
</MyDrawerLayout>
ここでのコンテンツのパディングは、NavigationViewの場合、縦向きでは0dp、横向きでは約300dpです(経験的に設定)。適切なvalues
フォルダーでそれらを定義します。
values/dimens.xml
-
<dimen name="content_padding">0dp</dimen>
values-land/dimens.xml
-
<dimen name="content_padding">300dp</dimen>
最後に、アクティビティ内のドロワーをロックします。
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
mDrawerLayout.setScrimColor(0x00000000); // or Color.TRANSPARENT
isDrawerLocked = true;
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
mDrawerLayout.setScrimColor(0x99000000); // default shadow
isDrawerLocked = false;
}