Reputation: 43
I would like to create a own FrameLayout class where I can cancel the toch event but the app crashes everytime directly with an error message.
I ran the same code with the normal FrameLayout and I got no crash. So the app crashes not because of another reason.
The FrameLayout class:
package com.example.motivationsappbetter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class MainFrameLayout extends FrameLayout {
private boolean canTouch = true;
public MainFrameLayout(@NonNull Context context) {
super(context);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (canTouch)
return super.onInterceptTouchEvent(ev);
else
return true;
}
public void setCanTouch(boolean b){
canTouch = b;
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
MainFrameLayout mainFrame;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainFrame = findViewById(R.id.main_frame);
mainFrame.getForeground().setAlpha(0);
}
}
The activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.motivationsappbetter.MainFrameLayout
android:id="@+id/main_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="56dp"
android:layout_marginBottom="56dp">
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/navigation"
tools:layout_editor_absoluteY="675dp">
</android.support.design.widget.BottomNavigationView>
</com.example.motivationsappbetter.MainFrameLayout>
<io.github.yavski.fabspeeddial.FabSpeedDial
android:id="@+id/fabspeeddial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="false"
android:layout_alignParentBottom="false"
android:layout_gravity="bottom|center"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="3dp"
app:elevation="10dp"
app:fabGravity="bottom_end"
app:fabMenu="@menu/fab_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"></io.github.yavski.fabspeeddial.FabSpeedDial>
</android.support.constraint.ConstraintLayout>
That's the error message:
2019-10-07 16:20:11.624 25601-25601/com.example.motivationsappbetter E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.motivationsappbetter, PID: 25601
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.motivationsappbetter/com.example.motivationsappbetter.MainActivity}: android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class com.example.motivationsappbetter.MainFrameLayout
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2793)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2864)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: android.view.InflateException: Binary XML file line #11: Binary XML file line #11: Error inflating class com.example.motivationsappbetter.MainFrameLayout
Caused by: android.view.InflateException: Binary XML file line #11: Error inflating class com.example.motivationsappbetter.MainFrameLayout
Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
at java.lang.Class.getConstructor0(Class.java:2204)
at java.lang.Class.getConstructor(Class.java:1683)
at android.view.LayoutInflater.createView(LayoutInflater.java:625)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:798)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:738)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:869)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:832)
at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)
at android.support.v7.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at com.example.motivationsappbetter.MainActivity.onCreate(MainActivity.java:59)
at android.app.Activity.performCreate(Activity.java:6915)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2746)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2864)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
I'll be happy about helpful answers :P
PS: Sorry for my bad english
Upvotes: 2
Views: 415
Reputation: 29724
The exception gives you the answer in the "Cause". It says that the method is not found for the constructor that takes Context
and AttrubuteSet
.
Caused by: java.lang.NoSuchMethodException: [class android.content.Context, interface android.util.AttributeSet]
Android uses different constructors for different versions - when making custom view classes, you need to include overrides for all of them:
public FrameLayout(@NonNull Context context) {...}
public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {...}
public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
@AttrRes int defStyleAttr) {...}
public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
@AttrRes int defStyleAttr, @StyleRes int defStyleRes) {...}
This way your code will run across all versions of Android, and choose the correct constructor for the version.
See completed class that shows all required methods overridden given in mohammadReza Abiri's answer
Upvotes: 1
Reputation: 1799
The custom view must have minimum one of the required public constructor that takes in Context,AttributeSet arguments :
public class MainFrameLayout extends FrameLayout {
private boolean canTouch = true;
public MainFrameLayout(@NonNull Context context) {
super(context);
}
public MainFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MainFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MainFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (canTouch)
return super.onInterceptTouchEvent(ev);
else
return true;
}
public void setCanTouch(boolean b) {
canTouch = b;
}
}
Upvotes: 2