1

I am adding some EditText views programmatically to a LinearLayout and for some reason I am not able to adjust the width of these EditText views. the goal I am trying to accomplish is have all the EditText views be of the same width, and that width is determined by whichever EditText ends up being the widest since they are using the WRAP_CONTENT option. Originally, I couldn't get the maxWidth to update at all, then I read about the viewObserverTree solution you can see in the middle of my function below. The Toast just outside of the if (maxWidth < viewWidth) block shows the correct amount for each of the views, but at the bottom where the for loop is supposed to be iterating through the children contained in a LinearLayout, it reads maxWidth as 0 and ends up looking weird since the views get squished to a width of 0. I am not sure why this is occuring and what to do about it. Below is the function:

    private fun createTimerFields(v : View, timeUnit : String) {
    if (v.findViewById<LinearLayout>(R.id.timer_fields) != null) {
        timerContainer.removeView(v.findViewById<LinearLayout>(R.id.timer_fields))
    }
    var maxWidth = 0
    val timeUnitsArray = ArrayList(listOf(*resources.getStringArray(R.array.time_units)))
    val timerFieldsLayout = LinearLayout(requireContext())
    val linearLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)

    timerFieldsLayout.layoutParams = linearLayoutParams
    timerFieldsLayout.orientation = LinearLayout.HORIZONTAL
    timerFieldsLayout.id = R.id.timer_fields

    for (unit in 0..timeUnitsArray.indexOf(timeUnit)) {
        val timeUnitEditText = EditText(requireContext())
        timeUnitEditText.layoutParams = linearLayoutParams
        timeUnitEditText.hint = "${timeUnitsArray[unit][0]}${timeUnitsArray[unit][0]}"
        val mVTO: ViewTreeObserver = timerFieldsLayout.viewTreeObserver
        mVTO.addOnGlobalLayoutListener {
            if (timeUnitEditText != null) {
                val viewWidth: Int = timeUnitEditText.width
                if (maxWidth < viewWidth) {
                    maxWidth = viewWidth
                }
                Toast.makeText(requireContext(), maxWidth.toString(), Toast.LENGTH_SHORT).show()
                //    any operation based on viewWidth is to be done here
            }
        }

        if (unit == 0) {
            var spacePadding = Space(requireContext())
            spacePadding.layoutParams = LinearLayout.LayoutParams(
                utils.convertDpsToPixels(requireContext(), 15F),
                LinearLayout.LayoutParams.MATCH_PARENT)
            timerContainer.addView(spacePadding, 0)
        }
        timerFieldsLayout.addView(timeUnitEditText, 0)
        //Toast.makeText(requireContext(), timeUnitEditText.width.toString(), Toast.LENGTH_SHORT).show()
    }
    timerContainer.addView(timerFieldsLayout, 0)
    for (child in 0 until timerFieldsLayout.childCount - 1) {
        var currentView = timerFieldsLayout.getChildAt(child)
        if (currentView.javaClass.simpleName == "EditText" ) {
            (currentView as EditText).width = maxWidth
            Toast.makeText(requireContext(), (currentView as EditText).width.toString(), Toast.LENGTH_SHORT).show()
        }
    }
}

Just so the tree of how I am trying to add things is clear, it goes like this:

LinearLayout for row

LinearLayout for inflated timer view

LinearLayout for timer view contents (needed for a Space view beneath the contents)

LinearLayout for the dynamically added fields of the timer

LinearLayout containing the fields

Space view followed by dynamically added EditText views detailed in above function

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

0 Answers0