在我的MainActivity中,我有以下组件:
>导航抽屉(实例化并加载许多碎片)
> ViewPager(仅适用于显示文章详细视图的ArticleFragment)
normaly,ViewPager与特定的Activity有关,但我真的想同时使用Navigation Drawer和ViewPager.唯一的方法是在同一个活动中实现这两个元素.
DrawerLayout由导航抽屉本身和内容区域组成.在我的内容区域中,我有一个FrameLayout和ViewPager.问题是始终显示ViewPager.
所以我的想法是使用android:visibility属性来交替显示/隐藏FrameLayout和ViewPager.如果查看我的activity_main.xml,您会发现在ViewPager上将android:visibility设置为不可见.
/layout/activity_main.xml
<!-- The main content view -->
<RelativeLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:paddingTop="?android:attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- ViewPager -->
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
</RelativeLayout>
<!-- The navigation drawer -->
<fragment android:id="@+id/navigation_drawer"
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="NavigationDrawerFragment" />
</android.support.v4.widget.DrawerLayout>
然后:
MainActivity.java
public class MainActivity extends ActionBaractivity implements NavigationDrawerFragment.NavigationDrawerCallbacks {
private NavigationDrawerFragment mNavigationDrawerFragment;
private FrameLayout mContainer;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the navigation drawer
mContainer = (FrameLayout) findViewById(R.id.container);
mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mNavigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout));
// Set up the viewpager
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setonPagechangelistener(new ViewPager.SimpleOnPagechangelistener() {
@Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
}
});
}
//-------------------------------//
// NAVIGATION DRAWER //
//-------------------------------//
/**
* Update the main content by replacing fragments
*/
@Override
public void onNavigationDrawerItemSelected(int position) {
Fragment fragment = null;
Boolean viewPagerArticles = false;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new FooFragment();
break;
case 2:
viewPagerArticles = true;
// Hide navigation drawer container and show the viewpager
mContainer.setVisibility(FrameLayout.GONE);
mPager.setVisibility(ViewPager.VISIBLE);
// NullPointerException with new this line. Why?
// Fragment already instanciate in ScreenSlidePagerAdapter -> getItem() -> ArticleFragment.create()?
//fragment = new ArticleFragment();
break;
default:
break;
}
// Show the view pager and hide navigation drawer container
// =================
// THE BUG IS HERE
// =================
if (!viewPagerArticles) {
mContainer.setVisibility(FrameLayout.VISIBLE);
mPager.setVisibility(ViewPager.GONE);
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
}
...
//-------------------------------//
// VIEWPAGER //
//-------------------------------//
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return DayFragment.create(position);
}
@Override
public int getCount() { ... }
}
...
}
NavigationDrawerFragment.java
在我的HomeFragment上,我有一个带有onClickListener的按钮:
mButton.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((MainActivity)getActivity()).onNavigationDrawerItemSelected(2);
}
});
当我加载MainActivity时,我遇到了以下错误:InflateException和NullPointerException
AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android/com.example.android.ui.MainActivity}: android.view.InflateException: Binary XML file line #34: Error inflating class fragment
at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:2211)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #34: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:267)
at android.app.Activity.setContentView(Activity.java:1895)
at android.support.v7.app.ActionBaractivity.superSetContentView(ActionBaractivity.java:216)
at android.support.v7.app.ActionBaractivityDelegateICS.setContentView(ActionBaractivityDelegateICS.java:111)
at android.support.v7.app.ActionBaractivity.setContentView(ActionBaractivity.java:76)
at com.example.android.ui.MainActivity.onCreate(MainActivity.java:42)
at android.app.Activity.performCreate(Activity.java:5133)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:2175)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.android.ui.MainActivity.onNavigationDrawerItemSelected(MainActivity.java:117)
at com.example.android.ui.NavigationDrawerFragment.selectItem(NavigationDrawerFragment.java:202)
at com.example.android.ui.NavigationDrawerFragment.onCreate(NavigationDrawerFragment.java:80)
at android.support.v4.app.Fragment.performCreate(Fragment.java:1477)
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:893)
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:1082)
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1184)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:291)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:267)
at android.app.Activity.setContentView(Activity.java:1895)
at android.support.v7.app.ActionBaractivity.superSetContentView(ActionBaractivity.java:216)
at android.support.v7.app.ActionBaractivityDelegateICS.setContentView(ActionBaractivityDelegateICS.java:111)
at android.support.v7.app.ActionBaractivity.setContentView(ActionBaractivity.java:76)
at com.example.android.ui.MainActivity.onCreate(MainActivity.java:42)
at android.app.Activity.performCreate(Activity.java:5133)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:2175)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
一切都很好(没有错误,活动加载)没有:
// =================
// THE BUG IS HERE
// =================
if (!viewPagerArticles) {
mContainer.setVisibility(FrameLayout.VISIBLE);
mPager.setVisibility(ViewPager.GONE);
}
…但它不符合我的期望,因为导航抽屉片段总是隐藏(由于mContainer.setVisibility(FrameLayout.GONE),它是正常的.)我只想反转mContainer / mPager可见性.
我希望我足够清楚……!
任何的想法?
解决方法:
您得到NullPointerException,因为您构建NavigationDrawerFragment片段的方式.更准确地说,在onCreate()方法中,您调用selectItem(),它通过Activity(注册为侦听器)传播到onNavigationDrawerItemSelected()回调.问题是片段在调用setContentView()时会膨胀(在onCreate()中),这意味着你将在行之前输入onNavigationDrawerItemSelected()回调:
mContainer = (FrameLayout) findViewById(R.id.container);
mPager = (ViewPager) findViewById(R.id.pager);
运行,在onNavigationDrawerItemSelected()中呈现这些引用为null.
要解决此问题,您只需替换当前的< fragment />即可.使用基本容器(例如占位符为空的FrameLayout)从Activity布局标记,并在上面的行(绑定视图的位置)之后在onCreate()中手动添加NavigationDrawerFragment.可能有另一种更好的解决方案(或者我可以提出其他建议)但是你不清楚如何处理可见性.也许你可以扩展这个.
编辑2:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the navigation drawer
mContainer = (FrameLayout) findViewById(R.id.container);
// Set up the viewpager
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setonPagechangelistener(new ViewPager.SimpleOnPagechangelistener() {
@Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
}
});
if (savedInstanceState == null) {
NavigationDrawerFragment ndf = new NavigationDrawerFragment();
ndf.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout));
getSupportFragmentManager().beginTransaction().add(R.id.nav_drawer, ndf).commit();
}
}
编辑1:
//...
<!-- ViewPager -->
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
</RelativeLayout>
<!-- The navigation drawer -->
<FrameLayout android:id="@+id/nav_drawer"
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
/>
</android.support.v4.widget.DrawerLayout>
最后在onCreate()中:
//...
mPager.setAdapter(mPagerAdapter);
mPager.setonPagechangelistener(new ViewPager.SimpleOnPagechangelistener() {
@Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
}
});
getSupportFragmentManager().beginTransaction().add(R.id.nav_drawer, new NavigationDrawerFragment()).commit();
如果您使用上面的代码获得异常,那么它是否在onNavigationDrawerItemSelected()方法中?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。