Слушатель кнопки с затенением в ViewPager - PullRequest
0 голосов
/ 13 ноября 2018

Я создаю вид, где у меня была какая-то форма регистрации, и я столкнулся со странной проблемой. Поэтому мне нужно создать форму, в которой будет 10 экранов, на каждом из которых пользователю будет предложено ввести конкретную информацию. Поэтому я решил использовать ViewPager с FragmentPageAdapter. Большинство представлений выглядят одинаково, поэтому я хотел использовать один файл макета во всех них. Код макета размещен ниже.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/form_text"
        style="@style/FormText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="@string/registration_experience_text" />

    <com.TwoButtonsView
        android:id="@+id/buttons_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/default_app_margin"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/form_text"
        app:negative_button_text=""
        app:positive_button_text="" />

</androidx.constraintlayout.widget.ConstraintLayout>

TwoButtonsView - это мой пользовательский вид, который выглядит следующим образом:

class TwoButtonsView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

    private lateinit var negativeButton: MaterialButton
    private lateinit var positiveButton: MaterialButton

    private var listener: TwoButtonsViewListener? = null

    interface TwoButtonsViewListener {
        fun onNegativeButtonClick()
        fun onPositiveButtonClick()
    }

    init {
        init(context, attrs)
    }

    private fun init(context: Context, attrs: AttributeSet?) {
        val view = LayoutInflater.from(context).inflate(R.layout.two_buttons_layout, this, true)

        negativeButton = view.findViewById(R.id.negative_button)
        positiveButton = view.findViewById(R.id.positive_button)

        negativeButton.setOnClickListener {
            listener?.onNegativeButtonClick()
            setButtonClicked(context, negativeButton)
            setButtonDefault(context, positiveButton)
        }

        positiveButton.setOnClickListener {
            listener?.onPositiveButtonClick()
            setButtonClicked(context, positiveButton)
            setButtonDefault(context, negativeButton)
        }

        if (attrs == null) {
            return
        }

        val typedArray =
            context.obtainStyledAttributes(attrs, R.styleable.TwoButtonsView)
        try {
            setNegativeButtonText(typedArray)
            setPositiveButtonText(typedArray)
        } catch (exception: Exception) {
            Timber.e(exception)
        } finally {
            typedArray.recycle()
        }

    }

    private fun setButtonClicked(context: Context, button: MaterialButton) {
        button.backgroundTintList = ColorStateList.valueOf(Color.WHITE)
        button.setTextColor(ContextCompat.getColor(context, R.color.colorPrimary))
    }

    private fun setButtonDefault(context: Context, button: MaterialButton) {
        button.backgroundTintList =
                ColorStateList.valueOf(ContextCompat.getColor(context, R.color.colorPrimary))
        button.setTextColor(Color.WHITE)
    }

    private fun setNegativeButtonText(typedArray: TypedArray) {
        negativeButton.text = typedArray.getString(R.styleable.TwoButtonsView_negative_button_text)
    }

    private fun setPositiveButtonText(typedArray: TypedArray) {
        positiveButton.text = typedArray.getString(R.styleable.TwoButtonsView_positive_button_text)
    }

Файл макета:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <com.google.android.material.button.MaterialButton
        android:id="@+id/positive_button"
        style="@style/TwoButtonsFormDefaultButton"
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_marginTop="@dimen/default_app_margin"
        android:layout_marginEnd="3dp"
        app:layout_constraintEnd_toStartOf="@id/negative_button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/form_text"
        tools:text="@string/registration_experience_positive" />

    <com.google.android.material.button.MaterialButton
        android:id="@+id/negative_button"
        style="@style/TwoButtonsFormDefaultButton"
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:layout_marginStart="3dp"
        android:layout_marginTop="@dimen/default_app_margin"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/positive_button"
        app:layout_constraintTop_toBottomOf="@id/form_text"
        tools:text="@string/registration_experience_negative" />

</androidx.constraintlayout.widget.ConstraintLayout>

Мой адаптер для ViewPager выглядит так:

class RegistrationPagerAdapter(
    fragmentManager: FragmentManager
) : FragmentStatePagerAdapter(fragmentManager) {

    override fun getItem(position: Int) =
        when (position) {
            0 -> RegistrationExperienceFragment()
            1 -> RegistrationRoleFragment()
            2 -> RegistrationNameFragment()
            3 -> RegistrationLastNameFragment()
            4 -> RegistrationBirthdayFragment()
            5 -> RegistrationGenderFragment()
            6 -> RegistrationCountryFragment()
            7 -> RegistrationPhoneNumberFragment()
            8 -> RegistrationNewsletterFragment()
            else -> RegistrationOpportunitiesFragment()
        }

    override fun getCount(): Int = 10
}

И почти каждый Fragment выглядит так:

class RegistrationExperienceFragment : BaseFragment(), TwoButtonsView.TwoButtonsViewListener {

    override fun onNegativeButtonClick() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onPositiveButtonClick() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = inflater.inflate(R.layout.fragment_two_buttons_form, container, false)

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        setupUi()
    }

    private fun setupUi() {
        form_text.text = getString(R.string.registration_experience_text)
    }

    companion object {

        const val TAG = "RegistrationExperienceFragment"

        fun newInstance() =
            RegistrationExperienceFragment()
    }
}

И что здесь не так, так это то, что когда я перехожу ко второму фрагменту (он выглядит точно так же, как первый), а затем я возвращаюсь к первому фрагменту, все события нажатия кнопки применяются ко второму фрагменту. Поэтому, когда я нажимаю кнопку на первом фрагменте, фактически цвет кнопки изменяется на втором фрагменте, а цвет на первом фрагменте не изменяется. Я хотел бы избежать создания каждого нового XML-файла для фрагмента, но я не знаю, возможно ли это на самом деле.

Любая помощь будет высоко оценена;)

...