Is it a good practice to wrap all layouts in CoordinatorLayout?
Asked Answered
P

3

24

I'm thinking of a way to implement Android Snackbars in my app. Basically, I want to be able to show Snackbar from anywhere in the app.

As I found out, android.support.design.widget.Snackbar performs the best when put in android.support.design.widget.CoordinatorLayout. Otherwise, I cannot swipe it away, it shows over navigation drawer and doesn't interact with Floating Action Button.

So the question is: Is it a good practice to wrap ALL my layouts in CoordinatorLayout, get the reference for it in a BaseActivity, so that it can be passed to Snackbar from almost anywhere?

That seems to be a solid way to ensure the Snackbar and other layout components behave correctly, but... well, means touching all layouts and having one BaseActivity which is extended by all other Activities and which would be accessed from any Fragment wanting to show a Snackbar.

Is there a better way?

Pellikka answered 8/4, 2016 at 17:33 Comment(1)
that is what I have done to my project.Abrogate
C
2

These are the options you have. Use one of these as you need in the project.

The best way

The best way of doing this is what you already said in your question, add a BaseActivity and extend all your activities from it. According to the official documentation of CoordinatorLayout,

CoordinatorLayout is intended for two primary use cases:

  1. As a top-level application decor or chrome layout
  2. As a container for a specific interaction with one or more child views

So CoordinatorLayout is created primarily for this reason (Though there are also other reasons). There will be the least performance issues as mentioned in the documentation.

By Using FrameLayout

As already answered by Rainmaker, you can use a Activity with a reference to the CoordinatorLayout layout in your layouts folder where the child will be a framelayout.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/activity_root"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>

Then you will be using only one activity with setContentView(R.layout.root_coordinate_layout). Then you will convert all other activities into fragments and add them with :

MyFragment myf = new MyFragment();
FragmentTransaction transaction = getFragmentManager()
    .beginTransaction()
    .add(R.id.your_layout, myf)
    .commit();

The programmatic way

This is another way of doing the same thing. But this is a bit more complex and need a lot of works to do.

In all your activity, instead of setContentView(R.id.your_layout), use this:

LayoutInflater inflater = LayoutInflater.from(this);
ConstraintLayout yourLayout = (ConstraintLayout) inflater.inflate(R.layout.your_layout, null, false);
CoordinatorLayout layout = new CoordinatorLayout(this);
// Set its property as you wish ...
layout.addView(mainScreen);
setContentView(layout);
Cloudcapped answered 17/11, 2017 at 1:47 Comment(0)
L
7

I have implemented same like open Snackbar from anywhere in application.

I have created one common method and just pass context and string message i need to display and no need to pass any view. Check out my code snippet.

 public static void showSnackBar(Activity context, String msg) {
   Snackbar.make(context.getWindow().getDecorView().findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).show();
 }

Using this, You will have your Snackbar on bottom every time.

Lightweight answered 17/11, 2017 at 5:31 Comment(5)
That does not help with the CoordinatorLayout situation. Not what I asked about at all!Pellikka
@anoniim well, your questions is Is there a better way? and I think that this answer complete Rahat's one.Vocabulary
Ye, is there a better way to use CoordinatorLayout?. Without it, snack bars are not swipeable and don't play well with other layout elements.Pellikka
this is what i need +1Ruhr
Beware that if it's not in a CoordinatorLayout, you loose the swipe-to-dismiss ability.Mobley
C
2

These are the options you have. Use one of these as you need in the project.

The best way

The best way of doing this is what you already said in your question, add a BaseActivity and extend all your activities from it. According to the official documentation of CoordinatorLayout,

CoordinatorLayout is intended for two primary use cases:

  1. As a top-level application decor or chrome layout
  2. As a container for a specific interaction with one or more child views

So CoordinatorLayout is created primarily for this reason (Though there are also other reasons). There will be the least performance issues as mentioned in the documentation.

By Using FrameLayout

As already answered by Rainmaker, you can use a Activity with a reference to the CoordinatorLayout layout in your layouts folder where the child will be a framelayout.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/activity_root"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>

Then you will be using only one activity with setContentView(R.layout.root_coordinate_layout). Then you will convert all other activities into fragments and add them with :

MyFragment myf = new MyFragment();
FragmentTransaction transaction = getFragmentManager()
    .beginTransaction()
    .add(R.id.your_layout, myf)
    .commit();

The programmatic way

This is another way of doing the same thing. But this is a bit more complex and need a lot of works to do.

In all your activity, instead of setContentView(R.id.your_layout), use this:

LayoutInflater inflater = LayoutInflater.from(this);
ConstraintLayout yourLayout = (ConstraintLayout) inflater.inflate(R.layout.your_layout, null, false);
CoordinatorLayout layout = new CoordinatorLayout(this);
// Set its property as you wish ...
layout.addView(mainScreen);
setContentView(layout);
Cloudcapped answered 17/11, 2017 at 1:47 Comment(0)
L
1

Yes, you can wrap up your layout into a coordinator layout, like

<android.support.design.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:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </android.support.design.widget.AppBarLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <Button
            android:id="@+id/btnSimpleSnackbar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="Simple Snackbar" />

        <Button
            android:id="@+id/btnActionCallback"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="With Action Callback" />

        <Button
            android:id="@+id/btnCustomSnackbar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="Custom Color" />

    </LinearLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>
Limbourg answered 17/11, 2017 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.