其他分享
首页 > 其他分享> > android – 导航抽屉Viewpager setVisibility = InflateException / NullPointer

android – 导航抽屉Viewpager setVisibility = InflateException / NullPointer

作者:互联网

我开发了一个Android应用程序,我遇到了一些问题.

在我的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

http://pastebin.com/LwKZnNiB

显示ViewPager内容

在我的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()方法中?

标签:android,android-fragments,android-viewpager,navigation-drawer,android-navigation
来源: https://codeday.me/bug/20190831/1773293.html