我知道之前可能会问这个问题,但由于我没有找到任何令人信服的信息,我需要再次提问。
当您还需要提供某种排序导航面板(例如Navigation Drawer)时,如何设计支持平板电脑和手机的应用?
我想我知道如何使用导航抽屉与纵向方向的手机和平板电脑,因为在那些情况下我当时只显示一个窗格(片段)。但是由于你有足够的空间来展示至少两个窗格(片段),因此平板电脑在风景中是完全不同的,大部分时间都会以某种“主体 - 细节”方式相关联。
只是提供一些关于我的应用程序的上下文以及为什么我认为除导航列表之外还需要两个窗格。
我的应用程序的主要目标是帮助服务员接受订单,这种情况在以下情况发挥作用:
服务员从左侧菜单(理想情况下是导航抽屉)中选择“接订单”选项
在我称之为“内容部分”的第一部分(左侧窗格)中,服务员可以从他们所服务的所有食物类别中选择(假装它是顶部的列表)并根据选择的类别,下面的列表显示该特定类别下的所有菜肴。
一旦服务员点击一个盘子,它会自动添加到“内容部分”的第二部分(右侧窗格)
知道导航抽屉的基本结构与此相似:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
android:layout_width="240dp"
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>
您如何处理“面向横向的平板电脑”方案?您是否在多窗格布局中使用嵌套片段(在这种情况下可能需要使用)?(听起来非常复杂)您是否使用自定义库?你知道在Git中实现这个的任何开源应用程序,我可以用作参考吗?
在尝试了一些想法后,我意识到为多个活动实现相同导航抽屉的最方便的方法是创建一个BaseActivity
来处理所有抽屉功能,我的所有活动都可以从中继承。
这是我到目前为止所得到的:
BaseActivity
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
public class BaseActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private ListView mDrawerListView;
protected void onCreate(Bundle savedInstanceState, int resLayoutID) {
setContentView(resLayoutID);
super.onCreate(savedInstanceState);
setupNavDrawer();
}
private void setupNavDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerListView = (ListView) findViewById(R.id.drawer);
mDrawerListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
String[] rows = getResources().getStringArray(R.array.drawer_rows);
mDrawerListView.setAdapter(new ArrayAdapter<String>(
this, R.layout.drawer_row, rows));
mDrawerToggle =
new ActionBarDrawerToggle(this, mDrawerLayout,
R.string.drawer_open,
R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> listView, View row,
int position, long id) {
if (position == 0) {
Log.d("Menu", "European Union");
} else {
Log.d("Menu", "Other Option");
}
mDrawerLayout.closeDrawers();
}
});
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
现在需要拥有导航抽屉的每个活动都需要扩展BaseActivity
:
EuropeanUnionActivity
public class EuropeanUnionActivity extends BaseActivity{
//...
}
此外,每个活动布局都需要在其代码中包含android.support.v4.widget.DrawerLayout
元素,如下所示:
activity_europeanunion
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/main" />
<ListView
android:id="@+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>
值得一提的是,DrawerLayout
(drawer_layout)和ListView
(抽屉)的ID在所有具有导航抽屉的活动布局中需要相同,因为这些ID由BaseActivity
使用。
为了简洁和快速测试这种方法,我使用了@CommonsWare的this example(我希望他不介意)。在那里,您可以找到@layout/main
的实现。
现在,虽然几乎所有内容都按预期运行,但我无法理解为什么我将ListView
的代码放在一个单独的文件中 listview_options 导航抽屉根本不会关闭并点击ActionBarDrawerToggle
只会让应用程序崩溃并在LogCat中显示:
FATAL EXCEPTION: main
Process: com.idealsolution.simplenavigationdrawer, PID: 17725
java.lang.IllegalArgumentException: No drawer view found with gravity LEFT
at android.support.v4.widget.DrawerLayout.openDrawer(DrawerLayout.java:1293)
at android.support.v7.app.ActionBarDrawerToggle.toggle(ActionBarDrawerToggle.java:290)
at android.support.v7.app.ActionBarDrawerToggle.onOptionsItemSelected(ActionBarDrawerToggle.java:280)
at com.idealsolution.simplenavigationdrawer.BaseActivity.onOptionsItemSelected(BaseActivity.java:86)
at android.app.Activity.onMenuItemSelected(Activity.java:2608)
at com.android.internal.widget.ActionBarView$3.onClick(ActionBarView.java:167)
at android.view.View.performClick(View.java:4456)
at android.view.View$PerformClick.run(View.java:18465)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
这是第86行:
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) { //Line 86
return true;
}
return super.onOptionsItemSelected(item);
}
这是相同的代码
activity_europeanunion ,但为include
使用ListView
标记
<include layout="@layout/main" />
<include layout="@layout/listview_options" />
listview_options.xml 的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/menu_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
</LinearLayout>
这是我在BaseActivity
中尝试检索ListView
的代码,但这显然无效:
private void setupNavDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
//Please pay special attention to the following two lines
mDrawerLinearLayout = (LinearLayout) findViewById(R.id.menu_layout);
mDrawerListView = (ListView) mDrawerLinearLayout.findViewById(R.id.drawer);
mDrawerListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
String[] rows = getResources().getStringArray(R.array.drawer_rows);
mDrawerListView.setAdapter(new ArrayAdapter<String>(
this, R.layout.drawer_row, rows));
mDrawerToggle =
new ActionBarDrawerToggle(this, mDrawerLayout,
R.string.drawer_open,
R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> listView, View row,
int position, long id) {
//...
mDrawerLayout.closeDrawers();
}
});
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
欢迎任何想法和建议。 感谢。
P.S。我找到了this question,据说使用导航抽屉是不可取的。
答案 0 :(得分:2)
对于手机和平板电脑肖像模式,您可以使用以下布局:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="@layout/fragments_layout" />
<include layout="@layout/drawer_list" />
</android.support.v4.widget.DrawerLayout>
这可能是平板电脑横向模式的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="@layout/drawer_list" />
<include layout="@layout/fragments_layout" />
</LinearLayout>
这是drawer_list:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="260dp"
android:layout_height="match_parent"
android:layout_gravity="start" >
<ListView
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:background="#111"
android:divider="@android:color/darker_gray"
android:dividerHeight="0dp" />
</RelativeLayout>
和fragments_layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment android:id="+@id/master_fragment" />
<fragment android:id="+@id/detail_fragment" />
</FrameLayout>
在活动中,您必须检查自己是否处于平板电脑横向模式并显示两个片段。否则,您将首先显示主片段,隐藏细节
如果导航抽屉在所有活动中都可见,请声明一个负责抽屉的抽象活动。然后,所有活动都继承自此抽象活动。您发布的BaseActivity是一个很好的例子