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
    }
}