From 04f0146afd193d34e43c8d0061e3ba5ad2b2ddb7 Mon Sep 17 00:00:00 2001 From: Tobias Preuss Date: Wed, 24 Jun 2020 12:16:30 +0200 Subject: [PATCH 1/2] Use Context#withStyledAttributes extension function. + This function is more concise and ensures "recycle()" is always invoked. + Sources: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-preference-release/core/core-ktx/src/main/java/androidx/core/content/Context.kt#52 --- CHANGES.md | 2 +- .../behavior/PercentViewBehavior.kt | 29 +++++---- .../core/platform/EllipsizingTextView.kt | 8 ++- .../core/platform/MaxHeightScrollView.kt | 9 +-- .../core/ui/views/BottomSheetActionButton.kt | 18 ++--- .../timeline/item/PollResultLineView.kt | 13 ++-- .../reactions/widget/ReactionButton.kt | 65 ++++++++++--------- 7 files changed, 75 insertions(+), 69 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 20b3b34375..22220d3b0b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,7 +26,7 @@ Build 🧱: - Upgrade gradle from 5.4.1 to 5.6.4 Other changes: - - + - Use `Context#withStyledAttributes` extension function (#1546) Changes in Riot.imX 0.91.3 (2020-07-01) =================================================== diff --git a/vector/src/main/java/im/vector/riotx/core/animations/behavior/PercentViewBehavior.kt b/vector/src/main/java/im/vector/riotx/core/animations/behavior/PercentViewBehavior.kt index 967d7d638d..37c07b8293 100644 --- a/vector/src/main/java/im/vector/riotx/core/animations/behavior/PercentViewBehavior.kt +++ b/vector/src/main/java/im/vector/riotx/core/animations/behavior/PercentViewBehavior.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 New Vector Ltd + * Copyright 2020 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import android.graphics.drawable.ColorDrawable import android.util.AttributeSet import android.view.View import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.content.withStyledAttributes import im.vector.riotx.R import kotlin.math.abs @@ -67,19 +68,19 @@ class PercentViewBehavior(context: Context, attrs: AttributeSet) : Coo private var isPrepared: Boolean = false init { - val a = context.obtainStyledAttributes(attrs, R.styleable.PercentViewBehavior) - dependViewId = a.getResourceId(R.styleable.PercentViewBehavior_behavior_dependsOn, 0) - dependType = a.getInt(R.styleable.PercentViewBehavior_behavior_dependType, DEPEND_TYPE_WIDTH) - dependTarget = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_dependTarget, UNSPECIFIED_INT) - targetX = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetX, UNSPECIFIED_INT) - targetY = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetY, UNSPECIFIED_INT) - targetWidth = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetWidth, UNSPECIFIED_INT) - targetHeight = a.getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetHeight, UNSPECIFIED_INT) - targetBackgroundColor = a.getColor(R.styleable.PercentViewBehavior_behavior_targetBackgroundColor, UNSPECIFIED_INT) - targetAlpha = a.getFloat(R.styleable.PercentViewBehavior_behavior_targetAlpha, UNSPECIFIED_FLOAT) - targetRotateX = a.getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateX, UNSPECIFIED_FLOAT) - targetRotateY = a.getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateY, UNSPECIFIED_FLOAT) - a.recycle() + context.withStyledAttributes(attrs, R.styleable.PercentViewBehavior) { + dependViewId = getResourceId(R.styleable.PercentViewBehavior_behavior_dependsOn, 0) + dependType = getInt(R.styleable.PercentViewBehavior_behavior_dependType, DEPEND_TYPE_WIDTH) + dependTarget = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_dependTarget, UNSPECIFIED_INT) + targetX = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetX, UNSPECIFIED_INT) + targetY = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetY, UNSPECIFIED_INT) + targetWidth = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetWidth, UNSPECIFIED_INT) + targetHeight = getDimensionPixelOffset(R.styleable.PercentViewBehavior_behavior_targetHeight, UNSPECIFIED_INT) + targetBackgroundColor = getColor(R.styleable.PercentViewBehavior_behavior_targetBackgroundColor, UNSPECIFIED_INT) + targetAlpha = getFloat(R.styleable.PercentViewBehavior_behavior_targetAlpha, UNSPECIFIED_FLOAT) + targetRotateX = getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateX, UNSPECIFIED_FLOAT) + targetRotateY = getFloat(R.styleable.PercentViewBehavior_behavior_targetRotateY, UNSPECIFIED_FLOAT) + } } private fun prepare(parent: CoordinatorLayout, child: View, dependency: View) { diff --git a/vector/src/main/java/im/vector/riotx/core/platform/EllipsizingTextView.kt b/vector/src/main/java/im/vector/riotx/core/platform/EllipsizingTextView.kt index f451308c36..f54776fc40 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/EllipsizingTextView.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/EllipsizingTextView.kt @@ -38,6 +38,7 @@ import android.text.TextUtils.substring import android.text.style.ForegroundColorSpan import android.util.AttributeSet import androidx.appcompat.widget.AppCompatTextView +import androidx.core.content.withStyledAttributes import timber.log.Timber import java.util.ArrayList import java.util.regex.Pattern @@ -71,6 +72,7 @@ class EllipsizingTextView @JvmOverloads constructor(context: Context, attrs: Att private var maxLines = 0 private var lineSpacingMult = 1.0f private var lineAddVertPad = 0.0f + /** * The end punctuation which will be removed when appending [.ELLIPSIS]. */ @@ -408,9 +410,9 @@ class EllipsizingTextView @JvmOverloads constructor(context: Context, attrs: Att } init { - val a = context.obtainStyledAttributes(attrs, intArrayOf(android.R.attr.maxLines, android.R.attr.ellipsize), defStyle, 0) - maxLines = a.getInt(0, Int.MAX_VALUE) - a.recycle() + context.withStyledAttributes(attrs, intArrayOf(android.R.attr.maxLines, android.R.attr.ellipsize), defStyle) { + maxLines = getInt(0, Int.MAX_VALUE) + } setEndPunctuationPattern(DEFAULT_END_PUNCTUATION) val currentTextColor = currentTextColor val ellipsizeColor = Color.argb(ELLIPSIZE_ALPHA, Color.red(currentTextColor), Color.green(currentTextColor), Color.blue(currentTextColor)) diff --git a/vector/src/main/java/im/vector/riotx/core/platform/MaxHeightScrollView.kt b/vector/src/main/java/im/vector/riotx/core/platform/MaxHeightScrollView.kt index b8587750a3..99c158252f 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/MaxHeightScrollView.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/MaxHeightScrollView.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 New Vector Ltd + * Copyright 2020 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package im.vector.riotx.core.platform import android.content.Context import android.util.AttributeSet +import androidx.core.content.withStyledAttributes import androidx.core.widget.NestedScrollView import im.vector.riotx.R @@ -34,9 +35,9 @@ class MaxHeightScrollView @JvmOverloads constructor(context: Context, attrs: Att init { if (attrs != null) { - val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView) - maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_maxHeight, DEFAULT_MAX_HEIGHT) - styledAttrs.recycle() + context.withStyledAttributes(attrs, R.styleable.MaxHeightScrollView) { + maxHeight = getDimensionPixelSize(R.styleable.MaxHeightScrollView_maxHeight, DEFAULT_MAX_HEIGHT) + } } } diff --git a/vector/src/main/java/im/vector/riotx/core/ui/views/BottomSheetActionButton.kt b/vector/src/main/java/im/vector/riotx/core/ui/views/BottomSheetActionButton.kt index d29982c9e4..455e856833 100644 --- a/vector/src/main/java/im/vector/riotx/core/ui/views/BottomSheetActionButton.kt +++ b/vector/src/main/java/im/vector/riotx/core/ui/views/BottomSheetActionButton.kt @@ -25,6 +25,7 @@ import android.view.View import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView +import androidx.core.content.withStyledAttributes import androidx.core.view.isGone import androidx.core.view.isInvisible import androidx.core.view.isVisible @@ -117,16 +118,15 @@ class BottomSheetActionButton @JvmOverloads constructor( inflate(context, R.layout.item_verification_action, this) ButterKnife.bind(this) - val typedArray = context.obtainStyledAttributes(attrs, R.styleable.BottomSheetActionButton, 0, 0) - title = typedArray.getString(R.styleable.BottomSheetActionButton_actionTitle) ?: "" - subTitle = typedArray.getString(R.styleable.BottomSheetActionButton_actionDescription) ?: "" - forceStartPadding = typedArray.getBoolean(R.styleable.BottomSheetActionButton_forceStartPadding, false) - leftIcon = typedArray.getDrawable(R.styleable.BottomSheetActionButton_leftIcon) + context.withStyledAttributes(attrs, R.styleable.BottomSheetActionButton) { + title = getString(R.styleable.BottomSheetActionButton_actionTitle) ?: "" + subTitle = getString(R.styleable.BottomSheetActionButton_actionDescription) ?: "" + forceStartPadding = getBoolean(R.styleable.BottomSheetActionButton_forceStartPadding, false) + leftIcon = getDrawable(R.styleable.BottomSheetActionButton_leftIcon) - rightIcon = typedArray.getDrawable(R.styleable.BottomSheetActionButton_rightIcon) + rightIcon = getDrawable(R.styleable.BottomSheetActionButton_rightIcon) - tint = typedArray.getColor(R.styleable.BottomSheetActionButton_tint, ThemeUtils.getColor(context, android.R.attr.textColor)) - - typedArray.recycle() + tint = getColor(R.styleable.BottomSheetActionButton_tint, ThemeUtils.getColor(context, android.R.attr.textColor)) + } } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt index c52b863658..bee3ca6c5b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt @@ -22,6 +22,7 @@ import android.view.View import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView +import androidx.core.content.withStyledAttributes import butterknife.BindView import butterknife.ButterKnife import im.vector.riotx.R @@ -73,11 +74,11 @@ class PollResultLineView @JvmOverloads constructor( orientation = HORIZONTAL ButterKnife.bind(this) - val typedArray = context.obtainStyledAttributes(attrs, R.styleable.PollResultLineView, 0, 0) - label = typedArray.getString(R.styleable.PollResultLineView_optionName) ?: "" - percent = typedArray.getString(R.styleable.PollResultLineView_optionCount) ?: "" - optionSelected = typedArray.getBoolean(R.styleable.PollResultLineView_optionSelected, false) - isWinner = typedArray.getBoolean(R.styleable.PollResultLineView_optionIsWinner, false) - typedArray.recycle() + context.withStyledAttributes(attrs, R.styleable.PollResultLineView) { + label = getString(R.styleable.PollResultLineView_optionName) ?: "" + percent = getString(R.styleable.PollResultLineView_optionCount) ?: "" + optionSelected = getBoolean(R.styleable.PollResultLineView_optionSelected, false) + isWinner = getBoolean(R.styleable.PollResultLineView_optionIsWinner, false) + } } } diff --git a/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt b/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt index 811d399b23..ec5aba8ee5 100644 --- a/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt +++ b/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 New Vector Ltd + * Copyright 2020 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +34,7 @@ import android.widget.TextView import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.core.content.ContextCompat +import androidx.core.content.withStyledAttributes import im.vector.riotx.EmojiCompatWrapper import im.vector.riotx.R import im.vector.riotx.core.di.HasScreenInjector @@ -110,41 +111,41 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut // emojiView?.typeface = this.emojiTypeFace ?: Typeface.DEFAULT - val array = context.obtainStyledAttributes(attrs, R.styleable.ReactionButton, defStyleAttr, 0) + context.withStyledAttributes(attrs, R.styleable.ReactionButton, defStyleAttr) { - onDrawable = ContextCompat.getDrawable(context, R.drawable.rounded_rect_shape) - offDrawable = ContextCompat.getDrawable(context, R.drawable.rounded_rect_shape_off) + onDrawable = ContextCompat.getDrawable(context, R.drawable.rounded_rect_shape) + offDrawable = ContextCompat.getDrawable(context, R.drawable.rounded_rect_shape_off) - circleStartColor = array.getColor(R.styleable.ReactionButton_circle_start_color, 0) + circleStartColor = getColor(R.styleable.ReactionButton_circle_start_color, 0) - if (circleStartColor != 0) { - circleView.startColor = circleStartColor + if (circleStartColor != 0) { + circleView.startColor = circleStartColor + } + + circleEndColor = getColor(R.styleable.ReactionButton_circle_end_color, 0) + + if (circleEndColor != 0) { + circleView.endColor = circleEndColor + } + + dotPrimaryColor = getColor(R.styleable.ReactionButton_dots_primary_color, 0) + dotSecondaryColor = getColor(R.styleable.ReactionButton_dots_secondary_color, 0) + + if (dotPrimaryColor != 0 && dotSecondaryColor != 0) { + dotsView.setColors(dotPrimaryColor, dotSecondaryColor) + } + + getString(R.styleable.ReactionButton_emoji)?.let { + reactionString = it + } + + reactionCount = getInt(R.styleable.ReactionButton_reaction_count, 0) + + val status = getBoolean(R.styleable.ReactionButton_toggled, false) + setChecked(status) + setOnClickListener(this@ReactionButton) + setOnLongClickListener(this@ReactionButton) } - - circleEndColor = array.getColor(R.styleable.ReactionButton_circle_end_color, 0) - - if (circleEndColor != 0) { - circleView.endColor = circleEndColor - } - - dotPrimaryColor = array.getColor(R.styleable.ReactionButton_dots_primary_color, 0) - dotSecondaryColor = array.getColor(R.styleable.ReactionButton_dots_secondary_color, 0) - - if (dotPrimaryColor != 0 && dotSecondaryColor != 0) { - dotsView.setColors(dotPrimaryColor, dotSecondaryColor) - } - - array.getString(R.styleable.ReactionButton_emoji)?.let { - reactionString = it - } - - reactionCount = array.getInt(R.styleable.ReactionButton_reaction_count, 0) - - val status = array.getBoolean(R.styleable.ReactionButton_toggled, false) - setChecked(status) - setOnClickListener(this) - setOnLongClickListener(this) - array.recycle() } private fun getDrawableFromResource(array: TypedArray, styleableIndexId: Int): Drawable? { From 179474b975a2628c8b108dd85e6cd06661cab51a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2020 17:51:57 +0200 Subject: [PATCH 2/2] Cleanup --- .../riotx/features/reactions/widget/ReactionButton.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt b/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt index ec5aba8ee5..140edaf03a 100644 --- a/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt +++ b/vector/src/main/java/im/vector/riotx/features/reactions/widget/ReactionButton.kt @@ -45,7 +45,8 @@ import javax.inject.Inject * An animated reaction button. * Displays a String reaction (emoji), with a count, and that can be selected or not (toggle) */ -class ReactionButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, +class ReactionButton @JvmOverloads constructor(context: Context, + attrs: AttributeSet? = null, defStyleAttr: Int = 0) : FrameLayout(context, attrs, defStyleAttr), View.OnClickListener, View.OnLongClickListener { @@ -110,9 +111,7 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut countTextView?.text = TextUtils.formatCountToShortDecimal(reactionCount) // emojiView?.typeface = this.emojiTypeFace ?: Typeface.DEFAULT - context.withStyledAttributes(attrs, R.styleable.ReactionButton, defStyleAttr) { - onDrawable = ContextCompat.getDrawable(context, R.drawable.rounded_rect_shape) offDrawable = ContextCompat.getDrawable(context, R.drawable.rounded_rect_shape_off) @@ -143,9 +142,10 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut val status = getBoolean(R.styleable.ReactionButton_toggled, false) setChecked(status) - setOnClickListener(this@ReactionButton) - setOnLongClickListener(this@ReactionButton) } + + setOnClickListener(this) + setOnLongClickListener(this) } private fun getDrawableFromResource(array: TypedArray, styleableIndexId: Int): Drawable? {