diff --git a/CHANGELOG.md b/CHANGELOG.md index 1432536b5..55f2649cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed +- Fixed `IterableEmbeddedView` card layout rendering issues: image now displays at a 16:9 aspect ratio instead of collapsing to zero height, card container no longer expands to fill the parent, buttons use a text style for better alignment with the campaign preview, missing end margin on the card is now applied, bottom spacing on buttons is no longer cut off, and the image properly clips to the card's rounded corners. + +### Added +- Added `imageScaleType` to `IterableEmbeddedViewConfig` to allow configuring the image scale type for embedded message views. +- Added default values to all `IterableEmbeddedViewConfig` constructor parameters for easier configuration. ## [3.7.0] - Replaced the deprecated `AsyncTask`-based push notification handling with `WorkManager` for improved reliability and compatibility with modern Android versions. No action is required. diff --git a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedView.kt b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedView.kt index 1d9c22553..8ab42c518 100644 --- a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedView.kt +++ b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedView.kt @@ -104,17 +104,17 @@ class IterableEmbeddedView() : Fragment() { val view = when (viewType) { IterableEmbeddedViewType.BANNER -> { val bannerView = inflater.inflate(R.layout.banner_view, container, false) - bind(viewType, bannerView, message) + bind(viewType, bannerView, message, config) bannerView } IterableEmbeddedViewType.CARD -> { val cardView = inflater.inflate(R.layout.card_view, container, false) - bind(viewType, cardView, message) + bind(viewType, cardView, message, config) cardView } IterableEmbeddedViewType.NOTIFICATION -> { val notificationView = inflater.inflate(R.layout.notification_view, container, false) - bind(viewType, notificationView, message) + bind(viewType, notificationView, message, config) notificationView } } @@ -167,7 +167,7 @@ class IterableEmbeddedView() : Fragment() { bodyText.setTextColor(bodyTextColor) } - private fun bind(viewType: IterableEmbeddedViewType, view: View, message: IterableEmbeddedMessage): View { + private fun bind(viewType: IterableEmbeddedViewType, view: View, message: IterableEmbeddedMessage, config: IterableEmbeddedViewConfig?): View { val embeddedMessageViewTitle: TextView = view.findViewById(R.id.embedded_message_title) val embeddedMessageViewBody: TextView = view.findViewById(R.id.embedded_message_body) val embeddedMessageViewButton: Button = view.findViewById(R.id.embedded_message_first_button) @@ -179,6 +179,7 @@ class IterableEmbeddedView() : Fragment() { if(message.elements?.mediaURL?.isEmpty() == true) { embeddedMessageImageView.visibility = View.GONE } else { + config?.imageScaleType?.let { embeddedMessageImageView.scaleType = it } Glide.with(view.context).load(message.elements?.mediaURL).into(embeddedMessageImageView) embeddedMessageImageView.contentDescription = message.elements?.mediaUrlCaption } diff --git a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewArguments.kt b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewArguments.kt index a85850dd4..0bba74262 100644 --- a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewArguments.kt +++ b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewArguments.kt @@ -1,6 +1,7 @@ package com.iterable.iterableapi.ui.embedded import android.os.Bundle +import android.widget.ImageView import com.iterable.iterableapi.IterableEmbeddedMessage import com.iterable.iterableapi.IterableLogger import org.json.JSONException @@ -23,6 +24,7 @@ internal object IterableEmbeddedViewArguments { private const val KEY_SECONDARY_BTN_TEXT = "secondary_btn_text" private const val KEY_TITLE_COLOR = "title_color" private const val KEY_BODY_COLOR = "body_color" + private const val KEY_IMAGE_SCALE_TYPE = "image_scale_type" fun toBundle( viewType: IterableEmbeddedViewType, @@ -78,7 +80,8 @@ internal object IterableEmbeddedViewArguments { arguments.containsKey(KEY_SECONDARY_BTN_BG) || arguments.containsKey(KEY_SECONDARY_BTN_TEXT) || arguments.containsKey(KEY_TITLE_COLOR) || - arguments.containsKey(KEY_BODY_COLOR) + arguments.containsKey(KEY_BODY_COLOR) || + arguments.containsKey(KEY_IMAGE_SCALE_TYPE) return if (hasConfig) { IterableEmbeddedViewConfig( @@ -91,7 +94,15 @@ internal object IterableEmbeddedViewArguments { secondaryBtnBackgroundColor = arguments.getIntOrNull(KEY_SECONDARY_BTN_BG), secondaryBtnTextColor = arguments.getIntOrNull(KEY_SECONDARY_BTN_TEXT), titleTextColor = arguments.getIntOrNull(KEY_TITLE_COLOR), - bodyTextColor = arguments.getIntOrNull(KEY_BODY_COLOR) + bodyTextColor = arguments.getIntOrNull(KEY_BODY_COLOR), + imageScaleType = arguments.getStringOrNull(KEY_IMAGE_SCALE_TYPE)?.let { + try { + ImageView.ScaleType.valueOf(it) + } catch (e: IllegalArgumentException) { + IterableLogger.e(TAG, "Invalid image scale type: $it, using default") + null + } + } ) } else { null @@ -110,6 +121,7 @@ internal object IterableEmbeddedViewArguments { cfg.secondaryBtnTextColor?.let { putInt(KEY_SECONDARY_BTN_TEXT, it) } cfg.titleTextColor?.let { putInt(KEY_TITLE_COLOR, it) } cfg.bodyTextColor?.let { putInt(KEY_BODY_COLOR, it) } + cfg.imageScaleType?.let { putString(KEY_IMAGE_SCALE_TYPE, it.name) } } } @@ -120,4 +132,8 @@ internal object IterableEmbeddedViewArguments { private fun Bundle.getFloatOrNull(key: String): Float? { return if (containsKey(key)) getFloat(key) else null } + + private fun Bundle.getStringOrNull(key: String): String? { + return if (containsKey(key)) getString(key) else null + } } diff --git a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewConfig.kt b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewConfig.kt index 7b0b9f5f1..2dee3f023 100644 --- a/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewConfig.kt +++ b/iterableapi-ui/src/main/java/com/iterable/iterableapi/ui/embedded/IterableEmbeddedViewConfig.kt @@ -1,14 +1,17 @@ package com.iterable.iterableapi.ui.embedded +import android.widget.ImageView + data class IterableEmbeddedViewConfig( - val backgroundColor: Int?, - val borderColor: Int?, - val borderWidth: Int?, - val borderCornerRadius: Float?, - val primaryBtnBackgroundColor: Int?, - val primaryBtnTextColor: Int?, - val secondaryBtnBackgroundColor: Int?, - val secondaryBtnTextColor: Int?, - val titleTextColor: Int?, - val bodyTextColor: Int? + val backgroundColor: Int? = null, + val borderColor: Int? = null, + val borderWidth: Int? = null, + val borderCornerRadius: Float? = null, + val primaryBtnBackgroundColor: Int? = null, + val primaryBtnTextColor: Int? = null, + val secondaryBtnBackgroundColor: Int? = null, + val secondaryBtnTextColor: Int? = null, + val titleTextColor: Int? = null, + val bodyTextColor: Int? = null, + val imageScaleType: ImageView.ScaleType? = null ) \ No newline at end of file diff --git a/iterableapi-ui/src/main/res/layout-v21/card_view.xml b/iterableapi-ui/src/main/res/layout-v21/card_view.xml index d481ffe23..e48487a17 100644 --- a/iterableapi-ui/src/main/res/layout-v21/card_view.xml +++ b/iterableapi-ui/src/main/res/layout-v21/card_view.xml @@ -3,14 +3,19 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" android:layout_gravity="center_vertical" + android:layout_marginStart="16dp" android:layout_marginTop="8dp" + android:layout_marginEnd="16dp" android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" android:layout_marginBottom="12dp" app:cardCornerRadius="8dp" app:cardElevation="0dp" android:background="@drawable/banner_card_border" + android:clipToOutline="true" + android:outlineProvider="background" android:orientation="vertical"> + /> @@ -79,41 +84,32 @@ android:orientation="horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/embedded_message_text_container" app:layout_constraintBottom_toBottomOf="parent"> + android:textSize="14sp" /> + android:textSize="14sp" /> diff --git a/iterableapi-ui/src/main/res/layout/card_view.xml b/iterableapi-ui/src/main/res/layout/card_view.xml index db5d3957b..11b42a081 100644 --- a/iterableapi-ui/src/main/res/layout/card_view.xml +++ b/iterableapi-ui/src/main/res/layout/card_view.xml @@ -2,16 +2,20 @@ + /> @@ -79,41 +83,32 @@ android:orientation="horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/embedded_message_text_container" app:layout_constraintBottom_toBottomOf="parent"> + android:textSize="14sp" /> + android:textSize="14sp" />