How to get drawable resources on FAB in Android

211 views Asked by At

I am trying to use a FAB with Bottom NavigationView in my app. I have designed drawable xml resources for that FAB to give the FAB gradient color and an icon along with a drop shadow of custom color. But the problem is when I try to get the drawable xml resource on FAB background attribute it doesn't work and the app crash. I am using Android Studio version 4.2.2 with Android Gradle plugin version 4.1.3 and Gradle Version 6.7.1.

Code for FAB with Bottom Navigation View

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    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"
    android:clipChildren="false"
    android:clipToPadding="false"
    tools:context=".MainActivity">

    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bottomAppBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:fabCradleMargin="5dp"
        android:clipChildren="true"
        android:clipToPadding="true"
        app:fabCradleVerticalOffset="10dp">
<!--        app:fabCradleRoundedCornerRadius="10dp"-->

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottomNavigationView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:labelVisibilityMode="labeled"
            app:itemIconSize="15dp"
            android:background="@android:color/transparent"
            app:itemBackground="@android:color/transparent"
            app:itemTextAppearanceActive="@style/BottomNavigationView.Active"
            app:itemTextAppearanceInactive="@style/BottomNavigationView"
            android:layout_marginEnd="16dp"
            app:menu="@menu/scan_app_menu" />

<!--android:background="@null"-->

    </com.google.android.material.bottomappbar.BottomAppBar>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:tint="@color/white"
        android:src="@drawable/scanqr"
        android:background="@drawable/gradient_color_for_scanning_btn"
        app:layout_anchor="@id/bottomAppBar"/>


    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Drawable xml resource Code called: gradient_color_for_scanning_btn

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="50dp"
            android:shape="oval">

            <corners android:radius="10dp" />

            <gradient
                android:startColor="#1fb8fc"
                android:angle="18"
                android:endColor="#0A5F8A" />

        </shape>
    </item>
    <item
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp">
        <bitmap
            android:gravity="center"
            android:src="@drawable/scanqr" />
    </item>
</layer-list>

My dependencies

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30

    defaultConfig {
        applicationId "com.kamranullah.bottomnavscanapp"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        vectorDrawables.useSupportLibrary = true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.3.0-alpha03'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

Logcat Result:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.kamranullah.bottomnavscanapp/com.kamranullah.bottomnavscanapp.MainActivity}: **android.view.InflateException: Binary XML file line #40: Binary XML file line #40: Error inflating class com.google.android.material.floatingactionbutton.FloatingActionButton**
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3320)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3416)
    at android.app.ActivityThread.access$1100(ActivityThread.java:229)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:7410)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
 **Caused by: android.view.InflateException: Binary XML file line #40: Binary XML file line #40: Error inflating class com.google.android.material.floatingactionbutton.FloatingActionButton**
    at android.view.LayoutInflater.inflate(LayoutInflater.java:551)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:380)
    at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699)
    at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
    at com.kamranullah.bottomnavscanapp.MainActivity.onCreate(MainActivity.java:30)
    at android.app.Activity.performCreate(Activity.java:6904)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1136)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3267)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3416) 
    at android.app.ActivityThread.access$1100(ActivityThread.java:229) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:7410) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
 **Caused by: android.view.InflateException: Binary XML file line #40: Error inflating class com.google.android.material.floatingactionbutton.FloatingActionButton**
    at android.view.LayoutInflater.createView(LayoutInflater.java:657)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:776)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:847)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:527)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:429) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:380) 
    at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699) 
    at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195) 
    at com.kamranullah.bottomnavscanapp.MainActivity.onCreate(MainActivity.java:30) 
    at android.app.Activity.performCreate(Activity.java:6904) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1136) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3267) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3416) 
    at android.app.ActivityThread.access$1100(ActivityThread.java:229) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:7410) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
 **Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.newInstance(Native Method)**
    at android.view.LayoutInflater.createView(LayoutInflater.java:631)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:776) 
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:847) 
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:527) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:429) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:380) 
    at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699) 
    at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195) 
    at com.kamranullah.bottomnavscanapp.MainActivity.onCreate(MainActivity.java:30) 
    at android.app.Activity.performCreate(Activity.java:6904) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1136) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3267) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3416) 
    at android.app.ActivityThread.access$1100(ActivityThread.java:229) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:7410) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
 **Caused by: android.content.res.Resources$NotFoundException: File res/drawable/gradient_color_for_scanning_btn.xml from drawable resource ID #0x7f070072**
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:4287)
    at android.content.res.Resources.loadDrawable(Resources.java:4156)
    at android.content.res.Resources.loadDrawable(Resources.java:4006)
    at android.content.res.TypedArray.getDrawable(TypedArray.java:886)
    at android.view.View.<init>(View.java:4249)
    at android.widget.ImageView.<init>(ImageView.java:150)
    at android.widget.ImageButton.<init>(ImageButton.java:85)
    at android.widget.ImageButton.<init>(ImageButton.java:81)
    at com.google.android.material.internal.VisibilityAwareImageButton.<init>(VisibilityAwareImageButton.java:47)
    at com.google.android.material.floatingactionbutton.FloatingActionButton.<init>(FloatingActionButton.java:207)
    at com.google.android.material.floatingactionbutton.FloatingActionButton.<init>(FloatingActionButton.java:201)
    at java.lang.reflect.Constructor.newInstance(Native Method) 
    at android.view.LayoutInflater.createView(LayoutInflater.java:631) 
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:776) 
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:847) 
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:527) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:429) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:380) 
    at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699) 
    at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195) 
    at com.kamranullah.bottomnavscanapp.MainActivity.onCreate(MainActivity.java:30) 
    at android.app.Activity.performCreate(Activity.java:6904) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1136) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3267) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3416) 
    at android.app.ActivityThread.access$1100(ActivityThread.java:229) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:7410) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
 **Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #10<gradient> tag requires 'angle' attribute to be a multiple of 45**

What I want to achieve: Needed is encircled with red line

1

There are 1 answers

4
Cheticamp On

It looks like the root issue is identified by the following line in the logcat trace:

**Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #10<gradient> tag requires 'angle' attribute to be a multiple of 45**

The angle that you have in the drawable is 18. From the documenation for ShapeDrawable:

<gradient> Specifies a gradient color for the shape.

attributes:

android:angle Integer. The angle for the gradient, in degrees. 0 is left to right, 90 is bottom to top. It must be a multiple of 45. Default is 0.

Try changing the angle to a multiple of 45 to see if that eliminates the crash. If so, you can then address how to otherwise go about getting the drawable you need.


Update:

I assume that the crash problem is resolved, but you don't see the FAB you want. It doesn't seem that the background attribute of the FAB is supported. Try the following:

gradient_color_for_scanning_btn.xml
This will get the rotated background without the crash. From the image you posted, it looks like a -90 degree rotation on the shape will get you what you want. If you find you need a rotation other than the -90 degree rotation, uncomment the rotate tag and specify the rotation you want.

I also added a ripple since the ripple will be lost on the true FAB background since it is covered up.

<layer-list>
    <item>
        <ripple android:color="@color/black">
            <item>
<!--                <rotate-->
<!--                    android:fromDegrees="90"-->
<!--                    android:pivotX="50%"-->
<!--                    android:pivotY="50%"-->
<!--                    android:toDegrees="90">-->
                        <shape android:shape="oval">
                            <gradient
                                android:angle="-90"
                                android:endColor="#0A5F8A"
                                android:startColor="#1fb8fc" />
                        </shape>
<!--                </rotate>-->
            </item>
        </ripple>
    </item>
    <item
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp">
        <bitmap
            android:gravity="center"
            android:src="@drawable/scanqr" />
    </item>
</layer-list>

Finally, define the FAB in the layout:

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:src="@drawable/gradient_color_for_scanning_btn"
    app:maxImageSize="56dp"/>

You should now see something like this:

enter image description here