【问题标题】:NullPointerException trying to use ActionBarDrawerToggleNullPointerException 试图使用 ActionBarDrawerToggle
【发布时间】:2020-12-10 07:48:27
【问题描述】:

我正在尝试使用 ActionBarDrawerToggle,但出现此错误:

无法启动活动 ComponentInfo{com.cristianerm.bestflight/com.cristianerm.bestflight.MonitoredDestinationsActivity}:java.lang.NullPointerException:尝试调用虚拟方法 'void androidx.drawerlayout.widget.DrawerLayout.addDrawerListener(androidx.drawerlayout .widget.DrawerLayout$DrawerListener)' 在空对象引用上

在我尝试添加抽屉之前,工具栏正在工作。我在这里找到了一些答案,但没有解决我的问题。如果有人可以帮助我,谢谢你:)

我的代码:

MonitoredDestinationsActivity

class MonitoredDestinationsActivity : AppCompatActivity(), NavigationHost,
    NavigationView.OnNavigationItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_monitored_destinations)

        if (savedInstanceState == null) {
            supportFragmentManager
                .beginTransaction()
                .add(R.id.container_monitored_destinations, MonitoredDestinationsFragment())
                .commit()
        }

        val actionBarDrawerToggle = ActionBarDrawerToggle(
            this,
            drawer_layout,
            app_bar_monitored_destinations,
            R.string.open_drawer,
            R.string.close_drawer
        )

        drawer_layout.addDrawerListener(actionBarDrawerToggle)
        actionBarDrawerToggle.syncState()
        nav_view.setNavigationItemSelectedListener(this)
    }

    override fun navigateTo(fragment: Fragment, addToBackstack: Boolean) {
        val transaction = supportFragmentManager
            .beginTransaction()
            .replace(R.id.container_monitored_destinations, fragment)

        if (addToBackstack) {
            transaction.addToBackStack(null)
        }

        transaction.commit()
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        TODO("Not yet implemented")
    }
} 

MonitoredDestinationsFragment

class MonitoredDestinationsFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_monitored_destinations, container, false)

        // Set up the toolbar.
        /*(activity as AppCompatActivity).setSupportActionBar(view.app_bar_monitored_destinations)

        view.app_bar_monitored_destinations.setNavigationOnClickListener {
            Toast.makeText(context, "Test", Toast.LENGTH_LONG).show();
        }*/

        view.app_bar_monitored_destinations.setOnMenuItemClickListener { menuItem ->
            when (menuItem.itemId) {
                R.id.menu_icon_more -> {
                    Toast.makeText(context, "Test item clicked", Toast.LENGTH_LONG).show();
                    true
                }
                else -> false
            }
        }

        return view
    }

    override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
        menuInflater.inflate(R.menu.toolbar_menu, menu)
        super.onCreateOptionsMenu(menu, menuInflater)
    }


}

fragment_monitored_destinations.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MonitoredDestinationsFragment">

    <androidx.drawerlayout.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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MonitoredDestinationsFragment"
        android:id="@+id/drawer_layout"
        >

        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <com.google.android.material.appbar.AppBarLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/app_bar_monitored_destinations"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:title="Best Flight"
                    app:navigationIcon="@drawable/ic_menu"
                    style="@style/Widget.MaterialComponents.Toolbar.Primary"/>
            </com.google.android.material.appbar.AppBarLayout>
        </androidx.coordinatorlayout.widget.CoordinatorLayout>

        <com.google.android.material.navigation.NavigationView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            app:menu="@menu/nav_menu"
            android:id="@+id/nav_view"
            android:layout_gravity="start"
            />

    </androidx.drawerlayout.widget.DrawerLayout>

</FrameLayout>

【问题讨论】:

    标签: android kotlin material-design


    【解决方案1】:

    我不知道您是否使用某些视图绑定来自动将drawer_layout 分配为变量(而不是执行findViewById),但该视图和 ID 是在您的片段中定义的,而不是在您的活动中。 The source for ActionBarDrawerToggle 表明它实际上并没有检查您传递给构造函数的 DrawerLayout 是否为空,因此当您尝试在其上调用 addDrawerListener 方法时它只是崩溃

    您可能不想浪费时间等待片段膨胀,以便获取它的视图并找到drawer_layout,所以我只想说通常的建议是将DrawerLayout 放在您的容器中活动,带有一个容器来粘贴实际内容(如片段)。这样,它是一个一致的 UI,而不是每次添加片段时都会更改,并且 DrawerLayout 将可以在 Activity 的 onCreate 中访问

    有一个你设置它的方式的例子here

    【讨论】:

    • 您好,我按照教程操作,移动了代码,进行了一些修改,并且成功了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多