Content Widget (Android)

Content widget is a feature in the Software Development Kit that allows you to embed an easily customizable view with recommendations in your application.

Two view layouts are available:

  • Horizontal slider - a single row view that slides horizontally on the screen.
  • Grid view - can be displayed as full- or half-screen grid layout within your app.

Both views offer a number of configuration options that allow you to style the view consistently in the app. Additionally, the Content widget automatically tracks 4 events:

  • recommendation.seen or recommendation.view (depending on configuration) sent when a recommended item is visible to the customer.
Recommendation.seen event
Recommendation.seen event
  • recommendation.click sent when a customer clicks the recommended item.
Recommendation.click event
Recommendation.click event
  • product.like sent when a customer clicks a selectable button in the recommendation. (The button must be added)
Event sent when a user clicks the
Event sent when a user clicks the "like" button on an item
  • product.dislike sent when a customer clicks a selectable button in the recommendation a second time. (The button must be added)
Product.dislike event
Product.dislike event
Note: Currently, the widget can only be used for displaying AI recommendations.

Prerequisites


To use the content widget feature, you must:

  • Obtain a customer token from Customer Authentication.

  • Create an AI Recommendation.

  • Create a document.
    Such a document should contain the following content:

    {
    	"name": "Similar Products",
    	"recommendations": "{% recommendations_json3 campaignId=COhsCCOdu8Cg %} {% endrecommendations_json3 %}"
    }
        

  • In the notepad, save the document’s slug and the ID of the recommendation for later use.

Tip: It’s a good practice to name slugs based on the area of the app that you want to place the content in, for example product-details, menu, and so on.

Basic implementation


Configure the ContentWidgetOptions and ContentWidgetAppearance settings first.

Class Description
ContentWidgetOptions Contains options for business logic, such as the slug, product identifier, and so on. Read more.
ContentWidgetAppearance Contains the UI configuration. Read more.

The example below is the most basic implementation.

String productId = "10214";
String slug = "similar";
        
ContentWidgetOptions options = new ContentWidgetRecommendationsOptions(this, slug, new OnRecommendationModelMapper() {
            @Override
            public ContentWidgetRecommendationDataModel onRecommendationMapping(Recommendation recommendation) {
            // Mapping provided by 
            	HashMap<String, Object> data = recommendation.getFeed();
                String imageLink = (String) data.get("imageLink");
                String productName = (String) data.get("title");

                String price = null;
                String salePrice = null;
                try {
                    JSONObject json = new JSONObject(data.get("price").toString());
                    price = json.getString("value");
                    if (data.containsKey("salePrice")) {
                        JSONObject jsonSalePrice = new JSONObject(data.get("salePrice").toString());
                        salePrice = jsonSalePrice.getString("value");
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return new ContentWidgetRecommendationDataModel(productName, imageLink, price, salePrice, null);
            }
        });
options.attributes.put(ContentWidgetOptions.ContentWidgetOptionsAttributeKeyProductId, productId);
ContentWidgetItemLayout itemLayoutDetails = new ContentWidgetItemLayout();
ContentWidgetHorizontalSliderLayout layout = new ContentWidgetHorizontalSliderLayout();
ContentWidgetAppearance contentWidgetAppearance = new ContentWidgetAppearance(layout, itemLayoutDetails);
ContentWidget widget = new ContentWidget(options, contentWidgetAppearance);

View view = widget.getView(); // our widget
insertPoint.addView(view); // your view which will receive widget

Widget options


The ContentWidgetRecommendationOptions class is responsible for defining the business logic options of the widget, for example:

  • document slug
  • product identifier (which is stored inside class instance in attributes HashMap)
  • recommendation model mapper

The table explains the parameters that can be configured in ContentWidgetRecommendationOptions.

Parameter Type Default Description
activity Activity - Activity to which you insert the widget (must be included)
slug String - Slug responsible for generating data
attributes Hashmap - Custom attributes for generating data
mapper OnRecommendationModelMapper - Mapper responsible for mapping data from feed to contentWidgetRecommendation model
recommendationEventType RecommendationEventType - Recommendation event type.
  • RECOMMENDATION_VIEW_EVENT sends all products in one event. We highly recommend using this type of event in content widget.
  • RECOMMENDATION_SEEN_EVENT sends each event as a separate event.

Example

String productId = "10214";
String slug = "similar";
ContentWidgetOptions options = new ContentWidgetRecommendationsOptions(this, slug, new OnRecommendationModelMapper() {
            @Override
            public ContentWidgetRecommendationDataModel onRecommendationMapping(Recommendation recommendation) {
            // here you should implement your mapping to SyneriseModel
            	HashMap<String, Object> data = recommendation.getFeed();
                String imageLink = (String) data.get("imageLink");
                String productName = (String) data.get("title");

                String price = null;
                String salePrice = null;
                try {
                    JSONObject json = new JSONObject(data.get("price").toString());
                    price = json.getString("value");
                    if (data.containsKey("salePrice")) {
                        JSONObject jsonSalePrice = new JSONObject(data.get("salePrice").toString());
                        salePrice = jsonSalePrice.getString("value");
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return new ContentWidgetRecommendationDataModel(productName, imageLink, price, salePrice, null);
            }
        });
options.attributes.put(ContentWidgetOptions.ContentWidgetOptionsAttributeKeyProductId, productId);
Tip: The recommendation response depends on your item feed.
In order to map your item feed, override onRecommendationMapping and inside it return ContentWidgetRecommendationDataModel.
The configuration of the data frames is available in AI engine configuration. It is defined separately for each item feed.

Appearance configuration


The ContentWidgetAppearance class is responsible for defining the appearance of the widget.

The class consists of parameters that define the widget’s appearance, however, two of them are the most important:

  • Main layout class: defines the way of distributing elements in the widget. Currently, two layouts are provided:
    • ContentWidgetHorizontalSliderLayout
    • ContentWidgetGridLayout
  • Item layout class: defines appearance and parameters for the item in the widget. Currently, there is only one layout provided: ContentWidgetBaseItemLayout.

The table explains the parameters that can be configured in ContentWidgetAppearance.

Parameter Type Default Description
layout ContentWidgetBaseLayout - Class that inherits from ContentWidgetBaseLayout, contains the UI details of the widget’s layout
itemLayout ContentWidgetBaseItemLayout - Class that inherits from ContentWidgetBaseItemLayout, contains the UI details of a single item in a widget

Layouts

Horizontal slider


This layout is intended to present recommendations in a fixed-hight horizontal scrollable slider.

Each item in the slider is called a card.

Click to see a screen with example widget with horizontal slider

Content Widget - Horizontal Slider

Parameters

The table below contains the parameters that can be configured in ContentWidgetHorizontalSliderLayout.

Parameter Type Default Description
cardViewSize ViewGroup.LayoutParams 0 Size of a single item (cardView). You can provide this parameter in dp (recommended) or px.
cardViewHorizontalSpacing Int 0 Horizontal spacing between items. You can provide this parameter in dp (recommended) or px.
cardViewBackgroundColor Int #fff Background color of a cardView
Tip: CardViewSize can be set either by attribution or by a setter.

Example

ContentWidgetHorizontalSliderLayout layout = new ContentWidgetHorizontalSliderLayout();

layout.setCardViewSize(250, 300);
layout.cardViewHorizontalSpacing = 15;
layout.cardViewBackgroundColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.regent);

Grid view


This layout presents recommendations in a vertical scrollable grid, with elements organized into columns and rows. You can create a full- or half-screen widget.

Click to see a screen with example widget with grid layout

Content Widget - Grid View

Constructor

Parameter Type Default Description
preferredWidth Float - Preferred width of your widget. You can pass the width in dp (recommended) or px
float screenWidthDp = displayMetrics.widthPixels;
ContentWidgetGridLayout layout = new ContentWidgetGridLayout(screenWidthDp);

Parameters

The table contains the parameters that can be configured in ContentWidgetGridLayout.

Parameter Type Default Description
cardViewSize ViewGroup.LayoutParams 0 Size of a single item (cardView)
cardViewVerticalSpacing Int 0 Vertical spacing between items in dp or px
cardViewHorizontalSpacing Int 0 Horizontal spacing between items in dp or px
cardViewBackgroundColor Int #fff Background color of a cardView
includeEdgeSpacing Boolean false When true, edge spacing is enabled
Tip: CardViewSize and preferredWidth can be set by attribution or by a setter.

Example

float screenWidthDp = displayMetrics.widthPixels;
ContentWidgetGridLayout layout = new ContentWidgetGridLayout(screenWidthDp);

layout.setCardViewSize(250, 300);
layout.cardViewHorizontalSpacing = 15;
layout.cardViewVerticalSpacing = 20;
layout.includeEdgeSpacing = false;
layout.cardViewBackgroundColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.regent);

Basic item layout


This is the basic layout for items. It contains: the image, the title, and the price from the uploaded data.

Parameters

The table below contains parameters that can be configured in ContentWidgetItemLayout.

Parameter Type Default Description
imageHeightToCardHeightRatio Double 0.6 Image height. A ratio of 0.6 means that the image height equals 60% of the entire height of an item
imageWidthToCardWidthRatio Double 1 Image width. 1 means that the image width is equal to the width of the item
imageScaleType ImageView.ScaleType ImageView.ScaleType.CENTER_INSIDE Scaling type of the image
imageMargin Int 0 General margin of the image
itemLabelStyle Typeface - Typeface of the label
itemLabelSize Int 12 Size of the label
itemLabelColor Int #000 Label text color
itemLabelMarginLeft Int 0 Left margin of the label text
itemLabelMarginRight Int 0 Right margin of the label text
itemLabelMarginBottom Int 0 Bottom margin of the label text
itemLabelMarginTop Int 0 Top margin of the label text
cardViewCornerRadius Float 0 Corner radius of the cardView
cardViewElevation Float 0 Elevation of the cardView
itemTitleStyle Typeface - Typeface of the product title
itemTitleSize Int 12 Size of the title
itemTitleColor Int #000 Color of the title text
itemTitleMarginLeft Int 0 Left margin of the title text
itemTitleMarginRight Int 0 Right margin of the title text
itemTitleMarginBottom Int 0 Bottom margin of the title text
itemTitleMarginTop Int 0 Top margin of the title text
itemPriceStyle Typeface - Typeface of the price
itemPriceSize Int 12 Size of the price text
itemPriceColor Int #000 Color of the price text
itemPriceMarginLeft Int 0 Left margin of the price text
itemPriceMarginRight Int 0 Right margin of the price text
itemPriceMarginTop Int 0 Top margin of the price text
itemPriceMarginBottom Int 0 Bottom margin of the price text
itemSalePriceStyle Typeface - Typeface of the sale price
itemSalePriceSize Int 12 Size of the sale price
itemSalePriceColor Int #000 Color of the sale price text
itemSalePriceGravity Int Gravity.LEFT Gravity of the sale price text
itemSalePriceMarginLeft Int 0 Left margin of the sale price text
itemSalePriceMarginRight Int 0 Right margin of the sale price text
itemSalePriceMarginTop Int 0 Top margin of the sale price text
itemSalePriceMarginBottom Int 0 Bottom margin of the sale price text
itemSalePriceOrientation Int LinearLayout.HORIZONTAL Orientation of the sale price text
isItemSalePriceVisible boolean false Flag determining whether to show the sale price or not
itemDiscountPercentageLabelStyle Typeface - Typeface of discount percentage label
itemDiscountPercentageLabelColor Int #000 Color of discount percentage label
itemDiscountPercentageLabelSize Int 12 Size of the discount percentage label text
itemDiscountPercentageLabelMarginLeft Int 0 Left margin of the discount percentage label text
itemDiscountPercentageLabelMarginRight Int 0 Right margin of the discount percentage label text
itemDiscountPercentageLabelMarginTop Int 0 Top margin of the discount percentage label text
itemDiscountPercentageLabelMarginBottom Int 0 Bottom margin of the discount percentage label text
isItemDiscountPercentageLabelVisible boolean false Flag determining whether to show the discount percentage label or not
itemActionButton ImageButtonCustomAction - Object which stores all information about the ActionButton
itemBadge ContentWidgetBadge - Object which stores all information about the Badge
imageButtonCustomActionGravity Int Gravity.TOP Gravity of the actionButton
Important:
  • You can combine the Gravity.* parameters. For example, to align an item to top and right, use: Gravity.TOP | Gravity.RIGHT
  • All text elements are centered horizontally.
Tip: ItemTitleMargins, ItemPriceMargins, ItemLabelMargins, ItemSalePriceMargins, and ItemDiscountLabelMargins can be set using setters, as shown below.
public void setItemTitleMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)

Example

ContentWidgetItemLayout itemLayoutDetails = new ContentWidgetItemLayout();
itemLayoutDetails.cardViewElevation = 5;
itemLayoutDetails.cardViewCornerRadius = 10;
itemLayoutDetails.imageHeightToCardHeightRatio = 0.6
itemLayoutDetails.imageWidthToCardWidthRatio = 1;
itemLayoutDetails.imageMargin = 5;
itemLayoutDetails.itemTitleStyle = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
itemLayoutDetails.itemTitleSize = 12;
itemLayoutDetails.itemTitleColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.charcoal);
itemLayoutDetails.itemTitleGravity = Gravity.LEFT;
itemLayoutDetails.setItemTitleMargins(10, 0, 0, 0);
itemLayoutDetails.itemPriceStyle = Typeface.create("sans-serif-light", Typeface.BOLD);
itemLayoutDetails.itemPriceSize = 12;
itemLayoutDetails.itemPriceColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.charcoal);
itemLayoutDetails.itemPriceGravity = Gravity.LEFT;
itemLayoutDetails.setItemPriceMargins(10, 0, 3, 0);

Interaction with the widget

Public interface


load() - Starts fetching data and creates a view structure of the widget.

getView() - Gets the root view of the whole widget view structure.

onContentWidgetListener is used to inform developers about the state of a widget. Read more below.

Listener


  • onLoading(ContentWidget contentWidget, boolean isLoading) - Called when the widget loading state changes.
  • onLoad(ContentWidget contentWidget) - Called after the widget is loaded.
  • onLoadingError(ContentWidget contentWidget, ApiError apiError) - Called when an error occurs while loading.
  • onSizeChange(ContentWidget contentWidget, ViewGroup.LayoutParams size) - Called when the widget size changes.
  • onClickActionReceive(ContentWidget contentWidget, BaseModel model) - Called when the customer clicks a widget item.

Image button custom action

ImageButtonCustomAction is used to add imageButton to your widget. You can add a singleStateButton or a selectableButton.

Parameters

The following table contains the parameters that can be configured in ImageButtonCustomAction.

Parameter Type Default Description
predefinedAction PredefinedActionType null PredefinedAction determines which event is sent on click
marginLeft Int 0 Left margin of the image button
marginRight Int 0 Right margin of the image button
marginTop Int - Top margin of the image button
marginBottom Int 0 Bottom margin of the image button
Tip: ImageButtonCustomAction margins can be set using setters, as shown below.
public void setImageButtonCustomActionMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)

The following table contains the parameters that can be configured in ContentWidgetBadge.

Parameter Type Default Description
textStyle Typeface - Typeface of the text badge
textSize Int 12 Size of the badge text
rule Int RelativeLayout.ALIGN_LEFT Rule deremining position of a badge. Can be ALIGN_LEFT or ALIGN_RIGHT
paddingLeft Int 0 Left padding of the badge text
paddingRight Int 0 Right padding of the badge text
paddingTop Int 0 Top padding of the badge text
paddingBottom Int 0 Bottom padding of the badge text
marginLeft Int 0 Left margin of the badge
marginRight Int 0 Right margin of the badge
marginTop Int - Top margin of the badge
marginBottom Int 0 Bottom margin of the badge
Tip: ContentWidgetBadge margins and paddings can be set using setters, as shown below.
public void setMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
public void setPaddings(int paddingLeft, int paddingRight, int paddingTop, int paddingBottom)

setStateDrawables

This method is responsible for passing icons to the image button.

Method name: imageButtonCustomAction.setStateDrawables(dislikeIcon, likeIcon)

Declaration

public void setStateDrawables(@NonNull Drawable defaultStateDrawable, @Nullable Drawable selectedStateDrawable)

Parameters

Parameter Type Mandatory Default Description
defaultStateDrawable Drawable yes Icon that appears in default and false state
selectedStateDrawable Drawable no Icon that appears in the selected state

Return Value

Void type

Example

Drawable likeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart);
Drawable unlikeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart_outline);
favouriteIcon.setStateDrawables(unlikeHeart, likeHeart);
Note: If you want a singleStateButton, pass null instead of selectedStateDrawable.

Public interface

Set a listener by using setOnItemActionListener.

OnActionItemStateListener is used to inform developers about the state of an ImageButton.

Listener

  • onReceiveClickAction(BaseModel model, boolean isSelected, ImageButton imageButton) - called when the customer clicks the image button in the widget.
  • onStateCheck(BaseModel model) - called before showing the view, when selectableImageButton needs information about the button state.

Example

The example shows how to implement the “like” button.

ImageButtonCustomAction favouriteIcon = new ImageButtonCustomAction();
        Drawable likeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart);
        Drawable unlikeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart_outline);
        favouriteIcon.setStateDrawables(unlikeHeart, likeHeart);
        favouriteIcon.setImageButtonCustomActionMargins(0, 0, 0, 0);
        favouriteIcon.predefinedAction = PredefinedActionType.SEND_LIKE_EVENT;
        favouriteIcon.setOnItemActionListener(new OnActionItemStateListener() {
            @Override
            public void onReceiveClickAction(BaseModel model, boolean isSelected, ImageButton imageButton) {
                Recommendation recommendation = (Recommendation) model;
                ViewUtils.pulse(imageButton);
            }

            @Override
            public boolean onStateCheck(BaseModel model) {
                return false;
            }
        });

        itemLayoutDetails.setItemAction(favouriteIcon);

Sample implementations

Horizontal slider

Slider layout with a fixed height.

public void loadWidget() {
    String productId = "10214";
    String slug = "similar";
    ContentWidgetOptions options = new ContentWidgetRecommendationsOptions(this, slug, new OnRecommendationModelMapper() {
            @Override
            public ContentWidgetRecommendationDataModel onRecommendationMapping(Recommendation recommendation) {
                HashMap<String, Object> data = recommendation.getFeed();
                String imageLink = (String) data.get("imageLink");

                String productName = (String) data.get("title");

                String price = null;
                String salePrice = null;
                try {
                    JSONObject json = new JSONObject(data.get("price").toString());
                    price = json.getString("value");
                    if (data.containsKey("salePrice")) {
                        JSONObject jsonSalePrice = new JSONObject(data.get("salePrice").toString());
                        salePrice = jsonSalePrice.getString("value");
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                ContentWidgetBadgeDataModel badgeDataModel = new ContentWidgetBadgeDataModel("Example badge", Color.BLACK, Color.RED);
                ContentWidgetRecommendationDataModel dataModel = new ContentWidgetRecommendationDataModel(productName, imageLink, price, salePrice, "PLN");
                dataModel.setBadgeDataModel(badgeDataModel);
                dataModel.setLabel("Black Week");
                return dataModel;
            }});
	options.attributes.put(ContentWidgetOptions.ContentWidgetOptionsAttributeKeyProductId, productId);
        ContentWidgetBasicProductItemLayout itemLayoutDetails = new ContentWidgetBasicProductItemLayout();
        ContentWidgetHorizontalSliderLayout layout = new ContentWidgetHorizontalSliderLayout();

        //CardView parameters
        if (!cardViewWidth.getEditText().getText().toString().matches("") && !cardViewHeight.getEditText().getText().toString().matches(""))
            layout.setCardViewSize(Integer.parseInt(cardViewWidth.getEditText().getText().toString()), Integer.parseInt(cardViewHeight.getEditText().getText().toString()));
        if (!cardViewElevation.getEditText().getText().toString().matches(""))
            itemLayoutDetails.cardViewElevation = Integer.parseInt(cardViewElevation.getEditText().getText().toString());
        if (!cornerRadius.getEditText().getText().toString().matches(""))
            itemLayoutDetails.cardViewCornerRadius = Integer.parseInt(cornerRadius.getEditText().getText().toString());
        if (!horizontalSpacing.getEditText().getText().toString().matches(""))
            layout.cardViewHorizontalSpacing = Integer.parseInt(horizontalSpacing.getEditText().getText().toString());
        layout.cardViewBackgroundColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.regent);

        //Image size as ratio to cardview size
        if (!imageHeightRatio.getEditText().getText().toString().matches(""))
            itemLayoutDetails.imageHeightToCardHeightRatio = Float.parseFloat(imageHeightRatio.getEditText().getText().toString());
        if (!imageWidthRatio.getEditText().getText().toString().matches(""))
            itemLayoutDetails.imageWidthToCardWidthRatio = Float.parseFloat(imageWidthRatio.getEditText().getText().toString());
        itemLayoutDetails.imageScaleType = ImageView.ScaleType.CENTER_CROP;
        itemLayoutDetails.imageMargin = 0; //have to be set when you set cardViewElevation

        //TextView product label
        itemLayoutDetails.itemLabelSize = 12;
        itemLayoutDetails.itemLabelColor = Color.GREEN;
        itemLayoutDetails.setItemLabelMargins(0,0,2,0);

        //TextView product name
        itemLayoutDetails.itemTitleStyle = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
        itemLayoutDetails.itemTitleSize = 12;
        itemLayoutDetails.itemTitleColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.charcoal);
        itemLayoutDetails.setItemTitleMargins(10, 0, 0, 0);

        //TextView Product price
        itemLayoutDetails.itemPriceStyle = Typeface.create("sans-serif-light", Typeface.BOLD);
        itemLayoutDetails.itemPriceSize = 13;
        itemLayoutDetails.itemPriceColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.charcoal);
        itemLayoutDetails.setItemPriceMargins(10, 0, 3, 0);

        //TextView Product Sale price
        itemLayoutDetails.isItemSalePriceVisible = true;
        itemLayoutDetails.itemSalePriceStyle = Typeface.create("sans-serif", Typeface.BOLD);
        itemLayoutDetails.itemSalePriceSize = 13;
        itemLayoutDetails.itemSalePriceColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.red);
        itemLayoutDetails.itemSalePriceOrientation = LinearLayout.HORIZONTAL;
        itemLayoutDetails.setItemSalePriceMargins(4, 0, 3, 0);
        // CrossedOut Price color
        itemLayoutDetails.itemRegularPriceColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.com_facebook_blue);
        itemLayoutDetails.priceDecimalSeparator = ',';
        itemLayoutDetails.priceGroupSeparator = ' ';

        // DiscountLabel
        itemLayoutDetails.itemDiscountPercentageLabelSize = 13;
        itemLayoutDetails.isItemDiscountPercentageLabelVisible = true;
        itemLayoutDetails.itemDiscountPercentageLabelColor = Color.BLUE;
        itemLayoutDetails.itemDiscountPercentageLabelStyle = Typeface.create("sans-serif", Typeface.BOLD);
        itemLayoutDetails.setItemDiscountLabelMargins(4, 0, 3, 0);

        // Badge
        ContentWidgetBadge badge = new ContentWidgetBadge();
        badge.textSize = 12;
        badge.rule = RelativeLayout.ALIGN_LEFT; // left or right
        badge.setMargins(0,0,0,20);
        badge.setPaddings(10, 10, 0, 0);

        //ImageButton
        ImageButtonCustomAction favouriteIcon = new ImageButtonCustomAction();
        Drawable likeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart);
        Drawable unlikeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart_outline);
        favouriteIcon.setStateDrawables(unlikeHeart, likeHeart);
        favouriteIcon.setImageButtonCustomActionMargins(0, 0, 0, 0);
        favouriteIcon.predefinedAction = PredefinedActionType.SEND_LIKE_EVENT;
        favouriteIcon.setOnItemActionListener(new OnActionItemStateListener() {
            @Override
            public void onReceiveClickAction(BaseModel model, boolean isSelected, ImageButton imageButton) {
                Recommendation recommendationModel = (Recommendation) model;
                ViewUtils.pulse(imageButton);
            }

            @Override
            public boolean onStateCheck(BaseModel model) {
                return false;
            }
        });

        itemLayoutDetails.setBadge(badge);
        itemLayoutDetails.setItemAction(favouriteIcon);

        ContentWidgetAppearance contentWidgetAppearance = new ContentWidgetAppearance(layout, itemLayoutDetails);
        ContentWidget widget = new ContentWidget(options, contentWidgetAppearance);

        widget.setOnContentWidgetListener(new OnContentWidgetListener() {
            @Override
            public void onLoading(ContentWidget contentWidget, boolean isLoading) {

            }

            @Override
            public void onLoadingError(ContentWidget contentWidget, ApiError apiError) {
                Toast.makeText(getApplicationContext(), apiError.toString(),Toast.LENGTH_LONG).show();
            }

            @Override
            public void onLoad(ContentWidget contentWidget) {
                insertPoint.removeAllViews();
                View view = widget.getView(); // our widget
                insertPoint.addView(view); // your view which will receive widget
            }

            @Override
            public void onClickActionReceive(ContentWidget contentWidget, BaseModel model) {
                Recommendation recommendationModel = (Recommendation) model;
                String itemId = recommendationModel.getItemId();
                startActivity(WidgetRecommendedProductDetailsActivity.createIntent(getApplicationContext(), itemId));
            }

            @Override
            public void onSizeChange(ContentWidget contentWidget, ViewGroup.LayoutParams size) {
                ViewGroup.LayoutParams params = insertPoint.getLayoutParams();
                params.height = size.height;
                insertPoint.setLayoutParams(params);
            }
        });
}

Grid view


If you want to avoid double scroll view, set the height as shown in the widgetSizeDidChange callback.

private void loadFullScreenWidget() {
    String slug = "similar";
    String productId = "10214";
    ContentWidgetOptions options = new ContentWidgetRecommendationsOptions(this, slug, new OnRecommendationModelMapper() {
            @Override
            public ContentWidgetRecommendationDataModel onRecommendationMapping(Recommendation recommendation) {
                HashMap<String, Object> data = recommendation.getFeed();
                String imageLink = (String) data.get("imageLink");

                String productName = (String) data.get("title");

                String price = null;
                String salePrice = null;
                try {
                    JSONObject json = new JSONObject(data.get("price").toString());
                    price = json.getString("value");
                    if (data.containsKey("salePrice")) {
                        JSONObject jsonSalePrice = new JSONObject(data.get("salePrice").toString());
                        salePrice = jsonSalePrice.getString("value");
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return new ContentWidgetRecommendationDataModel(productName, imageLink, price, salePrice, null);
            }});
	options.attributes.put(ContentWidgetOptions.ContentWidgetOptionsAttributeKeyProductId, productId);
    ContentWidgetItemLayout itemLayoutDetails = new ContentWidgetItemLayout();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    float screenWidthDp = displayMetrics.widthPixels;
    ContentWidgetGridLayout layout = new ContentWidgetGridLayout(screenWidthDp);

    //CardView parameters
    layout.setCardViewSize(250, 350);
    itemLayoutDetails.cardViewElevation = 5;
    itemLayoutDetails.cardViewCornerRadius = 5;
    layout.cardViewHorizontalSpacing = 10;
    layout.cardViewVerticalSpacing = 10;
    layout.includeEdgeSpacing = false;
    layout.cardViewBackgroundColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.regent);

    //Image size as ratio to cardview size
    itemLayoutDetails.imageHeightToCardHeightRatio = 0.7;
    itemLayoutDetails.imageWidthToCardWidthRatio = 1;
    itemLayoutDetails.imageMargin = 5; //have to be set when you set cardViewElevation

    //TextView product name
    itemLayoutDetails.itemTitleStyle = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
    itemLayoutDetails.itemTitleSize = 12;
    itemLayoutDetails.itemTitleColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.charcoal);
    itemLayoutDetails.itemTitleGravity = Gravity.LEFT;
    itemLayoutDetails.setItemTitleMargins(10, 0, 10, 0);

    //TextView Product price
    itemLayoutDetails.itemPriceStyle = Typeface.create("sans-serif-light", Typeface.BOLD);
    itemLayoutDetails.itemPriceSize = 12;
    itemLayoutDetails.itemPriceColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.charcoal);
    itemLayoutDetails.itemPriceGravity = Gravity.LEFT;
    itemLayoutDetails.setItemPriceMargins(10, 0, 10, 0);
	
	//TextView Product Sale Price
	itemLayoutDetails.itemSalePriceStyle = Typeface.create("sans-serif", Typeface.BOLD)
	itemLayoutDetails.itemSalePriceSize = 13
	itemLayoutDetails.itemSalePriceColor = ContextCompat.getColor(Synerise.getApplicationContext(), R.color.red)
	itemLayoutDetails.itemSalePriceOrientation = LinearLayout.HORIZONTAL
	itemLayoutDetails.isItemSalePriceVisible = true
	itemLayoutDetails.setItemSalePriceMargins(5, 0, 3, 0)
	
	//ImageButton
	val favouriteIcon = ImageButtonCustomAction()
	val likeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart)
	val unlikeHeart = ContextCompat.getDrawable(this, R.drawable.ic_heart_outline)
	favouriteIcon.setStateDrawables(unlikeHeart, likeHeart)
	favouriteIcon.setImageButtonCustomActionMargins(0, 0, 0, 0)
	favouriteIcon.predefinedAction = PredefinedActionType.SEND_LIKE_EVENT
	favouriteIcon.setOnItemActionListener(object:OnActionItemStateListener() {
		fun onReceiveClickAction(model:BaseModel, isSelected:Boolean, imageButton:ImageButton) {
			val recommendation = model as Recommendation
			ViewUtils.pulse(imageButton)
		}
		
		fun onStateCheck(model:BaseModel):Boolean {
			// Here you should set buttonState based on a product and a customer.
			return false
		}
	})
	
	itemLayoutDetails.setItemAction(favouriteIcon)
    ContentWidgetAppearance contentWidgetAppearance = new ContentWidgetAppearance(layout, itemLayoutDetails);
    ContentWidget widget = new ContentWidget(options, contentWidgetAppearance);


    widget.setOnContentWidgetListener(new OnContentWidgetListener() {
            @Override
            public void onLoading(ContentWidget contentWidget, boolean isLoading) {

            }

            @Override
            public void onLoadingError(ContentWidget contentWidget, ApiError apiError) {
                Toast.makeText(getApplicationContext(), apiError.toString(),Toast.LENGTH_LONG).show();
            }

            @Override
            public void onLoad(ContentWidget contentWidget) {
                insertPoint.removeAllViews();
                View view = widget.getView();
                insertPoint.addView(view);
            }

            @Override
            public void onClickActionReceive(ContentWidget contentWidget, BaseModel model) {
                Recommendation recommendation = (Recommendation)model;
                startActivity(WidgetRecommendedProductDetailsActivity.createIntent(getApplicationContext(), recommendation.getProductRetailerPartNo()));
            }

            @Override
            public void onSizeChange(ContentWidget contentWidget, ViewGroup.LayoutParams size) {
                ViewGroup.LayoutParams params = insertPoint.getLayoutParams();
                params.height = size.height;
                insertPoint.setLayoutParams(params);
            }
        });
}

More information


You can find more information under the following links:

😕

We are sorry to hear that

Thank you for helping improve out documentation. If you need help or have any questions, please consider contacting support.

😉

Awesome!

Thank you for helping improve out documentation. If you need help or have any questions, please consider contacting support.

Close modal icon Placeholder alt for modal to satisfy link checker