我知道以前可能会问过这个问题,但是由于我没有发现任何令人信服的内容,因此我需要再次询问。
当您还需要提供某种类型的导航面板(例如Navigation Drawer)时,如何设计将支持平板电脑和手机的应用程序?
我想我知道如何将导航抽屉与纵向使用的手机和平板电脑一起使用,因为在那种情况下,我当时只显示一个窗格(碎片)。但是对于平板电脑而言,这是完全不同的,因为您有足够的空间来显示至少两个窗格(碎片),大多数情况下,它们将以一种“重要细节”方式关联。
编辑#1
只是为了提供有关我的应用的背景信息,以及为什么我认为我需要在导航列表之外添加两个窗格。
我的应用程序的主要目标是帮助服务员下订单,这种情况在以下情况下起作用:
服务员从左侧菜单中选择“接单”选项(理想情况下为导航抽屉)
在我所谓的“内容部分”的第一部分(左窗格)中,服务员可以在他们提供的所有食物类别中进行选择(假装它是顶部的列表),然后根据所选类别,如下列表显示该特定类别下的所有菜肴。
一旦服务员点击菜,它就会自动添加到“内容部分”的第二部分(右窗格)中
知道导航抽屉的基本结构与此类似:
<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中有任何实现此功能的开源应用程序,并且可以用作参考?
编辑#2
在尝试了一些想法之后,我意识到为多个活动实现相同导航抽屉的最便捷方法是创建一个
BaseActivity
,该cc处理所有抽屉功能,并且所有活动都可以从中继承。到目前为止,这是我得到的:
基础活动
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
:欧洲联盟活动
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
(drawer)的ID必须相同,因为这些ID被为了简洁起见并快速测试这种方法,我使用了@CommonsWare的this example(我希望他不介意)。在这里,您可以找到
BaseActivity
的实现。现在,尽管几乎所有内容都能按预期工作,但我仍无法理解为什么我将
@layout/main
的代码放入单独的文件listview_options中,导航抽屉根本无法关闭并点击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,但对
ListView
使用ActionBarDrawerToggle
标记<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>
这是我在
include
中尝试检索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);
}
欢迎任何想法和建议。
谢谢。
附言我发现this question在其中不建议使用导航抽屉。
最佳答案
对于手机和平板电脑肖像模式,您可以使用以下布局:
<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>
这是抽屉列表:
<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是一个很好的例子
关于android - 如何为支持平板电脑和手机的应用程序提供导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28878027/