Carousel Push

Carousel Push functionality allows you to show your notification with a slideshow.

Requirements

  • Android SDK 2.0.0+

Before you start, you need to define your receiver in your manifest file.

Defining Custom Receiver

<receiver android:name=".MyReceiver"  
  android:exported="false">   <!-- change NotificationReceiver to .MyReceiver -->
<intent-filter>
        <action android:name="com.dengage.push.intent.RECEIVE" />
        <action android:name="com.dengage.push.intent.OPEN" />
        <action android:name="com.dengage.push.intent.DELETE" />
        <action android:name="com.dengage.push.intent.ITEM_CLICK" /> <!-- add this line-->
        <action android:name="com.dengage.push.intent.CAROUSEL_ITEM_CLICK" /><!-- add this line-->
        <action android:name="com.dengage.push.intent.ACTION_CLICK" />
      </intent-filter>
 </receiver>

Preparing Custom Layouts

The SDK uses a custom layout for the functionality. It means you need to set your layout first in your res folder. At the same time, We prepared 2 pre-build layouts that you can easily use;

  • Landscape
  • Portrait

To use them, Please add _den_carousel_landscape.xml or dencarousel_portrait.xml file to your layouts directory.

den_carousel_landscape.xml

Note: You will need to change drawable items with yours.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <include
        android:id="@+id/den_carousel_collapsed"
        layout="@layout/den_carousel_collapsed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>


    <FrameLayout
        android:id="@+id/den_carousel_frame"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/den_carousel_collapsed"
        android:layout_gravity="center"
        android:paddingLeft="16dp"
        android:paddingRight="16dp">

        <ImageView
            android:id="@+id/den_carousel_landscape_image"
            android:layout_width="match_parent"
            android:layout_height="160dp"
            android:scaleType="centerCrop"
            android:layout_gravity="center"
            />

        <ImageView
            android:id="@+id/den_carousel_left_image"
            android:layout_width="44dp"
            android:layout_height="44dp"
            android:src="@drawable/ic_carousal_left_arrow"
            android:layout_gravity="start|center_vertical"
            android:scaleType="fitXY"
            android:layout_marginStart="5dp" />

        <ImageView
            android:id="@+id/den_carousel_right_image"
            android:layout_width="44dp"
            android:layout_height="44dp"
            android:src="@drawable/ic_carousal_right_icon"
            android:layout_gravity="end|center_vertical"
            android:scaleType="fitXY"
            android:layout_marginEnd="5dp" />


    </FrameLayout>

    <LinearLayout android:id="@+id/den_carousel_item_title_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@id/den_carousel_frame"
        android:layout_marginTop="5dp"
        >
        <TextView
            android:id="@+id/den_carousel_item_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Item Title"
            />
    </LinearLayout>

    <LinearLayout android:id="@+id/den_carousel_item_description_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:layout_below="@id/den_carousel_item_title_container"
        >
        <TextView
            android:id="@+id/den_carousel_item_description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Item Description" />
    </LinearLayout>     
</RelativeLayout>

den_carousel_portrait.xml

Note: You will need to change drawable items with yours.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="320dp">

    <include
        android:id="@+id/den_carousel_collapsed"
        layout="@layout/den_carousel_collapsed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <FrameLayout
        android:id="@+id/den_carousel_body_portrait"
        android:layout_width="596dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/den_carousel_collapsed"
        android:layout_gravity="center"
        android:layout_marginBottom="8dp"
        android:paddingLeft="16dp"
        android:paddingRight="16dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center">

            <RelativeLayout
                android:id="@+id/den_carousel_left_container"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toStartOf="@+id/den_carousel_portrait_current_container"
                android:layout_toLeftOf="@+id/den_carousel_portrait_current_container">

                <ImageView
                    android:id="@+id/den_carousel_portrait_left_image"
                    android:layout_width="192dp"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:scaleType="centerCrop" />

                <RelativeLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignBottom="@+id/den_carousel_portrait_left_image"
                    android:layout_alignStart="@+id/den_carousel_portrait_left_image"
                    android:layout_alignLeft="@+id/den_carousel_portrait_left_image"
                    android:layout_alignEnd="@+id/den_carousel_portrait_left_image"
                    android:layout_alignRight="@+id/den_carousel_portrait_left_image"
                    android:layout_alignTop="@+id/den_carousel_portrait_left_image"
                    android:background="#BFffffff" />
            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/den_carousel_right_container"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toEndOf="@+id/den_carousel_portrait_current_container"
                android:layout_toRightOf="@+id/den_carousel_portrait_current_container">

                <ImageView
                    android:id="@+id/den_carousel_portrait_right_image"
                    android:layout_width="192dp"
                    android:layout_height="192dp"
                    android:layout_centerInParent="true"
                    android:scaleType="centerCrop" />

                <RelativeLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignBottom="@+id/den_carousel_portrait_right_image"
                    android:layout_alignStart="@+id/den_carousel_portrait_right_image"
                    android:layout_alignLeft="@+id/den_carousel_portrait_right_image"
                    android:layout_alignEnd="@+id/den_carousel_portrait_right_image"
                    android:layout_alignRight="@+id/den_carousel_portrait_right_image"
                    android:layout_alignTop="@+id/den_carousel_portrait_right_image"
                    android:background="#B0ffffff" />

            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/den_carousel_portrait_current_container"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true">

                <ImageView
                    android:id="@+id/den_carousel_portrait_current_image"
                    android:layout_width="212dp"
                    android:layout_height="192dp"
                    android:paddingLeft="10dp"
                    android:paddingRight="10dp"
                    android:cropToPadding="true"
                    android:scaleType="centerCrop" />


            </RelativeLayout>

        </RelativeLayout>

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp">

            <ImageView
                android:id="@+id/den_carousel_left_arrow"
                android:layout_width="44dp"
                android:layout_height="44dp"
                android:src="@drawable/ic_carousal_left_arrow"
                android:layout_gravity="start|center_vertical"
                android:scaleType="fitXY" />

            <ImageView
                android:id="@+id/den_carousel_right_arrow"
                android:layout_width="44dp"
                android:layout_height="44dp"
                android:src="@drawable/ic_carousal_right_icon"
                android:layout_gravity="end|center_vertical"
                android:scaleType="fitXY" />

        </FrameLayout>

    </FrameLayout>

    <LinearLayout android:id="@+id/den_carousel_item_title_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@id/den_carousel_body_portrait"
        >
        <TextView
            android:id="@+id/den_carousel_item_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Item Title"
            />
    </LinearLayout>

    <LinearLayout android:id="@+id/den_carousel_item_description_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@id/den_carousel_item_title_container"
        >
        <TextView
            android:id="@+id/den_carousel_item_description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Item Description" />
    </LinearLayout>
</RelativeLayout>

The above layout includes den_carousel_collapsed.xml file;

den_carousel_collapsed.xml

Note: You will need to change drawable items with yours.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp">

    <ImageView
        android:id="@+id/den_carousel_image"
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_gravity="top|end"
        android:layout_marginLeft="12dp"
        android:layout_marginStart="12dp"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher_foreground" /> <!-- Your App Icon -->

    <TextView
        android:id="@+id/den_carousel_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toStartOf="@+id/den_carousel_image"
        android:layout_toLeftOf="@id/den_carousel_image"
        android:text="Remote Title"
        android:textSize="15dp"
        android:textColor="@color/colorPrimary"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/den_carousel_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/den_carousel_title"
        android:layout_alignStart="@+id/den_carousel_title"
        android:layout_alignLeft="@+id/den_carousel_title"
        android:layout_alignEnd="@+id/den_carousel_title"
        android:layout_alignRight="@+id/den_carousel_title"
        android:layout_toLeftOf="@id/den_carousel_image"
        android:ellipsize="end"
        android:lineSpacingMultiplier="1.2"
        android:maxLines="1"
        android:text="Remote message"
        android:textSize="14dp"
        android:textColor="@color/colorPrimary"
        android:layout_marginBottom="16dp"/>

</RelativeLayout>

Please note that you can always edit these layouts or create a new one.

Building Notification

To use a custom layout for the notification requires building a message by the developer with the layout.

First, please create your receiver class extends from NotificationReceiver and override the methods below;

  • onRender
  • onReRender
class PushNotificationReceiver : NotificationReceiver() {
    override fun onCarouselRender(context: Context, intent: Intent?, message: Message?) {
        // build carousel message with a custom layout. In this case, we will use dengage_carousel_landscape.xml and dengage_carousel_portrait.xml files.
    }
    override fun onCarouselReRender(context: Context, intent: Intent?, message: Message?) {
        // Re-build carousel message with a custom layout to slide item next/prev. 
    }
}

Building Carousel

Copy the codes below to your receiver class.

class PushNotificationReceiver : NotificationReceiver() {

    override fun onCarouselRender(
        context: Context,
        intent: Intent,
        message: Message,
        leftCarouselItem: CarouselItem,
        currentCarouselItem: CarouselItem,
        rightCarouselItem: CarouselItem
    ) {
        super.onCarouselRender(
            context,
            intent,
            message,
            leftCarouselItem,
            currentCarouselItem,
            rightCarouselItem
        )

        val itemTitle = currentCarouselItem.title
        val itemDesc = currentCarouselItem.description

        // set intents (right button, left button, item click)
        val itemIntent = getItemClickIntent(intent.extras, context.packageName)
        val leftIntent = getLeftItemIntent(intent.extras, context.packageName)
        val rightIntent = getRightItemIntent(intent.extras, context.packageName)
        val deleteIntent = getDeleteIntent(intent.extras, context.packageName)
        val contentIntent = getContentIntent(intent.extras, context.packageName)

        val carouseItemIntent = getPendingIntent(context, 0, itemIntent)
        val carouselLeftIntent = getCarouselDirectionIntent(context, 1, leftIntent)
        val carouselRightIntent = getCarouselDirectionIntent(context, 2, rightIntent)
        val deletePendingIntent = getDeletePendingIntent(context, 4, deleteIntent)
        val contentPendingIntent = getPendingIntent(context, 5, contentIntent)

        // set views for the layout
        val collapsedView = RemoteViews(
            context.packageName,
            R.layout.den_carousel_collapsed
        )
        collapsedView.setTextViewText(R.id.den_carousel_title, message.title)
        collapsedView.setTextViewText(R.id.den_carousel_message, message.message)

        val carouselView = RemoteViews(
            context.packageName,
            R.layout.den_carousel_portrait
        )
        carouselView.setTextViewText(R.id.den_carousel_title, message.title)
        carouselView.setTextViewText(R.id.den_carousel_message, message.message)
        carouselView.setTextViewText(R.id.den_carousel_item_title, itemTitle)
        carouselView.setTextViewText(R.id.den_carousel_item_description, itemDesc)

        carouselView.setOnClickPendingIntent(R.id.den_carousel_left_arrow, carouselLeftIntent)
        carouselView.setOnClickPendingIntent(
            R.id.den_carousel_portrait_current_image,
            carouseItemIntent
        )
        carouselView.setOnClickPendingIntent(R.id.den_carousel_item_title, carouseItemIntent)
        carouselView.setOnClickPendingIntent(R.id.den_carousel_item_description, carouseItemIntent)
        carouselView.setOnClickPendingIntent(R.id.den_carousel_right_arrow, carouselRightIntent)

        val channelId = createNotificationChannel(context, message)

        loadCarouselImageToView(
            carouselView = carouselView,
            imageViewId = R.id.den_carousel_portrait_left_image,
            carouselItem = leftCarouselItem,
            onComplete = {
                // you can call notificationManager.notify for devices that could not show carousel image contents
            }
        )

        loadCarouselImageToView(
            carouselView = carouselView,
            imageViewId = R.id.den_carousel_portrait_current_image,
            carouselItem = currentCarouselItem,
            onComplete = {
                // you can call notificationManager.notify for devices that could not show carousel image contents
            }
        )

        loadCarouselImageToView(
            carouselView = carouselView,
            imageViewId = R.id.den_carousel_portrait_right_image,
            carouselItem = rightCarouselItem,
            onComplete = {
                // you can call notificationManager.notify for devices that could not show carousel image contents
            }
        )

        val notification = NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setCustomContentView(collapsedView)
            .setCustomBigContentView(carouselView)
            .setContentIntent(contentPendingIntent)
            .setDeleteIntent(deletePendingIntent)
            .build()

        // show message again silently with next, previous and current item.
        notification.flags = Notification.FLAG_AUTO_CANCEL or Notification.FLAG_ONLY_ALERT_ONCE

        // show message
        val notificationManager = NotificationManagerCompat.from(context)
        notificationManager.notify(
            message.messageSource,
            message.messageId,
            notification
        )
    }