【问题标题】:Crash when clicking button with custom theme单击具有自定义主题的按钮时崩溃
【发布时间】:2015-07-27 12:28:42
【问题描述】:

我正在为按钮创建一个自定义主题,并使用 xml 本身的 Button 的android:onClick 事件来处理按钮的点击。

由于某种原因,它崩溃并出现以下异常

java.lang.IllegalStateException: Could not find a method MyOnClick(View) in the activity class android.view.ContextThemeWrapper for onClick handler on view class android.widget.Button with id 'button1'

如果我只是从 Button 中删除主题属性,它工作正常,下面是我的 Button 主题

    <style name="ButtonTheme" parent="@android:style/Widget.Button">
        <item name="android:textColor">#FF0000</item>
        <item name="android:shadowColor">#FF000000</item>
    </style>

我的 Button 在 xml 中定义如下,

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_margin="20dp"
        android:onClick="MyOnClick"
        android:theme="@style/ButtonTheme"
        android:text="Button" />

这也是我的 java 代码,

public void MyOnClick(View view) {
        switch (view.getId()) {
        case R.id.button1:
            getWindow().setStatusBarColor(getResources()
                                   .getColor(R.color.statusBarColor));
            getWindow().setNavigationBarColor(getResources()
                                   .getColor(R.color.statusBarColor));
            break;

        default:
            break;
        }

    }

那么,崩溃的原因可能是什么?如果我从 xml 的 Button Widget 中删除 android:theme="@style/ButtonTheme" 属性,我就能够处理点击事件。

【问题讨论】:

  • 发布你的java代码...
  • 尝试使用旧方法删除 android:onClick 属性并使用 Button button=(Button)findViewById(R.id.button1);button.setOnClickListener(new View.OnClickListener(){ @Override public void onClick (查看 v) { } });并且不要忘记定义按钮
  • @L-X 但为什么呢?我想在xml本身中添加点击事件,然后呢?
  • 伙计,我猜错误是您为每个按钮定义了相同的 onClick 方法(猜测您有多个按钮),但这会产生错误尝试为不同的按钮定义不同的函数名称并定义所有这些java中的函数,试试吧
  • @L-X 我现在只有一个按钮,如果我有多个按钮,我也可以在开关盒内使用view.getId() 来定义它。

标签: android android-layout android-activity


【解决方案1】:

我从未见过有人将android:theme 属性应用于个人View,但经过一番谷歌搜索后,我发现这确实是可能的,但只是从Android 5.0 开始。

这方面的提示可以在结尾处看到here

还有更多细节here

正如第二个链接所解释的,ContextThemeWrapper 用于修改与基础Context 关联的主题。但是,由于您的Activity 需要坚持自己的主题,我只能想象创建一个新的ContextThemeWrapper 并将其分配为您的View 的新Context。由于这个新的Context 不再是你的Activity,你的回调函数在这里不存在,你会得到你描述的错误。

您可以使用调试器自己证明这一点(我使用的是 Android Studio,但您可能可以使用您选择的 IDE,细节可能会有所不同)。

  1. 在调试模式下运行应用程序并设置theme 属性。
  2. 当您收到异常时,堆栈跟踪将包含对调用onClickView 类的引用。
  3. 使用它来添加断点之前异常发生。
  4. 现在在调试模式下再次运行应用,点击按钮
  5. 当您到达断点时,计算表达式getContext()。你会看到这返回了一个ContextThemeWrapper 类型的对象,它会有一个成员mBase 指向你的实际Activity,所以getContext() 本身确实返回你的@987654343 @ 并且 没有 有你在 Activity 上定义的回调函数。
  6. 现在删除theme 属性,离开断点并再次运行应用程序。
  7. 当您遇到断点时,再次计算表达式getContext(),您将看到这一次它直接返回您的Activity,这就是您的回调工作的原因,如果您不设置theme 属性。

简而言之,如果您想使用此新功能,您似乎无法使用 android:onClick 属性,并且您必须手动分配 OnClickListener,如 here 所述

【讨论】:

  • 我们也可以用android:onClick和Fragments,我用过!
  • 我不是说你不能用,我说它没那么有用。我相信是这样,因为您正在创建片段来模块化您的 UI,然后您使用 onClick 将其牢固地绑定到特定活动。无论如何,这不是最初的问题,而且有点离题。
  • 我在最后删除了有争议的声明,因为它没有添加到答案中。我还添加了调试说明,可以准确显示正在发生的事情,因此您可以自己验证。
  • 只是想指出 AppCompat v22.1 及更高版本应该允许来自 API 11 及更高版本的单个小部件主题 android-developers.blogspot.co.nz/2015/04/…
【解决方案2】:

有时当我们为Button添加样式时,它会影响默认的android可点击行为。

尝试在&lt;Button... /&gt; 中添加属性clickable="true"

或者

您还可以在按钮样式中添加&lt;item name="android:clickable" &gt;true&lt;/item&gt;

【讨论】:

  • 按钮已经可以点击了,你没有发现我点击按钮崩溃了吗?
  • 它的意外行为。在按钮中使用样式而不是主题
  • @Azmi Ansari 但我想知道主题不起作用的原因
【解决方案3】:

在花了这么多时间之后,对我有用的是在 onCreate() 中的代码 setTheme(R.style.AppToolbar); 中应用主题,而不是从所有布局中删除所有 android:OnClick。

【讨论】:

    猜你喜欢
    • 2018-10-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 2017-06-15
    • 1970-01-01
    • 2015-09-18
    • 2013-09-23
    • 2017-02-26
    相关资源
    最近更新 更多