geNia geNia - 3 months ago 50
Android Question

Slide up panel like in stock Dialer on Nexus phones

In my app, when user clicks on a contact icon, I want to display contact's information in a slide, that appears from bottom and can be swiped up to cover the whole screen, or swiped down to dissapear.

Slide layout example

I tried to use the SlidingUpPanel from umano, but I couldn't make it work as I need, because it was not designed for that.

Is there some library for that?

Answer

This is called a BottomSheet in Android. You can create your own bottom sheet simply using a view as a Child of a coordinator layout.

Add to your app build.gradle:

dependencies{
    compile 'com.android.support:design:24.1.1'
}

And then use these classes to create your own:

BottomSheetDialogFragment

BottomSheetDialog

BottomSheetBehavior

BottomSheetBehavior.BottomSheetCallback

Here is an overly simplified demo to show how to make a FrameLayout act as a bottom sheet, you can replace the contents of the FrameLayout with a Fragment and pass information to it as needed. (in your case whichever contact was clicked):

The layout:

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.sample.bottomsheetsample.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:context="com.kdotj.bottomsheetsample.MainActivity"
        tools:showIn="@layout/activity_main">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
    </RelativeLayout>

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

    <!-- Notice a few things: 
        app:layout_behavior="@string/bottom_sheet_behavior" required to act as bottom sheet
        app:behavior_peekHeight="244dp" this is the collapsed state height
        app:behavior_hideable="true" lets you swipe to dismiss the sheet
        android:elevation="@dimen/design_appbar_elevation" puts the sheet over the action bar
    -->
    <FrameLayout
        android:id="@+id/fl_bottomSheet"
        app:layout_behavior="@string/bottom_sheet_behavior"
        app:behavior_peekHeight="244dp"
        app:behavior_hideable="true"
        android:elevation="@dimen/design_appbar_elevation"
        android:background="#777"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.AppCompatTextView
            android:layout_gravity="center|top"
            android:text="Hello, Bottom Sheet!"
            android:padding="16dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </FrameLayout>

</android.support.design.widget.CoordinatorLayout>

the Activity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FrameLayout frameLayout = (FrameLayout) findViewById(R.id.fl_bottomSheet);
        final BottomSheetBehavior behavior = BottomSheetBehavior.from(frameLayout);
        behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                //... Handle the state changes
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                //.. handle sliding if you want to
            }
        });

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
            }
        });
    }
}