来自 xml 的 NavigationView onClick 导致错误
NavigationView onClick from xml causes errors
使用新发布的 Android 支持设计库中的 NavigationView,如果导航 header 布局包含 onClick(在 xml 中),onClick 事件会使应用程序崩溃。可以通过 view.onClickListener
(而不是 xml)以编程方式添加 OnClick,然后点击工作正常。但是由于某些原因,每当使用xml onClick时,都会出错。
这是我的主要布局:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/mainActivityLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<RelativeLayout
android:id="@+id/mainContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="@+id/drawerNavView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer_menu">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
在我的 activity 中,我的菜单项点击(添加 navView.setNavigationItemSelectedListener()
)工作正常。问题是单击 header 时:
drawer_header.xml:
...
<View
android:id="@+id/testButton"
android:layout_width="match_parent"
android:layout_height="60dp"
android:onClick="testButtonClick"/>
...
产生以下错误:
java.lang.IllegalStateException: Could not find a method testButtonClick(View)
in the activity class android.view.ContextThemeWrapper for onClick handler
on view class android.view.View with id 'testButton'
更新
NavigationView 可以使用标准的菜单资源文件,但是如果使用菜单 XML 资源中的 onClick 也会出现类似的问题。根据 Menu Resource reference,android:onClick
属性覆盖了正常的回调。这通常可以很好地工作,但对于 NavigationView 中的菜单项,它不会。相反,它因以下错误而崩溃:
java.lang.RuntimeException: Unable to start activity ComponentInfo{...}:
android.view.InflateException: Binary XML file line #34:
Error inflating class android.support.design.widget.NavigationView
删除 XML onClick 后错误消失。
更新
我使用 Android 设计库的 "official" demo project 测试了 xml onClick。相同的结果:将 onClick(在 xml 中)添加到 NavigationView 的菜单或 header 中会导致应用程序崩溃。所以这似乎是 NavigationView 的错误。
已在 v23.1 中解决
Google 针对支持库 v23.1 中的这些 XML onClick 错误发布了 a fix。
您可以在代码中编写您的方法,而无需在 XML 中提及。在代码中,您只需使用代码
public void methodName()
{
//
}
View v = findViewById(R.id.view_id);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
methodName();
}
});
NavigationView 有一个用于菜单项的 OnNavigationItemSelectedListener。
例如
navigationView.setNavigationItemSelectedListener(new SelectedNavigationItemListener());
private class SelectedNavigationItemListener implements NavigationView.OnNavigationItemSelectedListener {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()){
case id1:
break;
}
Log.d("MENU ITEM", menuItem.getTitle().toString());
return false;
}
}
对于页眉,您可以这样做,例如
navigationView = (NavigationView) findViewById(R.id.navigation_view);
View header = navigationView.inflateHeaderView(R.layout.drawer_header);
RelativeLayout drawerHeader = (RelativeLayout) header.findViewById(R.id.drawerHeader);
drawerHeader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("CLICKED HEADER", "Header Clicked");
}
});
我的 HeaderLayout 参考:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawerHeader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="16sp" />
已确认,这是支持库中的错误。
显然它与 ContextThemeWrapper
有关,根据这个 bug report,支持库 22.1 中存在问题。
所以,简短的回答是:
在修复之前,不要将 XML onClick 与 NavigationView(或其他一些组件,如 EditText)一起使用。
解决方法:
在代码中设置点击监听器。对于 NavigationView,使用 setNavigationItemSelectedListener()
.
更新:此错误已修复
您现在可以在支持库 23.1 (bug report) 中使用 XML onClick。我已经验证它在我的应用程序中有效。但是 v23.1 中的 NavView 似乎还有其他(较新的)XML 问题(见下文),即使这个特定的 onClick 错误现在已修复。
完整性:
通过 XML 扩展 NavigationView header 时,似乎存在另一个(相关的?)错误。使用 XML app:headerLayout
会在 23.1 中产生错误,即使 XML onClick 现在有效。由于这个 inflation 问题,您需要在代码中使用 NavigationView.inflateHeaderView()
方法。这个新方法是在 23.1 中添加的,显然,以前的 XML inflate 现在被破坏了(或者他们可能在没有告诉任何人的情况下弃用了 app:headerLayout
?)。更多信息详细 here。
嗨:我的解决方案是删除
app:headerLayout="@layout/drawer_header"
从您的 NavigationView 布局如下:
<android.support.design.widget.NavigationView
android:id="@+id/drawerNavView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/drawer_menu">
</android.support.design.widget.NavigationView>
然后在您的 activity 或视图控制器中使用下面的内容
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View headerView= navigationView.inflateHeaderView(R.layout.nav_header);
TextView tvName = (TextView) headerView.findViewById(R.id.id_nav_header_uname);
tvName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
L.d("=======tv click=====");
}
});
这对我有用。
使用新发布的 Android 支持设计库中的 NavigationView,如果导航 header 布局包含 onClick(在 xml 中),onClick 事件会使应用程序崩溃。可以通过 view.onClickListener
(而不是 xml)以编程方式添加 OnClick,然后点击工作正常。但是由于某些原因,每当使用xml onClick时,都会出错。
这是我的主要布局:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/mainActivityLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<RelativeLayout
android:id="@+id/mainContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="@+id/drawerNavView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer_menu">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
在我的 activity 中,我的菜单项点击(添加 navView.setNavigationItemSelectedListener()
)工作正常。问题是单击 header 时:
drawer_header.xml:
...
<View
android:id="@+id/testButton"
android:layout_width="match_parent"
android:layout_height="60dp"
android:onClick="testButtonClick"/>
...
产生以下错误:
java.lang.IllegalStateException: Could not find a method testButtonClick(View)
in the activity class android.view.ContextThemeWrapper for onClick handler
on view class android.view.View with id 'testButton'
更新
NavigationView 可以使用标准的菜单资源文件,但是如果使用菜单 XML 资源中的 onClick 也会出现类似的问题。根据 Menu Resource reference,android:onClick
属性覆盖了正常的回调。这通常可以很好地工作,但对于 NavigationView 中的菜单项,它不会。相反,它因以下错误而崩溃:
java.lang.RuntimeException: Unable to start activity ComponentInfo{...}:
android.view.InflateException: Binary XML file line #34:
Error inflating class android.support.design.widget.NavigationView
删除 XML onClick 后错误消失。
更新
我使用 Android 设计库的 "official" demo project 测试了 xml onClick。相同的结果:将 onClick(在 xml 中)添加到 NavigationView 的菜单或 header 中会导致应用程序崩溃。所以这似乎是 NavigationView 的错误。
已在 v23.1 中解决
Google 针对支持库 v23.1 中的这些 XML onClick 错误发布了 a fix。
您可以在代码中编写您的方法,而无需在 XML 中提及。在代码中,您只需使用代码
public void methodName()
{
//
}
View v = findViewById(R.id.view_id);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
methodName();
}
});
NavigationView 有一个用于菜单项的 OnNavigationItemSelectedListener。
例如
navigationView.setNavigationItemSelectedListener(new SelectedNavigationItemListener());
private class SelectedNavigationItemListener implements NavigationView.OnNavigationItemSelectedListener {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()){
case id1:
break;
}
Log.d("MENU ITEM", menuItem.getTitle().toString());
return false;
}
}
对于页眉,您可以这样做,例如
navigationView = (NavigationView) findViewById(R.id.navigation_view);
View header = navigationView.inflateHeaderView(R.layout.drawer_header);
RelativeLayout drawerHeader = (RelativeLayout) header.findViewById(R.id.drawerHeader);
drawerHeader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("CLICKED HEADER", "Header Clicked");
}
});
我的 HeaderLayout 参考:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawerHeader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="16sp" />
已确认,这是支持库中的错误。
显然它与 ContextThemeWrapper
有关,根据这个 bug report,支持库 22.1 中存在问题。
所以,简短的回答是:
在修复之前,不要将 XML onClick 与 NavigationView(或其他一些组件,如 EditText)一起使用。
解决方法:
在代码中设置点击监听器。对于 NavigationView,使用 setNavigationItemSelectedListener()
.
更新:此错误已修复
您现在可以在支持库 23.1 (bug report) 中使用 XML onClick。我已经验证它在我的应用程序中有效。但是 v23.1 中的 NavView 似乎还有其他(较新的)XML 问题(见下文),即使这个特定的 onClick 错误现在已修复。
完整性:
通过 XML 扩展 NavigationView header 时,似乎存在另一个(相关的?)错误。使用 XML app:headerLayout
会在 23.1 中产生错误,即使 XML onClick 现在有效。由于这个 inflation 问题,您需要在代码中使用 NavigationView.inflateHeaderView()
方法。这个新方法是在 23.1 中添加的,显然,以前的 XML inflate 现在被破坏了(或者他们可能在没有告诉任何人的情况下弃用了 app:headerLayout
?)。更多信息详细 here。
嗨:我的解决方案是删除
app:headerLayout="@layout/drawer_header"
从您的 NavigationView 布局如下:
<android.support.design.widget.NavigationView
android:id="@+id/drawerNavView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/drawer_menu">
</android.support.design.widget.NavigationView>
然后在您的 activity 或视图控制器中使用下面的内容
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View headerView= navigationView.inflateHeaderView(R.layout.nav_header);
TextView tvName = (TextView) headerView.findViewById(R.id.id_nav_header_uname);
tvName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
L.d("=======tv click=====");
}
});
这对我有用。