Banners - Android Material UI/UX

A banner displays a prominent message and related optional actions.

Usage 

A banner displays an important, succinct message, and provides actions for users to address (or dismiss the banner). It requires a user action to be dismissed. Banners should be displayed at the top of the screen, below a top app bar. They’re persistent and nonmodal, allowing the user to either ignore them or interact with them at any time. Only one banner should be shown at a time.



Fragment:

package com.boltuix.materialuiux.banner

import android.os.Bundle
import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.boltuix.materialuiux.ViewAnimation
import com.boltuix.materialuiux.databinding.BannerPinBinding
import com.boltuix.materialuiux.recyclerview.RecyclerViewAdapter
import com.boltuix.materialuiux.recyclerview.RecyclerViewViewModel

class BannerFragment : Fragment() {


    private lateinit var adapterOrder: RecyclerViewAdapter
    private val viewModel: RecyclerViewViewModel by viewModels()


    private var _binding: BannerPinBinding? = null

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {

        _binding = BannerPinBinding.inflate(inflater, container, false)
        return binding.root

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)


        binding.banner.visibility = View.GONE


        binding.wifiOff.setOnClickListener {
            ViewAnimation.collapse(binding.banner)
        }

        try{
            Handler(requireActivity().mainLooper).postDelayed(Runnable {
                try{
                    ViewAnimation.expand(binding.banner)
                }catch (e:Exception){}
            }, 1000)
        }catch (e:Exception){}

        binding.recyclerView.apply {
            layoutManager =LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
            hasFixedSize()
            adapterOrder = RecyclerViewAdapter(event = { _, item ->
            })
            adapter= adapterOrder
        }
        viewModel.liveNewsData.observe(viewLifecycleOwner) { response ->
            adapterOrder.submitList(response)
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

..

In the XML:

<?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"
    android:id="@+id/parent_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!--banner ui start-->
        <LinearLayout
            android:id="@+id/banner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/white"
            android:orientation="vertical"
            android:visibility="visible"
            app:layout_collapseMode="pin">

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/grey_10" />

            <LinearLayout
                android:background="#EBEDF2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:paddingHorizontal="@dimen/spacing_large"
                android:paddingVertical="@dimen/spacing_medium">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/spacing_middle"
                    android:gravity="center_vertical"
                    android:orientation="horizontal"
                    android:paddingHorizontal="@dimen/spacing_small">

                    <RelativeLayout
                        android:layout_width="50dp"
                        android:layout_height="50dp">

                        <ImageView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            app:srcCompat="@drawable/shape_circle"
                            app:tint="@color/md_theme_light_primary" />

                        <ImageView
                            android:id="@+id/icon"
                            android:layout_width="30dp"
                            android:layout_height="30dp"
                            android:layout_centerInParent="true"
                            android:paddingTop="@dimen/spacing_small"
                            app:srcCompat="@drawable/ic_signal_wifi_off"
                            app:tint="@android:color/white" />

                    </RelativeLayout>

                    <View
                        android:layout_width="@dimen/spacing_smlarge"
                        android:layout_height="0dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="You have lost connection to the internet.\nThis app is offline"
                        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
                        android:textColor="@color/grey_60" />

                </LinearLayout>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <View
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:layout_weight="1" />

                    <com.google.android.material.button.MaterialButton
                        style="@style/Widget.Material3.Button.TextButton"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="TURN ON WIFI"
                        android:id="@+id/wifiOff"
                        android:textStyle="bold"
                        android:textColor="@color/md_theme_light_primary" />

                </LinearLayout>

            </LinearLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@color/grey_10" />

        </LinearLayout>
        <!--banner ui end-->

        <androidx.core.widget.NestedScrollView
            android:id="@+id/nested_scroll_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/grey_3"
            android:scrollbars="none"
            android:scrollingCache="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:focusableInTouchMode="true"
                android:orientation="vertical">

                <HorizontalScrollView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/spacing_mxlarge"
                    android:scrollbars="none">

                    <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center_vertical"
                        android:orientation="horizontal">

                        <View
                            android:layout_width="@dimen/spacing_smlarge"
                            android:layout_height="0dp" />

                        <androidx.cardview.widget.CardView
                            android:layout_width="150dp"
                            android:layout_height="wrap_content"
                            app:cardBackgroundColor="@color/light_blue_400"
                            app:cardCornerRadius="4dp"
                            app:cardElevation="0dp"
                            app:cardUseCompatPadding="false">

                            <LinearLayout
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:background="?attr/selectableItemBackgroundBorderless"
                                android:clickable="true"
                                android:orientation="vertical"
                                android:padding="@dimen/spacing_large">

                                <RelativeLayout
                                    android:layout_width="35dp"
                                    android:layout_height="35dp">

                                    <ImageView
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:layout_centerInParent="true"
                                        app:srcCompat="@drawable/shape_circle"
                                        app:tint="@android:color/white" />

                                    <ImageView
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:layout_centerVertical="true"
                                        android:layout_marginStart="5dp"
                                        android:layout_marginTop="5dp"
                                        android:layout_marginBottom="5dp"
                                        app:srcCompat="@drawable/ic_layers"
                                        app:tint="@color/light_blue_400" />

                                </RelativeLayout>

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:layout_marginTop="@dimen/spacing_middle"
                                    android:text="UI UX DESIGN"
                                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Body2"
                                    android:textColor="@android:color/white"
                                    />


                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:layout_marginTop="@dimen/spacing_medium"
                                    android:text="532 Articles"
                                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
                                    android:textColor="@color/grey_5" />

                            </LinearLayout>

                        </androidx.cardview.widget.CardView>

                        <View
                            android:layout_width="@dimen/spacing_middle"
                            android:layout_height="0dp" />

                        <androidx.cardview.widget.CardView
                            android:layout_width="150dp"
                            android:layout_height="wrap_content"
                            app:cardBackgroundColor="@color/light_green_300"
                            app:cardCornerRadius="4dp"
                            app:cardElevation="0dp"
                            app:cardUseCompatPadding="false">

                            <LinearLayout
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:background="?attr/selectableItemBackgroundBorderless"
                                android:clickable="true"
                                android:orientation="vertical"
                                android:padding="@dimen/spacing_large">

                                <RelativeLayout
                                    android:layout_width="35dp"
                                    android:layout_height="35dp">

                                    <ImageView
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:layout_centerInParent="true"
                                        app:srcCompat="@drawable/shape_circle"
                                        app:tint="@android:color/white" />

                                    <ImageView
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:layout_centerInParent="true"
                                        android:layout_margin="5dp"
                                        app:srcCompat="@drawable/ic_local_florist"
                                        app:tint="@color/light_green_300" />

                                </RelativeLayout>

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:layout_marginTop="@dimen/spacing_middle"
                                    android:text="FASHION"
                                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Body2"
                                    android:textColor="@android:color/white"
                                    />


                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:layout_marginTop="@dimen/spacing_medium"
                                    android:text="745 Articles"
                                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
                                    android:textColor="@color/grey_5" />

                            </LinearLayout>

                        </androidx.cardview.widget.CardView>

                        <View
                            android:layout_width="@dimen/spacing_middle"
                            android:layout_height="0dp" />

                        <androidx.cardview.widget.CardView
                            android:layout_width="150dp"
                            android:layout_height="wrap_content"
                            app:cardBackgroundColor="@color/red_300"
                            app:cardCornerRadius="4dp"
                            app:cardElevation="0dp"
                            app:cardUseCompatPadding="false">

                            <LinearLayout
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:background="?attr/selectableItemBackgroundBorderless"
                                android:clickable="true"
                                android:orientation="vertical"
                                android:padding="@dimen/spacing_large">

                                <RelativeLayout
                                    android:layout_width="35dp"
                                    android:layout_height="35dp">

                                    <ImageView
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:layout_centerInParent="true"
                                        app:srcCompat="@drawable/shape_circle"
                                        app:tint="@android:color/white" />

                                    <ImageView
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:layout_centerInParent="true"
                                        android:layout_margin="5dp"
                                        app:srcCompat="@drawable/ic_videogame_asset"
                                        app:tint="@color/red_300" />

                                </RelativeLayout>

                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:layout_marginTop="@dimen/spacing_middle"
                                    android:text="GAME"
                                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Body2"
                                    android:textColor="@android:color/white"
                                    />


                                <TextView
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    android:layout_marginTop="@dimen/spacing_medium"
                                    android:text="462 Articles"
                                    android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption"
                                    android:textColor="@color/grey_5" />

                            </LinearLayout>

                        </androidx.cardview.widget.CardView>

                        <View
                            android:layout_width="@dimen/spacing_smlarge"
                            android:layout_height="0dp" />

                    </LinearLayout>

                </HorizontalScrollView>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="@dimen/spacing_middle"
                    android:layout_marginLeft="@dimen/spacing_smlarge"
                    android:layout_marginRight="@dimen/spacing_smlarge"
                    android:layout_marginTop="@dimen/spacing_mlarge"
                    android:orientation="horizontal">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Trending Products"
                        android:textStyle="bold"
                        android:textAppearance="@style/Base.TextAppearance.AppCompat.Title"
                        android:textColor="@android:color/black"
                        />

                    <View
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:layout_weight="1" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="More"
                        android:textAppearance="@style/Base.TextAppearance.AppCompat.Body2"
                        android:textColor="@color/md_theme_light_primary" />

                </LinearLayout>

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/recyclerView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_margin="@dimen/spacing_medium"
                    android:fillViewport="true"
                    android:scrollbars="vertical"
                    android:scrollingCache="true" />

            </LinearLayout>

        </androidx.core.widget.NestedScrollView>
    </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

..

Helper class: Banner is currently not available in material plugin

package com.boltuix.materialuiux;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.Transformation;

/*Banner Helper class*/
public class ViewAnimation {

    public static void expand(final View v, final AnimListener animListener) {
        Animation a = expandAction(v);
        a.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                animListener.onFinish();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        v.startAnimation(a);
    }

    public static void expand(final View v) {
        Animation a = expandAction(v);
        v.startAnimation(a);
    }

    private static Animation expandAction(final View v) {
        v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        final int targtetHeight = v.getMeasuredHeight();

        v.getLayoutParams().height = 0;
        v.setVisibility(View.VISIBLE);
        Animation a = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                v.getLayoutParams().height = interpolatedTime == 1
                        ? LayoutParams.WRAP_CONTENT
                        : (int) (targtetHeight * interpolatedTime);
                v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        a.setDuration((int) (targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
        return a;
    }

    public static void collapse(final View v) {
        final int initialHeight = v.getMeasuredHeight();

        Animation a = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if (interpolatedTime == 1) {
                    v.setVisibility(View.GONE);
                } else {
                    v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
                    v.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        a.setDuration((int) (initialHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }

    public static void flyInDown(final View v, final AnimListener animListener) {
        v.setVisibility(View.VISIBLE);
        v.setAlpha(0.0f);
        v.setTranslationY(0);
        v.setTranslationY(-v.getHeight());
        // Prepare the View for the animation
        v.animate()
                .setDuration(200)
                .translationY(0)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (animListener != null) animListener.onFinish();
                        super.onAnimationEnd(animation);
                    }
                })
                .alpha(1.0f)
                .start();
    }

    public static void flyOutDown(final View v, final AnimListener animListener) {
        v.setVisibility(View.VISIBLE);
        v.setAlpha(1.0f);
        v.setTranslationY(0);
        // Prepare the View for the animation
        v.animate()
                .setDuration(200)
                .translationY(v.getHeight())
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (animListener != null) animListener.onFinish();
                        super.onAnimationEnd(animation);
                    }
                })
                .alpha(0.0f)
                .start();
    }

    public static void fadeIn(final View v) {
        ViewAnimation.fadeIn(v, null);
    }

    public static void fadeIn(final View v, final AnimListener animListener) {
        v.setVisibility(View.GONE);
        v.setAlpha(0.0f);
        // Prepare the View for the animation
        v.animate()
                .setDuration(200)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        v.setVisibility(View.VISIBLE);
                        if (animListener != null) animListener.onFinish();
                        super.onAnimationEnd(animation);
                    }
                })
                .alpha(1.0f);
    }

    public static void fadeOut(final View v) {
        ViewAnimation.fadeOut(v, null);
    }

    public static void fadeOut(final View v, final AnimListener animListener) {
        v.setAlpha(1.0f);
        // Prepare the View for the animation
        v.animate()
                .setDuration(500)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (animListener != null) animListener.onFinish();
                        super.onAnimationEnd(animation);
                    }
                })
                .alpha(0.0f);
    }

    public static void showIn(final View v) {
        v.setVisibility(View.VISIBLE);
        v.setAlpha(0f);
        v.setTranslationY(v.getHeight());
        v.animate()
                .setDuration(200)
                .translationY(0)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                    }
                })
                .alpha(1f)
                .start();
    }

    public static void initShowOut(final View v) {
        v.setVisibility(View.GONE);
        v.setTranslationY(v.getHeight());
        v.setAlpha(0f);
    }

    public static void showOut(final View v) {
        v.setVisibility(View.VISIBLE);
        v.setAlpha(1f);
        v.setTranslationY(0);
        v.animate()
                .setDuration(200)
                .translationY(v.getHeight())
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        v.setVisibility(View.GONE);
                        super.onAnimationEnd(animation);
                    }
                }).alpha(0f)
                .start();
    }

    public static boolean rotateFab(final View v, boolean rotate) {
        v.animate().setDuration(200)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                    }
                })
                .rotation(rotate ? 135f : 0f);
        return rotate;
    }


    public interface AnimListener {
        void onFinish();
    }

    public static void fadeOutIn(View view) {
        view.setAlpha(0.f);
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator animatorAlpha = ObjectAnimator.ofFloat(view, "alpha", 0.f, 0.5f, 1.f);
        ObjectAnimator.ofFloat(view, "alpha", 0.f).start();
        animatorAlpha.setDuration(500);
        animatorSet.play(animatorAlpha);
        animatorSet.start();
    }


    public static void showScale(final View v) {
        ViewAnimation.showScale(v, null);
    }

    public static void showScale(final View v, final AnimListener animListener) {
        v.animate()
                .scaleY(1)
                .scaleX(1)
                .setDuration(200)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (animListener != null) animListener.onFinish();
                        super.onAnimationEnd(animation);
                    }
                })
                .start();
    }

    public static void hideScale(final View v) {
        ViewAnimation.fadeOut(v, null);
    }

    public static void hideScale(final View v, final AnimListener animListener) {
        v.animate()
                .scaleY(0)
                .scaleX(0)
                .setDuration(200)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (animListener != null) animListener.onFinish();
                        super.onAnimationEnd(animation);
                    }
                })
                .start();
    }

    public static void hideFab(View fab) {
        int moveY = 2 * fab.getHeight();
        fab.animate()
                .translationY(moveY)
                .setDuration(300)
                .start();
    }

    public static void showFab(View fab) {
        fab.animate()
                .translationY(0)
                .setDuration(300)
                .start();
    }

    public static void rotate(View view, boolean rotate) {
        view.animate().setDuration(200).rotation(rotate ? 180 : 0);
    }
}

..

In the dimens.xml in the value folder:

<resources>
    <!--genaral spacing-->
    <dimen name="spacing_xsmall">2dp</dimen>
    <dimen name="spacing_small">3dp</dimen>
    <dimen name="spacing_medium">5dp</dimen>
    <dimen name="spacing_xmedium">7dp</dimen>
    <dimen name="spacing_middle">10dp</dimen>
    <dimen name="spacing_large">15dp</dimen>
    <dimen name="spacing_smlarge">18dp</dimen>
    <dimen name="spacing_mlarge">20dp</dimen>
    <dimen name="spacing_mxlarge">25dp</dimen>
    <dimen name="spacing_xlarge">35dp</dimen>
    <dimen name="spacing_xmlarge">40dp</dimen>
    <dimen name="spacing_xxlarge">50dp</dimen>
    <dimen name="spacing_xxxlarge">55dp</dimen>
    <dimen name="appbar_padding_top">8dp</dimen>
</resources>

..

Comments