При нажатии кнопки Spinner происходит расширение в раскрывающемся режиме, но она работает в диалоговом режиме (только в API <26) - PullRequest
0 голосов
/ 20 декабря 2018

У меня проблема с моим Spinner в Android.

Вылетает при щелчке по расширению.Это происходит только тогда, когда он находится в режиме Dropdown (режим Dialog работает нормально) и когда приложение работает на устройстве с API ниже 26. Вращатель используется во всплывающем окне, которое открывается внутри фрагмента.

Я получаю это исключение:

android.view.WindowManager $ BadTokenException: невозможно добавить окно - токен android.view.ViewRootImpl$W@4dc3e2a недопустим;ваша деятельность выполняется?

Я уже проверил, является ли контекст в моем всплывающем окне нулевым, но это не так.

Вот мой код всплывающего окна:

 private fun entryFunction(toChangeEntry: Entry?) {

    val view = inflater.inflate(R.layout.add_entry_popup, calendarLayout, false)

    val popupWindow = PopupWindow(
        view, ConstraintLayout.LayoutParams.MATCH_PARENT,
        ConstraintLayout.LayoutParams.WRAP_CONTENT, true
    )

    popupWindow.elevation = 10.0F

    val slideIn = Slide()
    slideIn.slideEdge = Gravity.START
    popupWindow.enterTransition = slideIn

    val slideOut = Slide()
    slideOut.slideEdge = Gravity.END
    popupWindow.exitTransition = slideOut

    val et = view.findViewById<EditText>(R.id.mahlzeitEditText)
    val cancelBtn = view.findViewById<Button>(R.id.cancelButton)
    val okBtn = view.findViewById<Button>(R.id.okButton)
    val rb = view.findViewById<RatingBar>(R.id.ratingBar)
    val deleteBtn = view.findViewById<ImageButton>(R.id.deleteButton)

    val spinner = view.findViewById<Spinner>(R.id.mealtype_spinner)

    //Fehler wegen dropdown spinner (dialog funktioniert)

    ArrayAdapter.createFromResource(
        view.context,
        R.array.mealtypeStringArray, android.R.layout.simple_spinner_dropdown_item
    ).also { spinnerAdapter ->
        spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
        spinner.adapter = spinnerAdapter
    }

    val day = view.findViewById<EditText>(R.id.dayEditText)
    val month = view.findViewById<EditText>(R.id.monthEditText)
    val year = view.findViewById<EditText>(R.id.yearEditText)

    val cal = Calendar.getInstance()

    if (toChangeEntry != null) {
        et.setText(toChangeEntry.meal)
        rb.rating = toChangeEntry.rating.toFloat()
        spinner.setSelection(toChangeEntry.mealType)
        cal.timeInMillis = toChangeEntry.date

        deleteBtn.setOnClickListener { deleteEntry(toChangeEntry, popupWindow) }
    } else deleteBtn.visibility = View.GONE

    day.setText(dayFormatter.format(cal.time))
    month.setText(monthFormatter.format(cal.time))
    year.setText(yearFormatter.format(cal.time))

    val clickListener = View.OnClickListener {
        cal.clear()

        if (day.text.toString().toInt() <= 31 && month.text.toString().toInt() <= 12) {
            cal[Calendar.DAY_OF_MONTH] = day.text.toString().toInt()
            cal[Calendar.MONTH] = month.text.toString().toInt() - 1
            cal[Calendar.YEAR] = year.text.toString().toInt()

            if (toChangeEntry != null) editEntry(
                toChangeEntry, cal.timeInMillis,
                et.text.toString(), rb.rating.toInt(), spinner.selectedItemPosition, popupWindow)
            else createEntry(
                cal.timeInMillis, et.text.toString(),
                rb.rating.toInt(), spinner.selectedItemPosition, popupWindow)
        } else if (view != null) Toast.makeText(view.context, R.string.checkDate, Toast.LENGTH_LONG).show()
    }

    val editorListener = TextView.OnEditorActionListener { _, actionID, _ ->
        if (actionID == EditorInfo.IME_ACTION_DONE) {
            cal.clear()

            if (day.text.toString().toInt() <= 31 && month.text.toString().toInt() <= 12) {
                cal[Calendar.DAY_OF_MONTH] = day.text.toString().toInt()
                cal[Calendar.MONTH] = month.text.toString().toInt() - 1
                cal[Calendar.YEAR] = year.text.toString().toInt()

                if (toChangeEntry != null) editEntry(
                    toChangeEntry, cal.timeInMillis,
                    et.text.toString(), rb.rating.toInt(), spinner.selectedItemPosition, popupWindow)
                else createEntry(
                    cal.timeInMillis, et.text.toString(),
                    rb.rating.toInt(), spinner.selectedItemPosition, popupWindow)
            } else if (view != null) Toast.makeText(view.context, R.string.checkDate, Toast.LENGTH_LONG).show()

            true
        } else false
    }

    okBtn.setOnClickListener(clickListener)
    et.setOnEditorActionListener(editorListener)
    day.setOnEditorActionListener(editorListener)
    month.setOnEditorActionListener(editorListener)
    year.setOnEditorActionListener(editorListener)

    cancelBtn.setOnClickListener {
        popupWindow.dismiss()
    }

    day.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(text: Editable?) {
            if (text?.length == 2) {
                month.requestFocus()
                month.setSelection(month.length())
            }
        }

        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
    })

    month.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(text: Editable?) {
            if (text?.length == 2) {
                year.requestFocus()
                year.setSelection(year.length())
            }
        }

        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
    })

    TransitionManager.beginDelayedTransition(calendarLayout)
    popupWindow.showAtLocation(calendarLayout, Gravity.CENTER, 0, 0)

    et.requestFocus()
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY)

    popupWindow.setOnDismissListener {
        imm.hideSoftInputFromWindow(view.windowToken, 0)
    }
}

И вот фрагмент, в котором он используется:

class CalendarFragment : Fragment() , AdapterView.OnItemSelectedListener {

private lateinit var viewAdapter: RecyclerView.Adapter<*>
private lateinit var viewManager: RecyclerView.LayoutManager
private lateinit var inflater: LayoutInflater
private lateinit var imm: InputMethodManager
private lateinit var calendarLayout: ConstraintLayout
private lateinit var recycler: RecyclerView

private var entryList = ArrayList<Entry>()

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

    if (activity != null) {
        inflater = layoutInflater
        imm = activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        calendarLayout = view.findViewById(R.id.calendar_fragment_layout)
        recycler = view.findViewById(R.id.scrollCalendar)!!
        setUpAdapter()
}

Вот всплывающее окно xml:

android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="#a4aebf">

<RatingBar
        android:id="@+id/ratingBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:rating="3"
        android:stepSize="1"
        android:isIndicator="false"
        android:layout_marginStart="5dp"
        android:layout_marginTop="5dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/mahlzeitTextView"
        style="@android:style/Widget.Material.RatingBar.Indicator"
/>

<ImageButton
        android:id="@+id/deleteButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:layout_marginTop="10dp"
        android:src="@drawable/delete_icon"
        android:background="@android:color/transparent"
        android:contentDescription="@string/delete"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
/>

<TextView
        android:id="@+id/mahlzeitTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_marginStart="10dp"
        android:text="@string/foodNameRequest"
        app:layout_constraintTop_toBottomOf="@id/ratingBar"
        app:layout_constraintStart_toStartOf="parent"
/>

<EditText
        android:id="@+id/mahlzeitEditText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:hint="@string/mahlzeit"
        android:inputType="textImeMultiLine"
        android:imeOptions="actionDone"
        app:layout_constraintTop_toBottomOf="@id/mahlzeitTextView"
        app:layout_constraintStart_toStartOf="@id/mahlzeitTextView"
        app:layout_constraintEnd_toEndOf="parent"
/>

<EditText
        android:id="@+id/dayEditText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:maxLength="2"
        android:inputType="number"
        android:hint="@string/two0"
        app:layout_constraintTop_toBottomOf="@id/mahlzeitEditText"
        app:layout_constraintStart_toStartOf="parent"
/>

<EditText
        android:id="@+id/monthEditText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLength="2"
        android:inputType="number"
        android:hint="@string/two0"
        app:layout_constraintTop_toBottomOf="@id/mahlzeitEditText"
        app:layout_constraintStart_toEndOf="@id/dayEditText"
/>

<Spinner
        android:id="@+id/mealtype_spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="10dp"
        android:spinnerMode="dropdown"
        android:gravity="end"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/mahlzeitEditText"
/>

<EditText
        android:id="@+id/yearEditText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLength="4"
        android:inputType="number"
        android:hint="@string/four0"
        app:layout_constraintTop_toBottomOf="@id/mahlzeitEditText"
        app:layout_constraintStart_toEndOf="@id/monthEditText"
/>

<Button
        android:id="@+id/cancelButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:text="@string/cancleButton"
        android:background="@android:color/transparent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/dayEditText"
/>

<Button
        android:id="@+id/okButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:text="@string/OK"
        android:background="@android:color/transparent"
        app:layout_constraintTop_toBottomOf="@id/dayEditText"
        app:layout_constraintEnd_toEndOf="parent"
/>

Я уже посмотрел на подобноепроблемы, но все еще не могли заставить его работать.

Обновление: Я попытался получить Windowtoken моего PopupWindow и распечатать его с помощью Log.d (), вызвав:

Log.d("debugLog", view.windowToken.toString())

Сбой этого приложения из-за этого вызова с NullPointerException:

java.lang.NullPointerException: попытка вызвать виртуальный метод 'java.lang.String java.lang.Object.toString() 'для пустой ссылки на объект

Я не знаю, связано ли это с моей проблемой, но я надеюсь, что это поможет.

1 Ответ

0 голосов
/ 24 декабря 2018

Очевидно, что во всплывающем окне не может быть Spinner с режимом вращения, установленным в раскрывающемся меню, если API ниже 26.

...