-1
class ClubCardsPricesFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_club_cards_prices, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val items = listOf(
            ClubCardPrices(R.drawable.some_people, "Друзья", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта"),
            ClubCardPrices(R.drawable.some_people, "Индивидуальная", "", "1 год", "с 7:00 до 23:00", "Тренажерный зал, залы групповых программ, бассейн, турецкая и русская бани, фитнес тестирование", "60 дней", "3 водных инструктажа", "3 гостевых визизта")
        )
        val clubCardsPricesRecyclerView = view.findViewById<RecyclerView>(R.id.card_types_recyclerview1)
        clubCardsPricesRecyclerView.layoutManager = GridLayoutManager(activity, 2)
        clubCardsPricesRecyclerView.adapter = ClubCardPricesAdapter(items) { item, cardImage, cardName ->
            val constraintLayout = view.findViewById<ConstraintLayout>(R.id.club_card_description_constraintlayout)
            val descriptionTitle = view.findViewById<TextView>(R.id.cc_description_title)
            val descriptionTime = view.findViewById<TextView>(R.id.cc_description_time)
            val descriptionAbilities = view.findViewById<TextView>(R.id.cc_description_abilities)
            val descriptionFreezing = view.findViewById<TextView>(R.id.cc_description_freezing)
            val descriptionInductionTrainings = view.findViewById<TextView>(R.id.cc_description_induction_trainings)
            val descriptionGuestVisits = view.findViewById<TextView>(R.id.cc_description_guestvisits)
            val descriptionProgressBar = view.findViewById<ProgressBar>(R.id.cc_description_progressbar)
            val descriptionMonths = view.findViewById<TextView>(R.id.cc_description_months)


            descriptionTitle.text = item.title
            descriptionTime.text = item.time
            descriptionAbilities.text = item.abilities
            descriptionFreezing.text = item.freezing
            descriptionInductionTrainings.text = item.inductionTrainings
            descriptionGuestVisits.text = item.guestVisits

        }
        val cardsCategories = view.findViewById<TextView>(R.id.cards_categories_textview)
        val initialHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 170.toFloat(), resources.displayMetrics).toInt()
        val constraintLayout = view.findViewById<ConstraintLayout>(R.id.card_prices_constraintlayout)
        var isExpanded = false
        cardsCategories.setOnClickListener{
            val targetHeight = if (isExpanded) initialHeight else 80
            isExpanded = !isExpanded
            ClubCardPricesAdapter(items) { item, cardImage, cardName ->
//
            }.toggle()
            val dpValue = 160f
            val density = resources.displayMetrics.density
            val pxValue = dpValue * density
            val floatPxValue = pxValue.toFloat()
            for (i in 0 until items.size) {
                if (isExpanded) {
                    val viewHolder =
                        clubCardsPricesRecyclerView.findViewHolderForAdapterPosition(i) as? ClubCardPricesAdapter.ViewHolder
                    val anim = ValueAnimator.ofFloat(viewHolder?.itemView?.translationY ?: 0f, -1f * i)
                    anim.addUpdateListener { valueAnimator ->
                        val animatedValue = valueAnimator.animatedValue as Float
                        viewHolder?.itemView?.translationY = animatedValue
                    }
                    anim.duration = 1000
                    anim.start()
                } else {
                    val viewHolder =
                        clubCardsPricesRecyclerView.findViewHolderForAdapterPosition(i) as? ClubCardPricesAdapter.ViewHolder
                    val anim = ValueAnimator.ofFloat(viewHolder?.itemView?.translationY ?: 0f, -floatPxValue * i)
                    anim.addUpdateListener { valueAnimator ->
                        val animatedValue = valueAnimator.animatedValue as Float
                        viewHolder?.itemView?.translationY = animatedValue
                    }
                    anim.duration = 1000
                    anim.start()
                }
            }


            val anim = ValueAnimator.ofInt(cardsCategories.height, targetHeight)
            anim.addUpdateListener { valueAnimator ->
                val value = valueAnimator.animatedValue as Int
                cardsCategories.layoutParams.height = value
                cardsCategories.requestLayout()
            }
            anim.duration = 1000
            anim.start()

        }
        val ktpConstraintLayout = view.findViewById<ConstraintLayout>(R.id.know_the_prices_constraintlayout)
        val ktpTextView = view.findViewById<TextView>(R.id.know_the_prices_textview)
        val ktpButton = view.findViewById<TextView>(R.id.know_the_prices_button)
        val ktpEnterName = view.findViewById<EditText>(R.id.card_prices_entername)
        val ktpEnterPhone = view.findViewById<EditText>(R.id.card_prices_enterphonenumber)
        val ktpError = view.findViewById<TextView>(R.id.card_prices_error)
        var ktpIsExpanded = false
        val db = FirebaseFirestore.getInstance()
        val priceListRef = db.collection("priceList")

        ktpConstraintLayout.setOnClickListener {
            ktpIsExpanded = !ktpIsExpanded
            if (ktpIsExpanded) {
                ktpTextView.visibility = View.GONE
                ktpButton.visibility = View.VISIBLE
                ktpEnterName.visibility = View.VISIBLE
                ktpEnterPhone.visibility = View.VISIBLE
                ktpError.visibility = View.INVISIBLE
                val anim = ValueAnimator.ofInt(
                    ktpConstraintLayout.measuredHeight,
                    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 160.toFloat(), resources.displayMetrics).toInt()
                )
                anim.addUpdateListener { valueAnimator ->
                    val value = valueAnimator.animatedValue as Int
                    val layoutParams: ViewGroup.LayoutParams = ktpConstraintLayout.layoutParams
                    layoutParams.height = value
                    ktpConstraintLayout.layoutParams = layoutParams
                }
                anim.duration = 1000
                anim.start()
            } else {
                ktpTextView.visibility = View.VISIBLE
                ktpButton.visibility = View.GONE
                ktpEnterName.visibility = View.GONE
                ktpEnterPhone.visibility = View.GONE
                ktpError.visibility = View.GONE
                val anim = ValueAnimator.ofInt(
                    ktpConstraintLayout.measuredHeight,
                    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30.toFloat(), resources.displayMetrics).toInt()
                )
                anim.addUpdateListener { valueAnimator ->
                    val value = valueAnimator.animatedValue as Int
                    val layoutParams: ViewGroup.LayoutParams = ktpConstraintLayout.layoutParams
                    layoutParams.height = value
                    ktpConstraintLayout.layoutParams = layoutParams
                }
                anim.duration = 1000
                anim.start()
            }

        }
        val descriptionCloseButton = view.findViewById<ImageButton>(R.id.cc_description_closebutton)
        descriptionCloseButton?.setOnClickListener {
            val constraintLayout = view.findViewById<ConstraintLayout>(R.id.club_card_description_constraintlayout)
            val constraintSet = ConstraintSet()
            val layout = view.findViewById<ConstraintLayout>(R.id.card_prices_constraintlayout)
            constraintSet.clone(layout)
            constraintSet.connect(constraintLayout.id, ConstraintSet.TOP, ClubCardsPricesFragment().id, ConstraintSet.BOTTOM)
            constraintSet.applyTo(layout)
        }

        ktpButton.setOnClickListener {
            val name = ktpEnterName.text.toString()
            val phoneNumber = ktpEnterPhone.text.toString()

            val data = hashMapOf(
                "name" to name,
                "phoneNumber" to phoneNumber
            )
            if (ktpEnterName.text.isNotEmpty() && ktpEnterPhone.text.isNotEmpty()) {
                priceListRef.add(data)
                    .addOnSuccessListener { documentReference ->
                        Toast.makeText(getActivity(),"Заявка отправлена успешно",Toast.LENGTH_LONG).show()
                        ktpTextView.visibility = View.VISIBLE
                        ktpButton.visibility = View.GONE
                        ktpEnterName.visibility = View.GONE
                        ktpEnterPhone.visibility = View.GONE
                        ktpError.visibility = View.GONE
                    }
                    .addOnFailureListener { e ->
                        ktpError.text = "Ошибка отправки"
                        ktpError.visibility = View.VISIBLE
                    }
            }
            else {
                ktpError.text = "Заполните все поля"
                ktpError.visibility = View.VISIBLE
            }
        }

    }

    companion object {
        fun newInstance() = ClubCardsPricesFragment()
    }
}

class ClubCardPricesAdapter(private val items: List<ClubCardPrices>, private val listener: (ClubCardPrices, ImageView, TextView) -> Unit) : RecyclerView.Adapter<ClubCardPricesAdapter.ViewHolder>() {

    private var isExpanded = false

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.card_type_element, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = items[position]
        holder.bind(item, listener)
        val layoutParams = holder.itemView.layoutParams as RecyclerView.LayoutParams
        holder.itemView.layoutParams = layoutParams
        val dpValue = 160f
        val density = holder.itemView.resources.displayMetrics.density
        val pxValue = dpValue * density
        val floatPxValue = pxValue.toFloat()

        if (isExpanded) {
            holder.itemView.translationY = 0f
            val animation = TranslateAnimation(0f, 0f, holder.itemView.translationY, 0f)
            animation.duration = 1000
            holder.itemView.startAnimation(animation)
            holder.bind(item, listener)
        } else {
            holder.itemView.translationY = -position*floatPxValue
            val animation = TranslateAnimation(0f, 0f, holder.itemView.translationY, 0f)
            animation.duration = 1000
            holder.itemView.startAnimation(animation)
            holder.bind(item, listener)
        }
    }

    fun toggle() {
        isExpanded = !isExpanded
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return items.size
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(item: ClubCardPrices, listener: (ClubCardPrices, ImageView, TextView) -> Unit) = with(itemView) {
            val cardImage = findViewById<ImageView>(R.id.card_type_image)
            val cardName = findViewById<TextView>(R.id.card_type_name)
            val cardPersonsAmount = findViewById<TextView>(R.id.card_type_personamount)
            val cardTerm = findViewById<TextView>(R.id.card_type_term)
            val cardLayout = findViewById<LinearLayout>(R.id.card_type_linearlayout)
            cardImage?.let{
                it.setImageResource(item.image)
            }
            cardName?.let{
                it.text = item.title
            }
            cardPersonsAmount?.let{
                it.text = item.personosAmount
            }
            cardTerm?.let{
                it.text = item.term
            }

            setOnClickListener {
                val constraintLayout = itemView.findViewById<ConstraintLayout>(R.id.club_card_description_constraintlayout)
                val ccTextView = itemView.findViewById<TextView>(R.id.cards_categories_textview)
                val constraintSet = ConstraintSet()
                val layout = itemView.findViewById<ConstraintLayout>(R.id.card_prices_constraintlayout)
                constraintSet.clone(layout)
                constraintSet.connect(constraintLayout.id, ConstraintSet.TOP, ccTextView.id, ConstraintSet.BOTTOM, 100)
                constraintSet.applyTo(layout)
                listener(item, cardImage, cardName)
            }
        }
    }
}

data class ClubCardPrices(val image: Int, val title: String, val personosAmount: String, val term: String, val time: String, val abilities: String, val freezing: String, val inductionTrainings: String, val guestVisits: String) : Serializable

An error occurs in the SetOnSlickListener when clicking on an item from a RecyclerView. I did exactly the same implementation of setting Constraints while clicking on the ImageButton and everything works, but when clicking on the element, a fatal error appears. I also tried to implement it via getChild(), but that didn't help either. What could be wrong?

1 Answers1

-1

You should post the actual stacktrace (the error message and the lines after it describing the calls that led to the error) - that's a lot of code to look through and guess where the problem is. If I had to guess though, you're getting it here:

setOnClickListener {
    ...
    val constraintSet = ConstraintSet()
    val layout = itemView.findViewById<ConstraintLayout>(R.id.card_prices_constraintlayout)
    constraintSet.clone(layout)

since that last method call invokes getChildCount on the layout you provide:

public void clone(ConstraintLayout constraintLayout) {
    int count = constraintLayout.getChildCount();

(I had to go look up the source code for ConstraintSet to confirm this - that's why posting the stacktrace always helps!)

So if that's where you're getting the error, your problem is that your layout (called constraintLayout in that method) is null, and you can't call getChildCount() on null. That means your findViewById lookup failed, and you got null as a result. Are you sure card_type_element.xml has a ConstraintLayout with an ID of card_prices_constraintlayout?

cactustictacs
  • 17,935
  • 2
  • 14
  • 25