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
Post a Comment