【问题标题】:How to get drawable resources on FAB in Android如何在 Android 的 FAB 上获取可绘制资源
【发布时间】:2021-07-20 06:36:43
【问题描述】:

我正在尝试在我的应用程序中使用带有底部导航视图的 FAB。我为该 FAB 设计了可绘制的 xml 资源,以提供 FAB 渐变颜色和一个图标以及自定义颜色的阴影。但问题是当我尝试获取 FAB 背景属性上的可绘制 xml 资源时,它不起作用并且应用程序崩溃。我正在使用 Android Studio 版本 4.2.2Android Gradle 插件版本 4.1.3Gradle 版本 6.7.1

带有底部导航视图的 FAB 代码

<?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>

可绘制的 xml 资源代码调用: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>

我的依赖项

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 结果:

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**

我想要达到的目标: Needed is encircled with red line

【问题讨论】:

    标签: android xml android-layout bottomnavigationview xml-drawable


    【解决方案1】:

    看起来根本问题由 logcat 跟踪中的以下行标识:

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

    你在drawable中的角度是18。来自ShapeDrawable 的文档:

    指定形状的渐变颜色。

    属性:

    机器人:角度 整数。渐变的角度,以度为单位。 0 是从左到右,90 是从下到上。它必须是 45 的倍数。默认为 0。

    尝试将角度更改为 45 的倍数,看看是否可以消除碰撞。如果是这样,那么您可以解决如何以其他方式获取所需的可绘制对象。


    更新:

    我假设崩溃问题已解决,但您看不到所需的 FAB。似乎不支持 FAB 的背景属性。请尝试以下操作:

    gradient_color_for_scanning_btn.xml
    这将获得旋转的背景而不会崩溃。从您发布的图片来看,形状上的 -90 度旋转似乎可以满足您的需求。如果您发现需要 -90 度旋转以外的旋转,请取消注释 rotate 标记并指定所需的旋转。

    我还添加了一个波纹,因为波纹会在真正的 FAB 背景上丢失,因为它被掩盖了。

    <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>
    

    最后,在布局中定义FAB:

    <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"/>
    

    您现在应该看到如下内容:

    【讨论】:

    • 我试过你的代码,但什么也没发生,先生。 drawable 不会以任何方式影响 FAB 按钮。就像 FAB 视图上没有使用可绘制资源一样。感谢您的宝贵时间。
    • 整个按钮显示为一个黑色圆圈,图标角在背景之外,那个角也是黑色的。意味着icon和FAB无论如何都是黑色的,谢谢您的努力先生。
    • @KamranKhan 对不起,它不适合你。如果您想尝试一下,我已经在 GitHub 上发布了我的 demo project
    • 好的,先生,我会检查一下。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 2020-07-20
    相关资源
    最近更新 更多