Skip to content

Commit

Permalink
Fix PIN Styling Parity for XML and dynamic rendering (#277)
Browse files Browse the repository at this point in the history
<!-- Update your title to prefix with your ticket number -->

## What
Fix PIN field sizing discrepancies between BT and Rosetta for xml-initialized and dynamically-initialized `ForagePINEditText`.

This PR also simplifies the **catalog** view of the Sample App since the previous view was overwhelming to develop against. 

<!-- Please include a summary of the change. List any dependencies that are required for this change. -->

## Why
The previous fix only:
1. zero'd out padding when the ForagePINEditText was rendered via XML; it did not zero out padding for dynamically rendered ForagePINEditText
2. did not address the styling discrepancies between BT and rosetta due different default textSizes

See [this code comment](https://app.graphite.dev/github/pr/teamforage/forage-android-sdk/277/Add-dynamically-created-ForagePINEditText-to-catalog#comment-PRRC_kwDOIQqcBs5iOMav) for more details.

<!-- Describe the motivations behind this change if they are a subset of your ticket -->

## Test Plan

- ❌ No unit tests for this since it's styling
- ✅ Danilo and Devin have both extensively tested this code change on their local machines.<!-- If so, please describe how to test below. -->

## Demo

<!-- If applicable, please include a screenshot to this PR description -->
<!-- If applicable, please include a screen recording and post it in #feature-recordings -->

## How
Can be released immediately 
<!-- Describe the rollout plan if it includes multiple PRs/Repos or requires extra steps beyond reverting this PR -->
  • Loading branch information
devinmorgan authored Jun 20, 2024
1 parent b658499 commit 9c253d8
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Application
import android.content.Context
import android.graphics.Typeface
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatEditText
import com.joinforage.forage.android.R
import com.joinforage.forage.android.core.services.EnvConfig
import com.joinforage.forage.android.core.services.ForageConfig
Expand Down Expand Up @@ -108,6 +109,32 @@ class ForagePINEditText @JvmOverloads constructor(
recycle()
}
}

// The following pieces of code are to fix height
// differences in the appearance of Rosetta-backed
// vs BT-backed ForagePINEditText in the case where
// no app:inputHeight or app:inputWidth are set.

// zero out the padding for Basis Theory element
val btFrame = btVaultWrapper.getTextElement()
val btTextElement = btFrame.getChildAt(0) as AppCompatEditText
btTextElement.setPadding(0, 0, 0, 0)

// ensure Rosetta's textSize is the same as BTs textSize
// There are three cases:
// 1) using XML layouts and somebody passes app:textSize ->
// both RosettaPinElement and BTVaultWrapper read
// that value and independently set the correct textSize
// 2) using XML layouts and app:textSize is not set ->
// This line of code fixes that issue
// 3) create dynamic instance of ForagePINEditText and
// call setTextSize ->
// setTextSize calls vault.setTextSize so the only
// visible text field will have the correct textSize
// 3) create dynamic instance of ForagePINEditText and
// never call setTextSize ->
// This line of code fixes that issue
rosettaPinElement.setTextSize(btTextElement.textSize)
}

private fun initWithForageConfig(forageConfig: ForageConfig) {
Expand Down Expand Up @@ -179,25 +206,6 @@ class ForagePINEditText @JvmOverloads constructor(
logger: Log
): AbstractVaultSubmitter = vault.getVaultSubmitter(envConfig, logger)

override fun onFinishInflate() {
super.onFinishInflate()

// we use post to make sure that this zero-ing out
// happens after all of BT's code executes. We need
// the zero-ing out to "win"
post {
// zero out the padding for Basis Theory element
// we expressly need to wait for after the BT
// Element has inflated before we can do this
// else an exception is thrown.
// also worth noting that the VGS padding is
// zero-d out in the dimens.xml file
val btFrame = btVaultWrapper.getTextElement()
val btTextElement = btFrame.getChildAt(0)
btTextElement.setPadding(0, 0, 0, 0)
}
}

override var typeface: Typeface?
get() = if (vault == btVaultWrapper) btVaultWrapper.typeface else rosettaPinElement.typeface
set(value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ internal class RosettaPinElement @JvmOverloads constructor(
}

override fun setTextSize(textSize: Float) {
_editText.textSize = textSize
_editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
}

override fun setHint(hint: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.joinforage.android.example.databinding.FragmentCatalogBinding
import com.joinforage.forage.android.core.services.ForageConfig
import com.joinforage.forage.android.ecom.ui.element.ForagePINEditText

class CatalogFragment : Fragment() {

Expand All @@ -32,25 +33,28 @@ class CatalogFragment : Fragment() {
merchantId = "0123456"
)

// ForagePANEditText can be created via XML layouts or
// dynamically. These different modes of creation are
// a natural point of styling differences to emerge.
// We add a ForagePANEditText to the catalog in the
// hopes that we'll spot these discrepancies
// NOTE: this view is currently unstyled compared to
// the other ForagePINEditText in the catalog which was
// created via XML and has some XML styles associated
// with it.
val dynamicPinEditText = ForagePINEditText(requireContext(), null)
binding.root.addView(dynamicPinEditText)

dynamicPinEditText.setForageConfig(forageConfig)
binding.firstForageEditText.setForageConfig(forageConfig)
binding.secondEditText.setForageConfig(forageConfig)
binding.thirdEditText.setForageConfig(forageConfig)
binding.fourthEditText.setForageConfig(forageConfig)
binding.foragePinEditText.setForageConfig(forageConfig)
binding.secondForagePINEditText.setForageConfig(forageConfig)
binding.thirdForagePINEditText.setForageConfig(forageConfig)

// NOTE: we call setForageConfig a second time here so that
// the CI tests always confirm that running setForageConfig
// more than once is OK and does not cause a crash. So,
// these duplicate calls are intentional here
binding.firstForageEditText.setForageConfig(forageConfig)
binding.secondEditText.setForageConfig(forageConfig)
binding.thirdEditText.setForageConfig(forageConfig)
binding.fourthEditText.setForageConfig(forageConfig)
binding.foragePinEditText.setForageConfig(forageConfig)
binding.secondForagePINEditText.setForageConfig(forageConfig)
binding.thirdForagePINEditText.setForageConfig(forageConfig)

return root
}
Expand Down
105 changes: 18 additions & 87 deletions sample-app/src/main/res/layout/fragment_catalog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,96 +7,27 @@
android:layout_marginBottom="100dp"
tools:context=".ui.catalog.CatalogFragment">

<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
<com.joinforage.forage.android.ecom.ui.element.ForagePANEditText
android:id="@+id/firstForageEditText"
style="?attr/catalogFirstForagePanEditTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<com.joinforage.forage.android.ecom.ui.element.ForagePANEditText
android:id="@+id/firstForageEditText"
style="?attr/catalogFirstForagePanEditTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />

<com.joinforage.forage.android.ecom.ui.element.ForagePANEditText
android:id="@+id/secondEditText"
style="?catalogSecondForagePanEditTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/firstForageEditText" />

<com.joinforage.forage.android.ecom.ui.element.ForagePANEditText
android:id="@+id/thirdEditText"
style="?catalogThirdForagePanEditTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/secondEditText" />

<com.joinforage.forage.android.ecom.ui.element.ForagePANEditText
android:id="@+id/fourthEditText"
style="?catalogFourthForagePanEditTextStyle"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/thirdEditText" />
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />

<com.joinforage.forage.android.ecom.ui.element.ForagePINEditText
android:id="@+id/foragePinEditText"
style="@style/ForagePINEditTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:inputWidth="200dp"
app:inputHeight="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/fourthEditText" />

<com.joinforage.forage.android.ecom.ui.element.ForagePINEditText
android:id="@+id/secondForagePINEditText"
style="@style/SecondForagePINEditTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:elementWidth="150dp"
app:elementHeight="70dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/foragePinEditText" />

<com.joinforage.forage.android.ecom.ui.element.ForagePINEditText
android:id="@+id/thirdForagePINEditText"
style="@style/ThirdForagePINEditTextStyle"
android:layout_width="80dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/secondForagePINEditText" />

</androidx.constraintlayout.widget.ConstraintLayout>

</ScrollView>
<com.joinforage.forage.android.ecom.ui.element.ForagePINEditText
android:id="@+id/foragePinEditText"
style="@style/ForagePINEditTextStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>

</androidx.constraintlayout.widget.ConstraintLayout>

0 comments on commit 9c253d8

Please sign in to comment.