This question is about mobile app UI design, I've searched the web for long time for this question and didn't found any satisfying explanation - so i decided to bring it here. I'm using Android studio (Java), I have a navigation bar that is made of a LinearLayout
that contains 5 navigation buttons in it inside my activity_home.xml
, I want to make kind of a rounded 'wavy' border in the middle (not corners) of that navigation bar. something that will look like this:
I will share here some code and images of what i already have and what i want it to be.
Code:
activity_home.xml:
<LinearLayout
android:id="@+id/navigationBar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="@drawable/navigation_bar_border"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1">
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".20"
android:background="@drawable/user_icon"
android:clickable="true" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".20"
android:background="@drawable/notifications_icon"
android:clickable="true" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".20"
android:background="@drawable/add_icon"
android:clickable="true" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".20"
android:background="@drawable/search_icon"
android:clickable="true" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".20"
android:background="@drawable/home_icon"
android:clickable="true" />
</LinearLayout>
navigation_bar_border.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp" />
<gradient
android:startColor="@color/light_dark_color"
android:endColor="@color/light_dark_color"
android:angle="90"/>
</shape>
</item>
</layer-list>
What i have now:
What i want to achieve:
How can i do that?
Ah, that can be achieved by using BottomAppBarTopEdgeTreatment. How? Let's see.
First, create a function like this which returns a MaterialShapeDrawable which you can set to the LinearLayout
as:
//Suppressing a Restricted API warning as it's a part of Stock Material Libraries.
@SuppressLint("RestrictedApi")
private fun returnBottomEdgeShapeDrawable(): MaterialShapeDrawable {
//This is how you get the curve, the main ingredient.
//BottomAppBarTopEdgeTreatment() takes three parameters:
//FabMargin - Margin between Fab Button and the curve
//RoundedCornerRadius - Radius to make the corners round
//CradleVerticalOffset - Vertical offset of curve and Fab
val bottomAppBarTopEdgeTreatment = BottomAppBarTopEdgeTreatment(
2f, 8f, 2f
)
//Diameter of the curve, current as Default Fab 56Dp
bottomAppBarTopEdgeTreatment.fabDiameter = resources.getDimension(R.dimen.56dp)
//This is further the shape of the LinearLayout.
//Set Corners to 0 in your case else corners of the LinearLayout will be curved
val shapeAppearanceModel = ShapeAppearanceModel()
.toBuilder()
.setAllCornerSizes(0f)
//Including the main ingredient here
.setTopEdge(bottomAppBarTopEdgeTreatment)
.build()
//Returning the ShapeDrawable
return MaterialShapeDrawable(shapeAppearanceModel)
}
This is exact code from one of my projects. Now, use it for your LinearLayout as:
ViewCompat.setBackground(yourLinearLayout, returnBottomEdgeShapeDrawable())
Remember to give the LinearLayout
a BackgroundTint
as the above code will make the shape but in Black color.
I've commented the code to make it more understandable.
Edit: One tip, you can use it for other Views as well like ImageView and also, you can show the curve in other sides as well like left or on bottom, just use setBottomEdge()
instead of setTopEdge()
. Also, this is the exact curve you've shown aboe in the images as this is the default code of Material App Bar shared by the one of the core developers of Material Libraries, Gabriele Mariotti.