I have an app with a simple layout with one button. I've tried implementing an onClick using AppCompatButton
and AppCompatImageButton
. But when I run it on a Android 4.1 device, when I click on it, my app crashes (Unfortunately, App Has Stopped).
I did the same test on a Android 5.0 device, and it worked. Then tried the same but using Button
and ImageButton
instead and it worked on both.
Those Buttons have no Style nor Theme were applied. Just bare Buttons with 30 x 30 dp. Here's the code:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
app:titleTextColor="@color/white" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/adContainer"
android:layout_width="match_parent"
android:layout_height="90dp">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn"
android:layout_width="30dp"
android:layout_height="30dp"
android:onClick="btnClick" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set ActionBar to Toolbar
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
public void btnClick(View v) {
// DO SOMETHING
}
}
For the moment I'm using ImageButton
but I don't know if that will imply some compatibility issue on some Android version (I'm supporting API 16+).
Thanks.
EDIT: That's what LogCat shows when using AppCompatButton
:
10-03 17:01:36.706 1313-1313/com.example.testappcompatbutton D/AndroidRuntime: Shutting down VM
10-03 17:01:36.706 1313-1313/com.example.testappcompatbutton W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa62ba288)
--------- beginning of /dev/log/system
10-03 17:01:36.734 1313-1313/com.example.testappcompatbutton E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalStateException: Could not find a method btnClick(View) in the activity class androidx.appcompat.widget.TintContextWrapper for onClick handler on view class androidx.appcompat.widget.AppCompatButton with id 'btn'
at android.view.View$1.onClick(View.java:3578)
at android.view.View.performClick(View.java:4084)
at android.view.View$PerformClick.run(View.java:16966)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NoSuchMethodException: btnClick [class android.view.View]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getMethod(Class.java:915)
at android.view.View$1.onClick(View.java:3571)
at android.view.View.performClick(View.java:4084)
at android.view.View$PerformClick.run(View.java:16966)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Seems like it can't find the onClick method.
I've never actually seen this before, but it looks like a combination of two things:
AppCompatButton
uses a TintContextWrapper
as the context of the button viewandroid:onClick
attribute uses reflection to find the method to execute, looking inside the view's contextTogether, this means that the system is looking for btnClick()
in the wrong place, and so the app crashes.
You can solve this by setting the click listener through code rather than by using the android:onClick
attribute. In your MainActivity's onCreate()
method:
View button = findViewById(R.id.btn);
button.setOnClickListener(v -> btnClick(v));