I develops an Android Application and I'm facing some problems.
In my MainActivity
I have the following components:
- Navigation Drawer (instanciates and loads many fragments)
- ViewPager (only for
ArticleFragment
which display the detail view of an article)
Normaly, the ViewPager is related to a specific Activity, but I really want to use both Navigation Drawer and ViewPager. The only way is to implement both elements in same activity.
The DrawerLayout
is composed by the navigation drawer itself and by the content area. In my content area I have a FrameLayout
and the ViewPager
. The problem is that the ViewPager
is always displayed.
So my idea was to play with the android:visibility
property to show/hide alternately the FrameLayout and the ViewPager. If you look at my activity_main.xml
you can notice the android:visibility
set to invisible
on the ViewPager
.
/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>
And then:
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
http://pastebin.com/LwKZnNiB
Display ViewPager content
On my HomeFragment
I have a button with a onClickListener:
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((MainActivity)getActivity()).onNavigationDrawerItemSelected(2);
}
});
When I load MainActivity I have these errors : InflateException and 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)
Everything is fine (no errors, activity loaded) without:
// =================
// THE BUG IS HERE
// =================
if (!viewPagerArticles) {
mContainer.setVisibility(FrameLayout.VISIBLE);
mPager.setVisibility(ViewPager.GONE);
}
...but it does not match my expectations because the Navigation Drawer fragments are always hiding (it's normal because of mContainer.setVisibility(FrameLayout.GONE);
. I just want to inverse the mContainer/mPager visibilities.
I hope I was enough clear...!
Any idea?