androidmaterial-designfloating-action-buttonmaterial-components-androidandroid-bottomappbar

How to use the fab style diamond?


How to use diamond style for fab + bottom app bar? In the sketch files on the website https://material.io/tools/theme-editor/ there are such styles fab: enter image description here

Looked at all possible styles and tags...


Solution

  • Props to Gabriele Mariotti. I used his code and changed it a little bit to give the rounded look to bottom app bar like in the original question.

    Firstly for the FAB I gave it rounded corners and rotated it 45 degrees like this:

    XML code for fab:

    <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fabHome"
            android:rotation="45"
            app:layout_anchor="@id/bottomBarHome"
            app:shapeAppearanceOverlay="@style/FabDiamondOverlay"/>
    

    The FabDiamondOverlay is:

    <style name="FabDiamondOverlay" parent="">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">15%</item>
    </style>
    

    which gives the resulting FAB:

    Diamond rounded FAB

    Now for the bottom bar XML:

    <com.google.android.material.bottomappbar.BottomAppBar
            android:id="@+id/bottomBarHome"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:backgroundTint="@color/grey"
            app:fabCradleMargin="20dp"
            app:fabCradleVerticalOffset="5dp"
            android:layout_gravity="bottom" />
    

    and this code in OnCreate method to give bottom app bar a custom look:

        BottomAppBar bar = findViewById(R.id.bottomBarHome);
    
        BottomAppBarTopEdgeTreatment topEdge = new BottomAppBarCutCornersTopEdge(
                bar.getFabCradleMargin(),
                bar.getFabCradleRoundedCornerRadius(),
                bar.getCradleVerticalOffset());
    
        MaterialShapeDrawable bottomBarBackground = (MaterialShapeDrawable) bar.getBackground();
        bottomBarBackground.setShapeAppearanceModel(
                bottomBarBackground.getShapeAppearanceModel()
                        .toBuilder()
                        .setTopRightCorner(CornerFamily.ROUNDED,75)
                        .setTopLeftCorner(CornerFamily.ROUNDED,75)
                        .setTopEdge(topEdge)
                        .build());
    

    Where BottomAppBarCutCornersTopEdge is by modifying Gabrielle's code: Source

    @Override
        @SuppressWarnings("RestrictTo")
        public void getEdgePath(float length, float center, float interpolation, ShapePath shapePath) {
            float fabDiameter = getFabDiameter();
            if (fabDiameter == 0) {
                shapePath.lineTo(length, 0);
                return;
            }
    
            float diamondSize = fabDiameter / 2f;
            float middle = center + getHorizontalOffset();
    
            float verticalOffsetRatio = cradleVerticalOffset / diamondSize;
            if (verticalOffsetRatio >= 1.0f) {
                shapePath.lineTo(length, 0);
                return;
            }
    
            float barLeftVertex = middle - (fabMargin + diamondSize - cradleVerticalOffset);
            float barRightVertex = middle + (fabMargin + diamondSize - cradleVerticalOffset);
            float depth = (diamondSize - cradleVerticalOffset + fabMargin) * interpolation;
    
            float heightArc = 25;
            float widthArc = 25;
    
            shapePath.lineTo(barLeftVertex, 0);
    
            shapePath.lineTo(middle-widthArc, depth-heightArc);
    
            shapePath.addArc(middle-widthArc-10, 35, middle+widthArc+10, depth-15, 135, -83);
    
            shapePath.lineTo(middle+widthArc, depth-heightArc);
            shapePath.lineTo(barRightVertex, 0);
    
            shapePath.lineTo(length, 0);
        }
    

    The values here were decided with hit and trial. I couldn't understand what every variable did and there seems to be really less documentation about it. But it gets the job done! Here is the final result:

    Final image