动态改变抽屉布局
dynamically change the drawer layout
我遇到这种情况:启动应用程序时,显示的第一个片段 (A) 包含一些用户的列表。单击用户时,会显示另一个片段 (B),每个用户的抽屉菜单都会不同。
如您所见,我无法在启动应用程序(主要 activity 或 Launcher)时设置 DrawerLayout,因为我还没有 listView 的数据,但必须设置它在应用程序完成启动后单击片段 A 中的列表中的用户时向上(那时我可以检索抽屉菜单的 listView 的数据,由下面的 id 表示:fragment_drawer xml 文件)。
这是 "MainActivity" 的 xml 文件:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- The main content view -->
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer, listView is inside MyDrawerFragment's layout-->
<fragment android:id="@+id/fragment_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="mypackage.com.MyDrawerFragment"
tools:layout="@layout/drawer_layout" />
</android.support.v4.widget.DrawerLayout>
如何实现片段 B 中的目标?这在片段 B 中完全可以实现吗?
如果无法在片段 B 中执行此操作,我正在考虑启动第二个 activity,比如 Activity2,上面的 xml 布局文件将应用于这个新的 activity,当单击片段 A 中的用户时,我只是继续这样做:通过调用 finish() 关闭现有的 Acitvity2 并使用抽屉菜单的新数据创建一个新的 Activity2 实例?这种方法是否可行?
非常感谢任何提示!
谢谢,
肖恩
我必须做一个应用程序,我必须制作一个 Activity 有 4 个片段和一个 ViewPager,其中只有 2 个我会打开一个不同的抽屉。
Activity的布局必须包含DrawerLayout*,但由于Drawer本身取决于我在哪个Fragment上,我认为它应该是负责渲染(或不渲染)抽屉的片段。
*如果Activity不包含DrawerLayout,就不会满屏显示!
我做了类似的事情,尽管它确实需要一些重构和清理:)
基于 Fragment 负责渲染抽屉的想法,但它是 Activity 可以访问它的那个,我制作了两个接口来与 Fragment 和 Activity 通信:
/**
* should be implemented by any fragment interested in communicating
* with a {@link FragmentListener} Activity
*/
public interface ActivityListener {
/**
* called from {@link FragmentListener} requestOpenDrawer
* the fragment is in charge of rendering its drawer's layout
*/
public void renderDrawer(DrawerLayout mDrawerLayout,
NavigationView viewById, Activity activity);
}
-
/**
* used to communicate FROM fragments, to its parent Activity
* implemented by {@link MainTabbedActivity}
*/
public interface FragmentListener {
/**
* call from a fragment to request opening the drawer
* note that if the drawer isn't opened by the activity,
* it wouldn't cover the whole screen
*/
void requestOpenDrawer(Fragment requester);
void requestCloseDrawer();
DrawerLayout getDrawerLayout();
}
实施
@Override
public void requestOpenDrawer(Fragment requester) {
mDrawerLayout.openDrawer(Gravity.RIGHT); //Edit Gravity.End need API 14
if (requester instanceof ActivityListener) {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
//let fragment render the drawer
((ActivityListener) requester).renderDrawer(mDrawerLayout, navigationView, this);
}
}
-
@Override
public void renderDrawer(DrawerLayout mDrawerLayout, NavigationView viewById, Activity activity) {
View child = activity.getLayoutInflater().inflate(R.layout.credit_fragment_drawer, null);
navigationView.addView(child);
}
布局
Activity 布局和 Fragments 布局都只是标准的抽屉实现:
Activity 带抽屉的布局:
<?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/main_tabbed_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="right">
<include
layout="@layout/activity_main_tabbed_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:fitsSystemWindows="true" />
</android.support.v4.widget.DrawerLayout>
其中 activity_main_tabbed_content 是您要放入 Activity 的任何内容。
Fragments 真的除了一个普通的Fragment 什么都没有。
示例:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- whatever views you want -->
</RelativeLayout>
我遇到这种情况:启动应用程序时,显示的第一个片段 (A) 包含一些用户的列表。单击用户时,会显示另一个片段 (B),每个用户的抽屉菜单都会不同。
如您所见,我无法在启动应用程序(主要 activity 或 Launcher)时设置 DrawerLayout,因为我还没有 listView 的数据,但必须设置它在应用程序完成启动后单击片段 A 中的列表中的用户时向上(那时我可以检索抽屉菜单的 listView 的数据,由下面的 id 表示:fragment_drawer xml 文件)。
这是 "MainActivity" 的 xml 文件:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- The main content view -->
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer, listView is inside MyDrawerFragment's layout-->
<fragment android:id="@+id/fragment_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="mypackage.com.MyDrawerFragment"
tools:layout="@layout/drawer_layout" />
</android.support.v4.widget.DrawerLayout>
如何实现片段 B 中的目标?这在片段 B 中完全可以实现吗?
如果无法在片段 B 中执行此操作,我正在考虑启动第二个 activity,比如 Activity2,上面的 xml 布局文件将应用于这个新的 activity,当单击片段 A 中的用户时,我只是继续这样做:通过调用 finish() 关闭现有的 Acitvity2 并使用抽屉菜单的新数据创建一个新的 Activity2 实例?这种方法是否可行?
非常感谢任何提示!
谢谢, 肖恩
我必须做一个应用程序,我必须制作一个 Activity 有 4 个片段和一个 ViewPager,其中只有 2 个我会打开一个不同的抽屉。
Activity的布局必须包含DrawerLayout*,但由于Drawer本身取决于我在哪个Fragment上,我认为它应该是负责渲染(或不渲染)抽屉的片段。
*如果Activity不包含DrawerLayout,就不会满屏显示!
我做了类似的事情,尽管它确实需要一些重构和清理:)
基于 Fragment 负责渲染抽屉的想法,但它是 Activity 可以访问它的那个,我制作了两个接口来与 Fragment 和 Activity 通信:
/**
* should be implemented by any fragment interested in communicating
* with a {@link FragmentListener} Activity
*/
public interface ActivityListener {
/**
* called from {@link FragmentListener} requestOpenDrawer
* the fragment is in charge of rendering its drawer's layout
*/
public void renderDrawer(DrawerLayout mDrawerLayout,
NavigationView viewById, Activity activity);
}
-
/**
* used to communicate FROM fragments, to its parent Activity
* implemented by {@link MainTabbedActivity}
*/
public interface FragmentListener {
/**
* call from a fragment to request opening the drawer
* note that if the drawer isn't opened by the activity,
* it wouldn't cover the whole screen
*/
void requestOpenDrawer(Fragment requester);
void requestCloseDrawer();
DrawerLayout getDrawerLayout();
}
实施
@Override
public void requestOpenDrawer(Fragment requester) {
mDrawerLayout.openDrawer(Gravity.RIGHT); //Edit Gravity.End need API 14
if (requester instanceof ActivityListener) {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
//let fragment render the drawer
((ActivityListener) requester).renderDrawer(mDrawerLayout, navigationView, this);
}
}
-
@Override
public void renderDrawer(DrawerLayout mDrawerLayout, NavigationView viewById, Activity activity) {
View child = activity.getLayoutInflater().inflate(R.layout.credit_fragment_drawer, null);
navigationView.addView(child);
}
布局
Activity 布局和 Fragments 布局都只是标准的抽屉实现:
Activity 带抽屉的布局:
<?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/main_tabbed_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="right">
<include
layout="@layout/activity_main_tabbed_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:fitsSystemWindows="true" />
</android.support.v4.widget.DrawerLayout>
其中 activity_main_tabbed_content 是您要放入 Activity 的任何内容。
Fragments 真的除了一个普通的Fragment 什么都没有。 示例:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- whatever views you want -->
</RelativeLayout>