From 15a9c79875ea401dd2d2b0e799a4ecc20de19e52 Mon Sep 17 00:00:00 2001 From: manpreet Date: Mon, 20 May 2024 18:50:15 +0530 Subject: [PATCH 01/10] swig changes --- .../objectmodel/RatingDisplayStyle.java | 52 +++++++++++++++++++ ...T_AdaptiveCards__RatingDisplayStyle_t.java | 26 ++++++++++ 2 files changed, 78 insertions(+) create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java new file mode 100644 index 000000000..fdf4eb3fe --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java @@ -0,0 +1,52 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package io.adaptivecards.objectmodel; + +public enum RatingDisplayStyle { + Default(0), + Compact; + + public final int swigValue() { + return swigValue; + } + + public static RatingDisplayStyle swigToEnum(int swigValue) { + RatingDisplayStyle[] swigValues = RatingDisplayStyle.class.getEnumConstants(); + if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue) + return swigValues[swigValue]; + for (RatingDisplayStyle swigEnum : swigValues) + if (swigEnum.swigValue == swigValue) + return swigEnum; + throw new IllegalArgumentException("No enum " + RatingDisplayStyle.class + " with value " + swigValue); + } + + @SuppressWarnings("unused") + private RatingDisplayStyle() { + this.swigValue = SwigNext.next++; + } + + @SuppressWarnings("unused") + private RatingDisplayStyle(int swigValue) { + this.swigValue = swigValue; + SwigNext.next = swigValue+1; + } + + @SuppressWarnings("unused") + private RatingDisplayStyle(RatingDisplayStyle swigEnum) { + this.swigValue = swigEnum.swigValue; + SwigNext.next = this.swigValue+1; + } + + private final int swigValue; + + private static class SwigNext { + private static int next = 0; + } +} + diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java new file mode 100644 index 000000000..32fbd978b --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java @@ -0,0 +1,26 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.2 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package io.adaptivecards.objectmodel; + +public class SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t { + private transient long swigCPtr; + + protected SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t(long cPtr, @SuppressWarnings("unused") boolean futureUse) { + swigCPtr = cPtr; + } + + protected SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t() { + swigCPtr = 0; + } + + protected static long getCPtr(SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +} + From 027f37527055336c6520ea2ad38d03c3cc64e333 Mon Sep 17 00:00:00 2001 From: manpreet Date: Mon, 20 May 2024 18:52:33 +0530 Subject: [PATCH 02/10] Revert "swig changes" This reverts commit 15a9c79875ea401dd2d2b0e799a4ecc20de19e52. --- .../objectmodel/RatingDisplayStyle.java | 52 ------------------- ...T_AdaptiveCards__RatingDisplayStyle_t.java | 26 ---------- 2 files changed, 78 deletions(-) delete mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java delete mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java deleted file mode 100644 index fdf4eb3fe..000000000 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/RatingDisplayStyle.java +++ /dev/null @@ -1,52 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 4.0.2 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -package io.adaptivecards.objectmodel; - -public enum RatingDisplayStyle { - Default(0), - Compact; - - public final int swigValue() { - return swigValue; - } - - public static RatingDisplayStyle swigToEnum(int swigValue) { - RatingDisplayStyle[] swigValues = RatingDisplayStyle.class.getEnumConstants(); - if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue) - return swigValues[swigValue]; - for (RatingDisplayStyle swigEnum : swigValues) - if (swigEnum.swigValue == swigValue) - return swigEnum; - throw new IllegalArgumentException("No enum " + RatingDisplayStyle.class + " with value " + swigValue); - } - - @SuppressWarnings("unused") - private RatingDisplayStyle() { - this.swigValue = SwigNext.next++; - } - - @SuppressWarnings("unused") - private RatingDisplayStyle(int swigValue) { - this.swigValue = swigValue; - SwigNext.next = swigValue+1; - } - - @SuppressWarnings("unused") - private RatingDisplayStyle(RatingDisplayStyle swigEnum) { - this.swigValue = swigEnum.swigValue; - SwigNext.next = this.swigValue+1; - } - - private final int swigValue; - - private static class SwigNext { - private static int next = 0; - } -} - diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java deleted file mode 100644 index 32fbd978b..000000000 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t.java +++ /dev/null @@ -1,26 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 4.0.2 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -package io.adaptivecards.objectmodel; - -public class SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t { - private transient long swigCPtr; - - protected SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t(long cPtr, @SuppressWarnings("unused") boolean futureUse) { - swigCPtr = cPtr; - } - - protected SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t() { - swigCPtr = 0; - } - - protected static long getCPtr(SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__RatingDisplayStyle_t obj) { - return (obj == null) ? 0 : obj.swigCPtr; - } -} - From e922852a24a880cd8374217386f2e0c079c5412c Mon Sep 17 00:00:00 2001 From: manpreet Date: Thu, 23 May 2024 18:32:08 +0530 Subject: [PATCH 03/10] implementation of rating element --- samples/HostConfig/microsoft-teams-dark.json | 32 +++- samples/HostConfig/microsoft-teams-light.json | 32 +++- samples/v1.5/Scenarios/RatingInput.json | 70 ++++++++ .../android/adaptivecards/gradle.properties | 2 +- .../renderer/FluentIconImageLoaderAsync.kt | 10 +- .../renderer/input/RatingInputRenderer.kt | 55 ++++++ .../inputhandler/RatingInputHandler.kt | 49 ++++++ .../renderer/layout/RatingStarDisplayView.kt | 165 ++++++++++++++++++ .../renderer/layout/RatingStarInputView.kt | 112 ++++++++++++ .../layout/StretchableInputLayout.java | 5 + .../readonly/RatingDisplayRenderer.kt | 41 +++++ .../readonly/RatingElementRendererUtil.kt | 74 ++++++++ .../CardRendererRegistration.java | 4 + .../res/drawable/ic_fluent_star_24_filled.xml | 9 + .../drawable/ic_fluent_star_24_regular.xml | 9 + .../res/drawable/ic_fluent_star_28_filled.xml | 9 + .../drawable/ic_fluent_star_28_regular.xml | 9 + .../res/drawable/ic_fluent_star_32_filled.xml | 9 + .../drawable/ic_fluent_star_32_regular.xml | 9 + .../drawable/rating_star_selector_large.xml | 6 + .../drawable/rating_star_selector_medium.xml | 5 + .../drawable/rating_star_selector_small.xml | 6 + .../src/main/res/raw/importer_card.json | 4 + 23 files changed, 718 insertions(+), 8 deletions(-) create mode 100644 samples/v1.5/Scenarios/RatingInput.json create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingDisplayRenderer.kt create mode 100644 source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt create mode 100644 source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_filled.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_regular.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_filled.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_regular.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_filled.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_regular.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/rating_star_selector_large.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/rating_star_selector_medium.xml create mode 100644 source/android/adaptivecards/src/main/res/drawable/rating_star_selector_small.xml diff --git a/samples/HostConfig/microsoft-teams-dark.json b/samples/HostConfig/microsoft-teams-dark.json index 1e38d1afc..b1d2bd563 100644 --- a/samples/HostConfig/microsoft-teams-dark.json +++ b/samples/HostConfig/microsoft-teams-dark.json @@ -304,5 +304,33 @@ "warp": true }, "spacing": 16 - } -} \ No newline at end of file + }, + "ratingInput": { + "filledStar": { + "marigoldColor": "#F2C661", + "neutralColor": "#E1E1E1" + }, + + "emptyStar": { + "marigoldColor": "#F2C661", + "neutralColor": "#E1E1E1" + }, + + "ratingTextColor": "#000000", + "countTextColor": "#000000" + }, + "ratingLabel": { + "filledStar": { + "marigoldColor": "#EAA300", + "neutralColor": "#E1E1E1" + }, + + "emptyStar": { + "marigoldColor": "#835B00", + "neutralColor": "#404040" + }, + + "ratingTextColor": "#E1E1E1", + "countTextColor": "#E1E1E1" + } +} diff --git a/samples/HostConfig/microsoft-teams-light.json b/samples/HostConfig/microsoft-teams-light.json index eb6d60533..e572d2b13 100644 --- a/samples/HostConfig/microsoft-teams-light.json +++ b/samples/HostConfig/microsoft-teams-light.json @@ -304,5 +304,33 @@ "warp": true }, "spacing": 16 - } -} \ No newline at end of file + }, + "ratingInput": { + "filledStar": { + "marigoldColor": "#EAA300", + "neutralColor": "#212121" + }, + + "emptyStar": { + "marigoldColor": "#EAA300", + "neutralColor": "#212121" + }, + + "ratingTextColor": "#000000", + "countTextColor": "#000000" + }, + "ratingLabel": { + "filledStar": { + "marigoldColor": "#EAA300", + "neutralColor": "#242424" + }, + + "emptyStar": { + "marigoldColor": "#F9E2AE", + "neutralColor": "#E1E1E1" + }, + + "ratingTextColor": "#000000", + "countTextColor": "#000000" + } +} diff --git a/samples/v1.5/Scenarios/RatingInput.json b/samples/v1.5/Scenarios/RatingInput.json new file mode 100644 index 000000000..7c539b6c7 --- /dev/null +++ b/samples/v1.5/Scenarios/RatingInput.json @@ -0,0 +1,70 @@ +{ + "type": "AdaptiveCard", + "$schema": "https://adaptivecards.io/schemas/adaptive-card.json", + "version": "1.5", + "body": [ + { + "type": "TextBlock", + "size": "Large", + "text": "Rating input" + }, + { + "type": "Input.Rating", + "id": "rating1", + "size": "medium", + "isRequired": true, + "label": "Pick a rating", + "errorMessage": "Please pick a rating", + "horizontalAlignment": "left", + "max": 5 + }, + { + "type": "Input.Rating", + "id": "rating2", + "label": "Pick a rating", + "size": "large", + "isRequired": true, + "errorMessage": "Please pick a rating", + "color": "marigold", + "value": 2, + "horizontalAlignment": "left", + "max": 4 + }, + { + "type": "TextBlock", + "size": "large", + "text": "Read-only ratings", + "separator": true, + "spacing": "extraLarge" + }, + { + "type": "Rating", + "value": 3, + "size": "medium", + "horizontalAlignment": "left" + }, + { + "type": "Rating", + "max": 20, + "value": 30, + "color": "marigold", + "size": "large", + "horizontalAlignment": "left" + }, + { + "type": "Rating", + "style": "compact", + "value": 3.2, + "color": "marigold", + "count": 1500, + "size": "large", + "horizontalAlignment": "left" + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "Submit" + } + ] +} diff --git a/source/android/adaptivecards/gradle.properties b/source/android/adaptivecards/gradle.properties index c6b1f931c..fa2288f39 100644 --- a/source/android/adaptivecards/gradle.properties +++ b/source/android/adaptivecards/gradle.properties @@ -2,7 +2,7 @@ NexusUserName= NexusPassword= azureArtifactsGradleAccessToken= -acVersion=3.1.2 +acVersion=19.0.0 # Configure Gradle Nexus Staging Plugin gnsp.disableApplyOnlyOnRootProjectEnforcement=true \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/FluentIconImageLoaderAsync.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/FluentIconImageLoaderAsync.kt index ae13d4c67..2ea204cee 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/FluentIconImageLoaderAsync.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/FluentIconImageLoaderAsync.kt @@ -107,11 +107,15 @@ open class FluentIconImageLoaderAsync( private fun getDrawableFromSVG(svgString: String, context: Context): BitmapDrawable { val svg = parseSvgString(context, svgString) val picture = svg.renderToPicture() - var bitmap = Bitmap.createBitmap(picture.width, picture.height, Bitmap.Config.ARGB_8888) + val bitmap = Bitmap.createBitmap(picture.width, picture.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) picture.draw(canvas) - var drawable = BitmapDrawable(context.resources, bitmap) - val color = Color.parseColor(iconColor) + val drawable = BitmapDrawable(context.resources, bitmap) + val color = try { + Color.parseColor(iconColor) + } catch (e: IllegalArgumentException) { + Color.BLACK + } drawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_IN) return drawable } diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt new file mode 100644 index 000000000..cece8d4bd --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package io.adaptivecards.renderer.input + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.fragment.app.FragmentManager +import io.adaptivecards.objectmodel.BaseCardElement +import io.adaptivecards.objectmodel.HostConfig +import io.adaptivecards.objectmodel.RatingInput +import io.adaptivecards.renderer.BaseCardElementRenderer +import io.adaptivecards.renderer.RenderArgs +import io.adaptivecards.renderer.RenderedAdaptiveCard +import io.adaptivecards.renderer.TagContent +import io.adaptivecards.renderer.Util +import io.adaptivecards.renderer.actionhandler.ICardActionHandler +import io.adaptivecards.renderer.inputhandler.InputUtils.updateInputHandlerInputWatcher +import io.adaptivecards.renderer.inputhandler.RatingInputHandler +import io.adaptivecards.renderer.layout.RatingStarInputView +import io.adaptivecards.renderer.readonly.RatingElementRendererUtil + +/** + * Renderer for rating input element + **/ +object RatingInputRenderer: BaseCardElementRenderer() { + override fun render( + renderedCard: RenderedAdaptiveCard, + context: Context, + fragmentManager: FragmentManager, + viewGroup: ViewGroup, + baseCardElement: BaseCardElement, + cardActionHandler: ICardActionHandler?, + hostConfig: HostConfig, + renderArgs: RenderArgs + ): View { + val ratingInput = Util.castTo(baseCardElement, RatingInput::class.java) + val ratingInputHandler = RatingInputHandler(ratingInput) + val view = RatingStarInputView( + context, + hostConfig, + ratingInput, + ratingInputHandler + ) as LinearLayout + RatingElementRendererUtil.applyHorizontalAlignment(view, ratingInput.GetHorizontalAlignment(), renderArgs) + ratingInputHandler.setView(view) + renderedCard.registerInputHandler(ratingInputHandler, renderArgs.containerCardId) + ratingInputHandler.updateInputHandlerInputWatcher() + view.tag = TagContent(ratingInput, ratingInputHandler) + viewGroup.addView(view) + return view + } + +} \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt new file mode 100644 index 000000000..90323f9ce --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package io.adaptivecards.renderer.inputhandler + +import android.view.accessibility.AccessibilityEvent +import io.adaptivecards.objectmodel.BaseInputElement +import io.adaptivecards.renderer.Util +import io.adaptivecards.renderer.layout.RatingStarInputView + +/** + * Input handler for Rating input + **/ +class RatingInputHandler( + baseInputElement: BaseInputElement +): BaseInputHandler(baseInputElement) { + override fun getInput() = (m_view as RatingStarInputView).getRating().toString() + + override fun setInput(input: String?) { + // no-op + } + + override fun setFocusToView() { + val rating = (m_view as RatingStarInputView).getRating() + val focusView = (m_view as RatingStarInputView).getChildAt(if (rating == 0) 0 else rating - 1) + Util.forceFocus(focusView) + focusView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) + } + + override fun isValid(showError: Boolean): Boolean { + var isValid = true + if (m_baseInputElement.GetIsRequired()) { + isValid = try { + input.toDouble() > 0 + } catch(e: NumberFormatException) { + false + } + } + isValid = isValid && isValidOnSpecifics(input) + if (showError) { + showValidationErrors(isValid) + } + return isValid + } + + override fun registerInputObserver() { + notifyAllInputWatchers() + } + +} \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt new file mode 100644 index 000000000..bf51b796a --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt @@ -0,0 +1,165 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package io.adaptivecards.renderer.layout + +import android.content.Context +import android.graphics.Typeface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.Gravity +import android.view.View +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.res.ResourcesCompat +import io.adaptivecards.R +import io.adaptivecards.objectmodel.HostConfig +import io.adaptivecards.objectmodel.RatingColor +import io.adaptivecards.objectmodel.RatingStyle +import io.adaptivecards.objectmodel.RatingLabel +import io.adaptivecards.objectmodel.RatingSize +import io.adaptivecards.renderer.Util +import io.adaptivecards.renderer.readonly.RatingElementRendererUtil + +/** + * View to display the read only rating stars + **/ +class RatingStarDisplayView: LinearLayout { + + private var value: Double = 0.0 + + private var maxStarsCount = 5 + + private var size = RatingSize.Medium + + private var style = RatingStyle.Default + + private var count: Long? = null + + private lateinit var color: RatingColor + + private val ratingStars: MutableList = ArrayList() + + private lateinit var hostConfig: HostConfig + + constructor( + context: Context, + ratingLabel: RatingLabel, + hostConfig: HostConfig + ) : super(context) { + this.maxStarsCount = (ratingLabel.GetMax().toInt()).coerceAtMost(5) + this.value = ratingLabel.GetValue() + this.hostConfig = hostConfig + this.size = ratingLabel.GetRatingSize() + this.style = ratingLabel.GetRatingStyle() + this.count = ratingLabel.GetCount() + this.color = ratingLabel.GetRatingColor() + initStars() + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initStars() + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + initStars() + } + + private fun initStars() { + orientation = HORIZONTAL + layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) + + when (style) { + RatingStyle.Default -> defaultStyle() + RatingStyle.Compact -> compactStyle() + } + } + + private fun defaultStyle() { + for (i in 0 until maxStarsCount) { + val star = ImageView(context) + star.setImageDrawable(getStarDrawable()) + star.isActivated = true + star.setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, i < value.toInt(), hostConfig)) + star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + ratingStars.add(star) + val rightMargin = if (i < maxStarsCount - 1) MARGIN_BETWEEN_STARS else MARGIN_BETWEEN_STARS_AND_RATING_TEXT + addViewWithMargin(star, rightMargin) + } + + val rating = if (value.rem(1.0) == 0.0) value.toInt() else value + val ratingTextView = createTextView(rating.toString(), hostConfig.GetRatingLabelConfig().ratingTextColor, Typeface.BOLD) + addView(ratingTextView) + } + + /** + * A single activated star with the rating value is shown in the compact style + * if count is present, it is shown next to the rating value + **/ + private fun compactStyle() { + val star = ImageView(context) + star.setImageDrawable(getStarDrawable()) + star.isActivated = true + star.setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, true, hostConfig)) + star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + ratingStars.add(star) + addViewWithMargin(star, MARGIN_BETWEEN_STARS_AND_RATING_TEXT) + + val rating = if (value.rem(1.0) == 0.0) value.toInt() else value + val ratingTextView = createTextView(rating.toString(), hostConfig.GetRatingLabelConfig().ratingTextColor, Typeface.BOLD) + + count?.let { + if (it == 0L) { + addView(ratingTextView) + } else { + addViewWithMargin(ratingTextView, MARGIN_BETWEEN_RATING_TEXT_AND_DOT_COUNT) + addUsersCountTextView(it) + } + } ?: addView(ratingTextView) + + } + + private fun addUsersCountTextView(countValue: Long) { + val dotTextView = createTextView("·", hostConfig.GetRatingLabelConfig().ratingTextColor, Typeface.BOLD) + addViewWithMargin(dotTextView, MARGIN_BETWEEN_RATING_TEXT_AND_DOT_COUNT) + + val formattedCount = RatingElementRendererUtil.formatNumberWithCommas(countValue) + val countTextView = createTextView(formattedCount, hostConfig.GetRatingLabelConfig().countTextColor, Typeface.NORMAL) + addView(countTextView) + } + + private fun createTextView(text: String, textColor: String, style: Int): TextView { + val color = RatingElementRendererUtil.getColorFromHexCode(textColor) + val textView = TextView(context) + textView.text = text + textView.setTextColor(color) + textView.textSize = 16F + textView.setTypeface(null, style) + textView.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT) + textView.gravity = Gravity.CENTER_VERTICAL + return textView + } + + private fun addViewWithMargin(view: View, rightMargin: Int) { + val rightMarginInPixels = Util.dpToPixels(context, rightMargin.toFloat()) + val params = view.layoutParams as LayoutParams + params.rightMargin = rightMarginInPixels + addView(view, params) + } + + /** + * get the star drawable based on the size + **/ + private fun getStarDrawable(): Drawable? { + return when (size) { + RatingSize.Medium -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_small, null) + RatingSize.Large -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_medium, null) + } + } + + companion object { + private const val MARGIN_BETWEEN_STARS = 4 + private const val MARGIN_BETWEEN_STARS_AND_RATING_TEXT = 8 + private const val MARGIN_BETWEEN_RATING_TEXT_AND_DOT_COUNT = 4 + } +} \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt new file mode 100644 index 000000000..f896655fe --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package io.adaptivecards.renderer.layout + +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.core.content.res.ResourcesCompat +import io.adaptivecards.R +import io.adaptivecards.objectmodel.HostConfig +import io.adaptivecards.objectmodel.RatingColor +import io.adaptivecards.objectmodel.RatingInput +import io.adaptivecards.objectmodel.RatingSize +import io.adaptivecards.renderer.Util +import io.adaptivecards.renderer.inputhandler.RatingInputHandler +import io.adaptivecards.renderer.readonly.RatingElementRendererUtil +import java.lang.ref.WeakReference + +/** + * View to display the input rating stars + **/ +class RatingStarInputView: LinearLayout { + + private var value = 0 + + private var maxStarsCount = 5 + + private lateinit var color: RatingColor + + private var size = RatingSize.Medium + + private val ratingStars: MutableList = ArrayList() + + private var rating = 0 + + private lateinit var hostConfig: HostConfig + + private var ratingInputHandler: WeakReference? = null + + constructor( + context: Context, + hostConfig: HostConfig, + ratingInput: RatingInput, + ratingInputHandler: RatingInputHandler + ) : super(context) { + isSaveEnabled = true + this.maxStarsCount = (ratingInput.GetMax().toInt()).coerceAtMost(5) + this.value = (ratingInput.GetValue().toInt()).coerceAtMost(5) + this.color = ratingInput.GetRatingColor() + this.rating = value + this.size = ratingInput.GetRatingSize() + this.hostConfig = hostConfig + this.ratingInputHandler = WeakReference(ratingInputHandler) + initStars(context) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initStars(context) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + initStars(context) + } + + private fun initStars(context: Context) { + orientation = HORIZONTAL + layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) + val rightMargin = Util.dpToPixels(context, RIGHT_MARGIN.toFloat()) + for (index in 0 until maxStarsCount) { + val star = ImageView(context) + star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0f) + star.contentDescription = "Rating Star $index+1" + star.setImageDrawable(getStarDrawable()) + star.setColorFilter(RatingElementRendererUtil.getInputStarColor(color, index < value, hostConfig)) + star.isActivated = index < value + ratingStars.add(star) + star.setOnClickListener { + handleClick(index) + } + val params = star.layoutParams as LayoutParams + if (index < maxStarsCount - 1) { + params.rightMargin = rightMargin + } + addView(star, params) + } + } + + private fun handleClick(index: Int) { + rating = index + 1 + for (i in 0 until maxStarsCount) { + ratingStars[i].isActivated = i < rating + } + ratingInputHandler?.get()?.registerInputObserver() + } + + private fun getStarDrawable(): Drawable? { + return when (size) { + RatingSize.Medium -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_medium, null) + RatingSize.Large -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_large, null) + } + } + + fun getRating(): Int { + return rating + } + + companion object { + private const val RIGHT_MARGIN = 12 + } +} diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/StretchableInputLayout.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/StretchableInputLayout.java index df0ad2fe5..1236bc4fb 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/StretchableInputLayout.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/StretchableInputLayout.java @@ -58,6 +58,11 @@ public void setInputView(View input) m_inputView = layout.getChildAt(0); m_viewWithVisualCues = input; } + else if (input instanceof RatingStarInputView || input instanceof RatingStarDisplayView) { + LinearLayout layout = (LinearLayout) input; + m_inputView = layout; + m_viewWithVisualCues = layout; + } // Input.Text with an inline action render inside a regular LinearLayout, but in this case // the view inside of the Layout has the visual cue. We have to verify that the expanded // ChoiceSet are not considered in this step as in that case they both use LinearLayout but diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingDisplayRenderer.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingDisplayRenderer.kt new file mode 100644 index 000000000..f9559ab01 --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingDisplayRenderer.kt @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package io.adaptivecards.renderer.readonly + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.FragmentManager +import io.adaptivecards.objectmodel.BaseCardElement +import io.adaptivecards.objectmodel.HostConfig +import io.adaptivecards.objectmodel.RatingLabel +import io.adaptivecards.renderer.BaseCardElementRenderer +import io.adaptivecards.renderer.RenderArgs +import io.adaptivecards.renderer.RenderedAdaptiveCard +import io.adaptivecards.renderer.TagContent +import io.adaptivecards.renderer.Util +import io.adaptivecards.renderer.actionhandler.ICardActionHandler +import io.adaptivecards.renderer.layout.RatingStarDisplayView + +/** + * Renderer for read only rating element + **/ +object RatingDisplayRenderer: BaseCardElementRenderer() { + override fun render( + renderedCard: RenderedAdaptiveCard, + context: Context, + fragmentManager: FragmentManager, + viewGroup: ViewGroup, + baseCardElement: BaseCardElement, + cardActionHandler: ICardActionHandler?, + hostConfig: HostConfig, + renderArgs: RenderArgs + ): View { + val ratingLabel = Util.castTo(baseCardElement, RatingLabel::class.java) + val view = RatingStarDisplayView(context, ratingLabel, hostConfig) + RatingElementRendererUtil.applyHorizontalAlignment(view, ratingLabel.GetHorizontalAlignment(), renderArgs) + view.tag = TagContent(ratingLabel) + viewGroup.addView(view) + return view + } +} \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt new file mode 100644 index 000000000..b8043e1af --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package io.adaptivecards.renderer.readonly + +import android.graphics.Color +import android.widget.LinearLayout +import io.adaptivecards.objectmodel.HorizontalAlignment +import io.adaptivecards.objectmodel.HostConfig +import io.adaptivecards.objectmodel.RatingColor +import io.adaptivecards.renderer.RenderArgs +import java.text.NumberFormat +import java.util.Locale + +object RatingElementRendererUtil { + + /** + * returns the color of the star based on the activated state + * if the star is activated, it returns the filled star color else it returns the empty star color from the hostConfig + **/ + fun getInputStarColor(color: RatingColor, isActivated: Boolean, hostConfig: HostConfig): Int { + return if (isActivated) { + when (color) { + RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingInputConfig().filledStar.neutralColor) + RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingInputConfig().filledStar.marigoldColor) + } + } else { + when (color) { + RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingInputConfig().emptyStar.neutralColor) + RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingInputConfig().emptyStar.marigoldColor) + } + } + } + + /** + * returns the color of the read only stars based on the activated state + * if the star is activated, it returns the filled star color else it returns the empty star color from the hostConfig + **/ + fun getReadOnlyStarColor(color: RatingColor, isActivated: Boolean, hostConfig: HostConfig): Int { + return if (isActivated) { + when (color) { + RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().filledStar.neutralColor) + RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().filledStar.marigoldColor) + } + } else { + when (color) { + RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().emptyStar.neutralColor) + RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().emptyStar.marigoldColor) + } + } + } + + fun formatNumberWithCommas(number: Long): String { + return NumberFormat.getNumberInstance(Locale.getDefault()).format(number) + } + + /** + * parse the hexcode and return the color + **/ + fun getColorFromHexCode(hexcode: String): Int { + return try { + Color.parseColor(hexcode) + } catch (e: IllegalArgumentException) { + Color.BLACK + } + } + + fun applyHorizontalAlignment(view: LinearLayout, horizontalAlignment: HorizontalAlignment?, renderArgs: RenderArgs) { + when (horizontalAlignment ?: renderArgs.horizontalAlignment ?: HorizontalAlignment.Left) { + HorizontalAlignment.Center -> view.gravity = android.view.Gravity.CENTER_HORIZONTAL + HorizontalAlignment.Right -> view.gravity = android.view.Gravity.END + else -> view.gravity = android.view.Gravity.START + } + } +} \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/registration/CardRendererRegistration.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/registration/CardRendererRegistration.java index 660d9f46f..14d497e8f 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/registration/CardRendererRegistration.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/registration/CardRendererRegistration.java @@ -57,6 +57,7 @@ import io.adaptivecards.renderer.input.DateInputRenderer; import io.adaptivecards.renderer.input.InputUtil; import io.adaptivecards.renderer.input.NumberInputRenderer; +import io.adaptivecards.renderer.input.RatingInputRenderer; import io.adaptivecards.renderer.input.TextInputRenderer; import io.adaptivecards.renderer.input.TimeInputRenderer; import io.adaptivecards.renderer.input.ToggleInputRenderer; @@ -73,6 +74,7 @@ import io.adaptivecards.renderer.readonly.ImageRenderer; import io.adaptivecards.renderer.readonly.ImageSetRenderer; import io.adaptivecards.renderer.readonly.MediaRenderer; +import io.adaptivecards.renderer.readonly.RatingDisplayRenderer; import io.adaptivecards.renderer.readonly.RichTextBlockRenderer; import io.adaptivecards.renderer.readonly.TableRenderer; import io.adaptivecards.renderer.readonly.TableCellRenderer; @@ -95,6 +97,7 @@ private CardRendererRegistration() { registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.ActionSet), ActionSetRenderer.getInstance()); registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.Table), TableRenderer.INSTANCE); registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.TableCell), TableCellRenderer.INSTANCE); + registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.RatingLabel), RatingDisplayRenderer.INSTANCE); // Register Input Renderers registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.TextInput), TextInputRenderer.getInstance()); @@ -103,6 +106,7 @@ private CardRendererRegistration() { registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.TimeInput), TimeInputRenderer.getInstance()); registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.ToggleInput), ToggleInputRenderer.getInstance()); registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.ChoiceSetInput), ChoiceSetInputRenderer.getInstance()); + registerRenderer(AdaptiveCardObjectModel.CardElementTypeToString(CardElementType.RatingInput), RatingInputRenderer.INSTANCE); // Register Action Renderer registerActionRenderer(AdaptiveCardObjectModel.ActionTypeToString(ActionType.Execute), ActionElementRenderer.getInstance()); diff --git a/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_filled.xml b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_filled.xml new file mode 100644 index 000000000..24e734d85 --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_filled.xml @@ -0,0 +1,9 @@ + + + diff --git a/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_regular.xml b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_regular.xml new file mode 100644 index 000000000..e9f005522 --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_24_regular.xml @@ -0,0 +1,9 @@ + + + diff --git a/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_filled.xml b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_filled.xml new file mode 100644 index 000000000..6d40e57ec --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_filled.xml @@ -0,0 +1,9 @@ + + + diff --git a/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_regular.xml b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_regular.xml new file mode 100644 index 000000000..5301286b4 --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_28_regular.xml @@ -0,0 +1,9 @@ + + + diff --git a/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_filled.xml b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_filled.xml new file mode 100644 index 000000000..dba7c0bfe --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_filled.xml @@ -0,0 +1,9 @@ + + + diff --git a/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_regular.xml b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_regular.xml new file mode 100644 index 000000000..4bec556f0 --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/ic_fluent_star_32_regular.xml @@ -0,0 +1,9 @@ + + + diff --git a/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_large.xml b/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_large.xml new file mode 100644 index 000000000..e3f172722 --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_large.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_medium.xml b/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_medium.xml new file mode 100644 index 000000000..626590e7b --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_medium.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_small.xml b/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_small.xml new file mode 100644 index 000000000..de84d7641 --- /dev/null +++ b/source/android/adaptivecards/src/main/res/drawable/rating_star_selector_small.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/source/android/mobile/src/main/res/raw/importer_card.json b/source/android/mobile/src/main/res/raw/importer_card.json index 387960f1f..64076562c 100644 --- a/source/android/mobile/src/main/res/raw/importer_card.json +++ b/source/android/mobile/src/main/res/raw/importer_card.json @@ -19,6 +19,10 @@ "title": "FluentIcon", "value": "v1.5/Scenarios/FluentIcon.json" }, + { + "title": "RatingInput", + "value": "v1.5/Scenarios/RatingInput.json" + }, { "title": "ActivityUpdate", "value": "v1.5/Scenarios/ActivityUpdate.json" From 957a65b866745323d36b46a7db725cb7762c6cfe Mon Sep 17 00:00:00 2001 From: manpreet Date: Thu, 23 May 2024 18:46:52 +0530 Subject: [PATCH 04/10] support count for default style for read only rating element --- samples/v1.5/Scenarios/RatingInput.json | 12 ++++--- .../renderer/layout/RatingStarDisplayView.kt | 33 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/samples/v1.5/Scenarios/RatingInput.json b/samples/v1.5/Scenarios/RatingInput.json index 7c539b6c7..a960e8a66 100644 --- a/samples/v1.5/Scenarios/RatingInput.json +++ b/samples/v1.5/Scenarios/RatingInput.json @@ -28,7 +28,7 @@ "color": "marigold", "value": 2, "horizontalAlignment": "left", - "max": 4 + "max": 5 }, { "type": "TextBlock", @@ -39,17 +39,19 @@ }, { "type": "Rating", - "value": 3, + "value": 3.2, "size": "medium", - "horizontalAlignment": "left" + "horizontalAlignment": "left", + "count": 10 }, { "type": "Rating", "max": 20, - "value": 30, + "value": 3.2, "color": "marigold", "size": "large", - "horizontalAlignment": "left" + "horizontalAlignment": "left", + "count": 150 }, { "type": "Rating", diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt index bf51b796a..f9579d232 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt @@ -79,17 +79,14 @@ class RatingStarDisplayView: LinearLayout { for (i in 0 until maxStarsCount) { val star = ImageView(context) star.setImageDrawable(getStarDrawable()) - star.isActivated = true + star.isActivated = i < value.toInt() star.setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, i < value.toInt(), hostConfig)) star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) ratingStars.add(star) val rightMargin = if (i < maxStarsCount - 1) MARGIN_BETWEEN_STARS else MARGIN_BETWEEN_STARS_AND_RATING_TEXT addViewWithMargin(star, rightMargin) } - - val rating = if (value.rem(1.0) == 0.0) value.toInt() else value - val ratingTextView = createTextView(rating.toString(), hostConfig.GetRatingLabelConfig().ratingTextColor, Typeface.BOLD) - addView(ratingTextView) + addRatingAndCount() } /** @@ -104,10 +101,24 @@ class RatingStarDisplayView: LinearLayout { star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) ratingStars.add(star) addViewWithMargin(star, MARGIN_BETWEEN_STARS_AND_RATING_TEXT) + addRatingAndCount() + } + + private fun addUsersCountTextView(countValue: Long) { + val dotTextView = createTextView("·", hostConfig.GetRatingLabelConfig().ratingTextColor, Typeface.BOLD) + addViewWithMargin(dotTextView, MARGIN_BETWEEN_RATING_TEXT_AND_DOT_COUNT) + + val formattedCount = RatingElementRendererUtil.formatNumberWithCommas(countValue) + val countTextView = createTextView(formattedCount, hostConfig.GetRatingLabelConfig().countTextColor, Typeface.NORMAL) + addView(countTextView) + } + /** + * adds the rating and count value to the stars + **/ + private fun addRatingAndCount() { val rating = if (value.rem(1.0) == 0.0) value.toInt() else value val ratingTextView = createTextView(rating.toString(), hostConfig.GetRatingLabelConfig().ratingTextColor, Typeface.BOLD) - count?.let { if (it == 0L) { addView(ratingTextView) @@ -116,16 +127,6 @@ class RatingStarDisplayView: LinearLayout { addUsersCountTextView(it) } } ?: addView(ratingTextView) - - } - - private fun addUsersCountTextView(countValue: Long) { - val dotTextView = createTextView("·", hostConfig.GetRatingLabelConfig().ratingTextColor, Typeface.BOLD) - addViewWithMargin(dotTextView, MARGIN_BETWEEN_RATING_TEXT_AND_DOT_COUNT) - - val formattedCount = RatingElementRendererUtil.formatNumberWithCommas(countValue) - val countTextView = createTextView(formattedCount, hostConfig.GetRatingLabelConfig().countTextColor, Typeface.NORMAL) - addView(countTextView) } private fun createTextView(text: String, textColor: String, style: Int): TextView { From 95040cfbe966687f55a22ca6fccacda8b30c695f Mon Sep 17 00:00:00 2001 From: manpreet Date: Thu, 23 May 2024 19:05:47 +0530 Subject: [PATCH 05/10] revert gradle.properties version change --- source/android/adaptivecards/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/android/adaptivecards/gradle.properties b/source/android/adaptivecards/gradle.properties index fa2288f39..c6b1f931c 100644 --- a/source/android/adaptivecards/gradle.properties +++ b/source/android/adaptivecards/gradle.properties @@ -2,7 +2,7 @@ NexusUserName= NexusPassword= azureArtifactsGradleAccessToken= -acVersion=19.0.0 +acVersion=3.1.2 # Configure Gradle Nexus Staging Plugin gnsp.disableApplyOnlyOnRootProjectEnforcement=true \ No newline at end of file From e394cb6acf6c6878a71bda2b927a7c8e53d60f02 Mon Sep 17 00:00:00 2001 From: manpreet Date: Thu, 23 May 2024 19:22:44 +0530 Subject: [PATCH 06/10] set state to activated for read only stars --- .../io/adaptivecards/renderer/layout/RatingStarDisplayView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt index f9579d232..43901de13 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt @@ -79,7 +79,7 @@ class RatingStarDisplayView: LinearLayout { for (i in 0 until maxStarsCount) { val star = ImageView(context) star.setImageDrawable(getStarDrawable()) - star.isActivated = i < value.toInt() + star.isActivated = true star.setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, i < value.toInt(), hostConfig)) star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) ratingStars.add(star) From 3c64c59dc3633bf959992a3521bb4719f7c8ff6b Mon Sep 17 00:00:00 2001 From: manpreet Date: Thu, 30 May 2024 18:48:28 +0530 Subject: [PATCH 07/10] addressed review comments --- .../renderer/layout/RatingStarDisplayView.kt | 36 +++++++++++-------- .../renderer/layout/RatingStarInputView.kt | 20 ++++++----- .../readonly/RatingElementRendererUtil.kt | 8 ++--- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt index 43901de13..7e4ae4320 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt @@ -78,10 +78,12 @@ class RatingStarDisplayView: LinearLayout { private fun defaultStyle() { for (i in 0 until maxStarsCount) { val star = ImageView(context) - star.setImageDrawable(getStarDrawable()) - star.isActivated = true - star.setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, i < value.toInt(), hostConfig)) - star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + star.apply { + setImageDrawable(getStarDrawable()) + isActivated = true + setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, i < value.toInt(), hostConfig)) + layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + } ratingStars.add(star) val rightMargin = if (i < maxStarsCount - 1) MARGIN_BETWEEN_STARS else MARGIN_BETWEEN_STARS_AND_RATING_TEXT addViewWithMargin(star, rightMargin) @@ -95,10 +97,12 @@ class RatingStarDisplayView: LinearLayout { **/ private fun compactStyle() { val star = ImageView(context) - star.setImageDrawable(getStarDrawable()) - star.isActivated = true - star.setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, true, hostConfig)) - star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + star.apply { + setImageDrawable(getStarDrawable()) + isActivated = true + setColorFilter(RatingElementRendererUtil.getReadOnlyStarColor(color, true, hostConfig)) + layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + } ratingStars.add(star) addViewWithMargin(star, MARGIN_BETWEEN_STARS_AND_RATING_TEXT) addRatingAndCount() @@ -132,12 +136,14 @@ class RatingStarDisplayView: LinearLayout { private fun createTextView(text: String, textColor: String, style: Int): TextView { val color = RatingElementRendererUtil.getColorFromHexCode(textColor) val textView = TextView(context) - textView.text = text - textView.setTextColor(color) - textView.textSize = 16F - textView.setTypeface(null, style) - textView.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT) - textView.gravity = Gravity.CENTER_VERTICAL + textView.apply { + setText(text) + setTextColor(color) + textSize = 16F + setTypeface(null, style) + layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT) + gravity = Gravity.CENTER_VERTICAL + } return textView } @@ -153,8 +159,8 @@ class RatingStarDisplayView: LinearLayout { **/ private fun getStarDrawable(): Drawable? { return when (size) { - RatingSize.Medium -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_small, null) RatingSize.Large -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_medium, null) + else -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_small, null) } } diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt index f896655fe..aa0d8230b 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt @@ -70,15 +70,17 @@ class RatingStarInputView: LinearLayout { val rightMargin = Util.dpToPixels(context, RIGHT_MARGIN.toFloat()) for (index in 0 until maxStarsCount) { val star = ImageView(context) - star.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0f) - star.contentDescription = "Rating Star $index+1" - star.setImageDrawable(getStarDrawable()) - star.setColorFilter(RatingElementRendererUtil.getInputStarColor(color, index < value, hostConfig)) - star.isActivated = index < value - ratingStars.add(star) - star.setOnClickListener { - handleClick(index) + star.apply { + layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0f) + contentDescription = "Rating Star $index+1" + setImageDrawable(getStarDrawable()) + setColorFilter(RatingElementRendererUtil.getInputStarColor(color, index < value, hostConfig)) + isActivated = index < value + setOnClickListener { + handleClick(index) + } } + ratingStars.add(star) val params = star.layoutParams as LayoutParams if (index < maxStarsCount - 1) { params.rightMargin = rightMargin @@ -97,8 +99,8 @@ class RatingStarInputView: LinearLayout { private fun getStarDrawable(): Drawable? { return when (size) { - RatingSize.Medium -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_medium, null) RatingSize.Large -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_large, null) + else -> ResourcesCompat.getDrawable(resources, R.drawable.rating_star_selector_medium, null) } } diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt index b8043e1af..e68b4af2a 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/readonly/RatingElementRendererUtil.kt @@ -20,13 +20,13 @@ object RatingElementRendererUtil { fun getInputStarColor(color: RatingColor, isActivated: Boolean, hostConfig: HostConfig): Int { return if (isActivated) { when (color) { - RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingInputConfig().filledStar.neutralColor) RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingInputConfig().filledStar.marigoldColor) + else -> getColorFromHexCode(hostConfig.GetRatingInputConfig().filledStar.neutralColor) } } else { when (color) { - RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingInputConfig().emptyStar.neutralColor) RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingInputConfig().emptyStar.marigoldColor) + else -> getColorFromHexCode(hostConfig.GetRatingInputConfig().emptyStar.neutralColor) } } } @@ -38,13 +38,13 @@ object RatingElementRendererUtil { fun getReadOnlyStarColor(color: RatingColor, isActivated: Boolean, hostConfig: HostConfig): Int { return if (isActivated) { when (color) { - RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().filledStar.neutralColor) RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().filledStar.marigoldColor) + else -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().filledStar.neutralColor) } } else { when (color) { - RatingColor.Neutral -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().emptyStar.neutralColor) RatingColor.Marigold -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().emptyStar.marigoldColor) + else -> getColorFromHexCode(hostConfig.GetRatingLabelConfig().emptyStar.neutralColor) } } } From 9ee53af6926f84ae346cbd88113a50f9b57861a0 Mon Sep 17 00:00:00 2001 From: manpreet Date: Fri, 31 May 2024 13:11:56 +0530 Subject: [PATCH 08/10] added default case in switch statement --- .../io/adaptivecards/renderer/layout/RatingStarDisplayView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt index 7e4ae4320..66c4d9e9f 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarDisplayView.kt @@ -70,8 +70,8 @@ class RatingStarDisplayView: LinearLayout { layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) when (style) { - RatingStyle.Default -> defaultStyle() RatingStyle.Compact -> compactStyle() + else -> defaultStyle() } } From 926774b8cc3f9aea08fc6656ad364472c10b75ea Mon Sep 17 00:00:00 2001 From: manpreet Date: Fri, 31 May 2024 19:00:20 +0530 Subject: [PATCH 09/10] addressed review comments --- .../renderer/input/RatingInputRenderer.kt | 3 +- .../inputhandler/RatingInputHandler.kt | 29 ++++++++++---- .../renderer/layout/RatingStarInputView.kt | 38 +++++++++---------- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt index cece8d4bd..c7ca4ff5e 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt @@ -40,8 +40,7 @@ object RatingInputRenderer: BaseCardElementRenderer() { val view = RatingStarInputView( context, hostConfig, - ratingInput, - ratingInputHandler + ratingInput ) as LinearLayout RatingElementRendererUtil.applyHorizontalAlignment(view, ratingInput.GetHorizontalAlignment(), renderArgs) ratingInputHandler.setView(view) diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt index 90323f9ce..711344412 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt @@ -4,8 +4,10 @@ package io.adaptivecards.renderer.inputhandler import android.view.accessibility.AccessibilityEvent import io.adaptivecards.objectmodel.BaseInputElement +import io.adaptivecards.objectmodel.RatingInput import io.adaptivecards.renderer.Util import io.adaptivecards.renderer.layout.RatingStarInputView +import io.adaptivecards.renderer.layout.RatingStarInputViewListener /** * Input handler for Rating input @@ -13,15 +15,18 @@ import io.adaptivecards.renderer.layout.RatingStarInputView class RatingInputHandler( baseInputElement: BaseInputElement ): BaseInputHandler(baseInputElement) { - override fun getInput() = (m_view as RatingStarInputView).getRating().toString() + override fun getInput() = (m_view as RatingStarInputView).rating.toString() - override fun setInput(input: String?) { - // no-op + override fun setInput(input: String) { + try { + (m_view as RatingStarInputView).handleRatingChange(input.toDouble()) + } catch(e: NumberFormatException) { + return + } } override fun setFocusToView() { - val rating = (m_view as RatingStarInputView).getRating() - val focusView = (m_view as RatingStarInputView).getChildAt(if (rating == 0) 0 else rating - 1) + val focusView = (m_view as RatingStarInputView).getChildAt(0) Util.forceFocus(focusView) focusView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) } @@ -42,8 +47,16 @@ class RatingInputHandler( return isValid } - override fun registerInputObserver() { - notifyAllInputWatchers() + override fun resetValue() { + val ratingInput = Util.castTo(m_baseInputElement, RatingInput::class.java) + input = ratingInput.GetValue().toString() } -} \ No newline at end of file + override fun registerInputObserver() { + (m_view as RatingStarInputView).setRatingStarInputViewListener(object: RatingStarInputViewListener { + override fun onRatingChanged() { + notifyAllInputWatchers() + } + }) + } +} diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt index aa0d8230b..786a0ee37 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt @@ -14,16 +14,14 @@ import io.adaptivecards.objectmodel.RatingColor import io.adaptivecards.objectmodel.RatingInput import io.adaptivecards.objectmodel.RatingSize import io.adaptivecards.renderer.Util -import io.adaptivecards.renderer.inputhandler.RatingInputHandler import io.adaptivecards.renderer.readonly.RatingElementRendererUtil -import java.lang.ref.WeakReference /** * View to display the input rating stars **/ class RatingStarInputView: LinearLayout { - private var value = 0 + private var value: Double = 0.0 private var maxStarsCount = 5 @@ -33,26 +31,24 @@ class RatingStarInputView: LinearLayout { private val ratingStars: MutableList = ArrayList() - private var rating = 0 + var rating: Double = 0.0 private lateinit var hostConfig: HostConfig - private var ratingInputHandler: WeakReference? = null + private var listener: RatingStarInputViewListener? = null constructor( context: Context, hostConfig: HostConfig, - ratingInput: RatingInput, - ratingInputHandler: RatingInputHandler + ratingInput: RatingInput ) : super(context) { isSaveEnabled = true this.maxStarsCount = (ratingInput.GetMax().toInt()).coerceAtMost(5) - this.value = (ratingInput.GetValue().toInt()).coerceAtMost(5) + this.value = (ratingInput.GetValue()).coerceAtMost(5.0) this.color = ratingInput.GetRatingColor() this.rating = value this.size = ratingInput.GetRatingSize() this.hostConfig = hostConfig - this.ratingInputHandler = WeakReference(ratingInputHandler) initStars(context) } @@ -75,9 +71,9 @@ class RatingStarInputView: LinearLayout { contentDescription = "Rating Star $index+1" setImageDrawable(getStarDrawable()) setColorFilter(RatingElementRendererUtil.getInputStarColor(color, index < value, hostConfig)) - isActivated = index < value + isActivated = index < value.toInt() setOnClickListener { - handleClick(index) + handleRatingChange((index+1).toDouble()) } } ratingStars.add(star) @@ -89,12 +85,16 @@ class RatingStarInputView: LinearLayout { } } - private fun handleClick(index: Int) { - rating = index + 1 + fun setRatingStarInputViewListener(listener: RatingStarInputViewListener) { + this.listener = listener + } + + fun handleRatingChange(rating: Double) { + this.rating = rating for (i in 0 until maxStarsCount) { - ratingStars[i].isActivated = i < rating + ratingStars[i].isActivated = i < rating.toInt() } - ratingInputHandler?.get()?.registerInputObserver() + listener?.onRatingChanged() } private fun getStarDrawable(): Drawable? { @@ -104,11 +104,11 @@ class RatingStarInputView: LinearLayout { } } - fun getRating(): Int { - return rating - } - companion object { private const val RIGHT_MARGIN = 12 } } + +interface RatingStarInputViewListener { + fun onRatingChanged() +} From 24f120b02e80fa5fa9856d58a3fe63e3bd564338 Mon Sep 17 00:00:00 2001 From: manpreet Date: Mon, 3 Jun 2024 12:29:53 +0530 Subject: [PATCH 10/10] addressed review comments --- .../renderer/input/RatingInputRenderer.kt | 2 +- .../renderer/inputhandler/RatingInputHandler.kt | 13 +++++++++---- .../renderer/layout/RatingStarInputView.kt | 10 +++++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt index c7ca4ff5e..7fd1eee04 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/RatingInputRenderer.kt @@ -36,7 +36,7 @@ object RatingInputRenderer: BaseCardElementRenderer() { renderArgs: RenderArgs ): View { val ratingInput = Util.castTo(baseCardElement, RatingInput::class.java) - val ratingInputHandler = RatingInputHandler(ratingInput) + val ratingInputHandler = RatingInputHandler(ratingInput, renderedCard, renderArgs.containerCardId) val view = RatingStarInputView( context, hostConfig, diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt index 711344412..88d5a61f0 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/inputhandler/RatingInputHandler.kt @@ -5,6 +5,7 @@ package io.adaptivecards.renderer.inputhandler import android.view.accessibility.AccessibilityEvent import io.adaptivecards.objectmodel.BaseInputElement import io.adaptivecards.objectmodel.RatingInput +import io.adaptivecards.renderer.RenderedAdaptiveCard import io.adaptivecards.renderer.Util import io.adaptivecards.renderer.layout.RatingStarInputView import io.adaptivecards.renderer.layout.RatingStarInputViewListener @@ -13,13 +14,16 @@ import io.adaptivecards.renderer.layout.RatingStarInputViewListener * Input handler for Rating input **/ class RatingInputHandler( - baseInputElement: BaseInputElement -): BaseInputHandler(baseInputElement) { - override fun getInput() = (m_view as RatingStarInputView).rating.toString() + baseInputElement: BaseInputElement, + renderedAdaptiveCard: RenderedAdaptiveCard?, + cardId: Long +): BaseInputHandler(baseInputElement, renderedAdaptiveCard, cardId) { + + override fun getInput() = (m_view as RatingStarInputView).getRating().toString() override fun setInput(input: String) { try { - (m_view as RatingStarInputView).handleRatingChange(input.toDouble()) + (m_view as RatingStarInputView).setRating(input.toDouble()) } catch(e: NumberFormatException) { return } @@ -58,5 +62,6 @@ class RatingInputHandler( notifyAllInputWatchers() } }) + addValueChangedActionInputWatcher() } } diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt index 786a0ee37..138927539 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/layout/RatingStarInputView.kt @@ -31,7 +31,7 @@ class RatingStarInputView: LinearLayout { private val ratingStars: MutableList = ArrayList() - var rating: Double = 0.0 + private var rating: Double = 0.0 private lateinit var hostConfig: HostConfig @@ -73,7 +73,7 @@ class RatingStarInputView: LinearLayout { setColorFilter(RatingElementRendererUtil.getInputStarColor(color, index < value, hostConfig)) isActivated = index < value.toInt() setOnClickListener { - handleRatingChange((index+1).toDouble()) + setRating((index+1).toDouble()) } } ratingStars.add(star) @@ -85,11 +85,15 @@ class RatingStarInputView: LinearLayout { } } + fun getRating(): Double { + return rating + } + fun setRatingStarInputViewListener(listener: RatingStarInputViewListener) { this.listener = listener } - fun handleRatingChange(rating: Double) { + fun setRating(rating: Double) { this.rating = rating for (i in 0 until maxStarsCount) { ratingStars[i].isActivated = i < rating.toInt()