Payment Method Selection UI Component

Payment Method Selection UI Component

The Payment Method Selection UI Component displays the available payment methods and provides functionality to select one of them.

Basic implementation

This code sample demonstrates a basic implementation of Payment Method Selection UI Component.

Implementation
Layout

public class PaymentMethodSelectionUiComponentFragment extends Fragment implements PaymentMethodSelectionUiComponent {

    private PaymentMethodSelectionUiComponentFragmentBinding binding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        binding = PaymentMethodSelectionUiComponentFragmentBinding.inflate(inflater, container, false);

        return binding.getRoot();
    }

    @Override
    public void onUiComponentCreated(@NonNull PaymentMethodSelectionUiComponentInteraction interaction) {
        // this method will be called after onViewCreated() and before onStart(),
        // it provides the link to the UI Component interaction, use it to initialize your UI,
        // use interaction to get available payment methods
        PaymentMethod[] paymentMethods = interaction.getPaymentMethods();

        PaymentMethodAdapter adapter = new PaymentMethodAdapter(
                paymentMethods,
                // use interaction to select payment method
                position -> interaction.onPaymentMethodSelected(paymentMethods[position])
        );

        binding.paymentMethodRecyclerView.setAdapter(adapter);
    }

    private static class PaymentMethodAdapter extends RecyclerView.Adapter<PaymentMethodAdapter.ViewHolder> {

        @FunctionalInterface
        interface OnItemClickListener {

            void onItemClick(int position);
        }

        static class ViewHolder extends RecyclerView.ViewHolder {

            private final PaymentMethodItemBinding binding;

            public ViewHolder(@NonNull PaymentMethodItemBinding binding,
                              @NonNull OnItemClickListener listener) {
                super(binding.getRoot());

                this.binding = binding;
                binding.getRoot().setOnClickListener(view -> {
                    int position = getAbsoluteAdapterPosition();

                    if (position != RecyclerView.NO_POSITION) {
                        listener.onItemClick(position);
                    }
                });
            }
        }

        private final PaymentMethod[] paymentMethods;
        private final OnItemClickListener listener;

        public PaymentMethodAdapter(@NonNull PaymentMethod[] paymentMethods,
                                    @NonNull OnItemClickListener listener) {
            this.paymentMethods = paymentMethods;
            this.listener = listener;
        }

        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
                                             int viewType) {
            PaymentMethodItemBinding binding = PaymentMethodItemBinding.inflate(
                    LayoutInflater.from(parent.getContext()), parent, false);

            return new ViewHolder(binding, listener);
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder,
                                     int position) {
            PaymentMethod paymentMethod = paymentMethods[position];
            holder.binding.paymentMethodName.setText(paymentMethod.getDisplayableName());
        }

        @Override
        public int getItemCount() {
            return paymentMethods.length;
        }
    }
}
class PaymentMethodSelectionUiComponentFragment : Fragment(), PaymentMethodSelectionUiComponent {

    private var _binding: PaymentMethodSelectionUiComponentFragmentBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = PaymentMethodSelectionUiComponentFragmentBinding.inflate(
            inflater, container, false)

        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()

        _binding = null
    }

    override fun onUiComponentCreated(interaction: PaymentMethodSelectionUiComponentInteraction) {
        // this method will be called after onViewCreated() and before onStart(),
        // it provides the link to the UI Component interaction, use it to initialize your UI,
        // use interaction to get available payment methods.
        val paymentMethods = interaction.paymentMethods
        val adapter = PaymentMethodAdapter(paymentMethods) {
            // use interaction to select payment method
            position -> interaction.onPaymentMethodSelected(paymentMethods[position])
        }

        binding.paymentMethodRecyclerView.adapter = adapter
    }

    class PaymentMethodAdapter(private val paymentMethods: Array,
                               private val listener: OnItemClickListener) :
        RecyclerView.Adapter() {

        fun interface OnItemClickListener {

            fun onItemClick(position: Int)
        }

        class ViewHolder(val binding: PaymentMethodListItemBinding, listener: OnItemClickListener) :
            RecyclerView.ViewHolder(binding.root) {

            init {
                itemView.setOnClickListener {
                    val position = adapterPosition

                    if (position != RecyclerView.NO_POSITION) listener.onItemClick(position)
                }
            }
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val binding = PaymentMethodListItemBinding.inflate(
                LayoutInflater.from(parent.context), parent, false)

            return ViewHolder(binding, listener)
        }

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.binding.paymentMethodName.text = paymentMethods[position].displayableName
        }

        override fun getItemCount() = paymentMethods.size
    }
}