Content widget

Content widget is a feature in our Software Development Kit that allows you to embed an easily customizable view with various types of content in your application.

Two view layouts are available:

  • Horizontal Slider - a single row view that slides horizontally within 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 events such as views or clicks within the view.

There are 4 types of events tracked automatically:

  • recommendation.seen sent when a recommended item is visible to the customer.
Recommendation.seen event
Recommendation.seen event
  • recommendation.click sent when a customer clicks on 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. Stay tuned for future development!

Prerequisites


Such a document should contain the following content:

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

Note: Take note of the Document’s slug for later use.
Tip: It’s a good practice to name slugs based on area of the app that you want to place the content in, for example product-details, menu.

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 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

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 and 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”.

Example widget configuration 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.

Example widget configuration 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

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 ContentWidgetBasicProductItemLayout.

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
itemTitleMaxLines Int 1 Maximum displayed lines of the title text
itemSubTitleStyle Typeface - Typeface of the product subtitle
itemTitleSize Int 12 Size of the title
itemSubTitleColor Int #000 Color of the subtitle text
itemSubTitleMarginLeft Int 0 Left margin of the subtitle text
itemSubTitleMarginRight Int 0 Right margin of the subtitle text
itemSubTitleMarginBottom Int 0 Bottom margin of the subtitle text
itemSubTitleMarginTop Int 0 Top margin of the subtitle text
isItemSubTitleVisible Boolean false Flag indicating visibility of subtitle
itemSubTitleGravity Int Gravity.LEFT Flag indicating gravity of subtitle
itemSubTitleMaxLines Int 1 Maximum displayed lines of the subtitle text
itemProductIdentifier Typeface - Typeface of the product identifier
itemIdentifierSize Int 12 Size of the identifier
itemIdentifierColor Int #000 Color of the identifier text
itemIdentifierMarginLeft Int 0 Left margin of the identifier text
itemIdentifierMarginRight Int 0 Right margin of the identifier text
itemIdentifierMarginBottom Int 0 Bottom margin of the identifier text
itemIdentifierMarginTop Int 0 Top margin of the identifier text
isItemIdentifierVisible Boolean false Flag indicating visibility of identifier
itemIdentifierGravity Int Gravity.LEFT Flag indicating gravity of identifier
itemIdentifierMaxLines Int 1 Maximum displayed lines of the identifier text
itemLoyaltyPointsStyle Typeface - Typeface of the loyalty points
itemLoyaltyPointsSize Int 12 Size of the loyalty points
itemLoyaltyPointsColor Int #000 Color of the loyalty points text
itemLoyaltyPointsMarginLeft Int 0 Left margin of the loyalty points text
itemLoyaltyPointsMarginRight Int 0 Right margin of the loyalty points text
itemLoyaltyPointsMarginBottom Int 0 Bottom margin of the loyalty points text
itemLoyaltyPointsMarginTop Int 0 Top margin of the loyalty points text
isItemLoyaltyPointsVisible Boolean false Flag indicating visibility of loyalty points
itemLoyaltyPointsHorizontalPosition HorizontalPosition HorizontalPosition.LEFT Flag indicating position of loyaltyPoints
itemLoyaltyPointsLabel String “Loyalty points” Label for loyalty points field
itemLoyaltyPointsLabelStyle Typeface - Typeface of the loyalty points label
itemLoyaltyPointsLabelSize Int 12 Size of the loyalty points label
itemLoyaltyPointsLabelColor Int #000 Color of the loyalty points label text
itemLoyaltyPointsLabelMarginLeft Int 0 Left margin of the loyalty points label text
itemLoyaltyPointsLabelMarginRight Int 0 Right margin of the loyalty points label text
itemLoyaltyPointsLabelMarginBottom Int 0 Bottom margin of the loyalty points label text
itemLoyaltyPointsLabelMarginTop Int 0 Top margin of the loyalty points label 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
itemPriceCurrencyHorizontalPosition HorizontalPosition HorizontalPosition.RIGHT Flag indicating position of currency
itemPriceHorizontalPosition HorizontalPosition 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
Important: Note that 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, you should 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