Kotlin: Как заменить уже открытый фрагмент на новый фрагмент в студии Android?

Я просто учась использовать фрагменты в студии Android. Я пытаюсь заменить фрагмент MainFragment фрагментом PickPowerFragement, но когда я нажимаю кнопку в MainFragment, чтобы заменить MainFragment с помощью PickPowerFragment, приложение аварийно завершает работу. Мне удалось успешно загрузить PickPowerFragment в java, как указано в учебнике, но приложение падает, когда я пытался это сделать в Котлине (только для практики). Итак, как я могу заменить фрагмент, используя синтаксис Kotlin

activity_hero_me.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.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" tools:context="com.example.mandar.herome.Activities.HeroMe" tools:layout_editor_absoluteX="0dp" tools:layout_editor_absoluteY="25dp"> <FrameLayout android:id="@+id/ReplaceFrame" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0"> </FrameLayout> </android.support.constraint.ConstraintLayout> 

HeroMe.kt

 package com.example.mandar.herome.Activities import android.app.Activity import android.app.Fragment import android.app.FragmentManager import android.net.Uri import android.os.Bundle import com.example.mandar.herome.Fragments.MainFragment import com.example.mandar.herome.Fragments.PickPowerFragment import com.example.mandar.herome.R class HeroMe : Activity() , MainFragment.OnMainFragmentInteractionListener , PickPowerFragment.pickPowerInteractionListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_hero_me) val manager : FragmentManager = fragmentManager var fragment : Fragment? = manager.findFragmentById(R.id.ReplaceFrame) if (fragment == null){ fragment = MainFragment() manager.beginTransaction().add(R.id.ReplaceFrame,fragment).commit() } } fun loadPickPowerScreen(){ var pickpowerfrag = PickPowerFragment() fragmentManager.beginTransaction().replace(R.id.ReplaceFrame, pickpowerfrag).addToBackStack(null).commit() } override fun onMainFragmentInteraction(uri: Uri) { } override fun onPickPowerInteraction(uri: Uri) { } } 

Здесь я вызываю функцию loadPickPowerScreen () из MainFragment

Я тестировал Если кнопка (кнопка, которую я использую для замены MainFragment с помощью pickPowerFragment) работает правильно или нет, используя ее для изменения текста на ней при нажатии кнопки, и кажется, что она работает нормально. Поэтому я думаю, что не должно быть любая проблема с MainFragment.kt

Вот метод onClick () из MainFragment.kt

 var onClick = View.OnClickListener(){view -> var heroActivity : HeroMe = HeroMe() heroActivity.loadPickPowerScreen() } 

и вот фрагмент PickPowerFragment.kt

 package com.example.mandar.herome.Fragments import android.app.Fragment import android.content.Context import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.example.mandar.herome.R /** * A simple [Fragment] subclass. * Activities that contain this fragment must implement the * [PickPowerFragment.OnFragmentInteractionListener] interface * to handle interaction events. * Use the [PickPowerFragment.newInstance] factory method to * create an instance of this fragment. */ class PickPowerFragment : Fragment() { // TODO: Rename and change types of parameters private var mParam1: String? = null private var mParam2: String? = null private var mListener: pickPowerInteractionListener? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (arguments != null) { mParam1 = arguments.getString(ARG_PARAM1) mParam2 = arguments.getString(ARG_PARAM2) } } override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater!!.inflate(R.layout.fragment_pick_power, container, false) // Inflate the layout for this fragment return view } // TODO: Rename method, update argument and hook method into UI event fun onButtonPressed(uri: Uri) { if (mListener != null) { mListener!!.onPickPowerInteraction(uri) } } override fun onAttach(context: Context?) { super.onAttach(context) if (context is pickPowerInteractionListener) { mListener = context } else { throw RuntimeException(context!!.toString() + " must implement OnFragmentInteractionListener") } } override fun onDetach() { super.onDetach() mListener = null } /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity and potentially other fragments contained in that * activity. * * * See the Android Training lesson [Communicating with Other Fragments](http://developer.android.com/training/basics/fragments/communicating.html) for more information. */ interface pickPowerInteractionListener { // TODO: Update argument type and name fun onPickPowerInteraction(uri: Uri) } companion object { // TODO: Rename parameter arguments, choose names that match // the fragment initialization parameters, eg ARG_ITEM_NUMBER private val ARG_PARAM1 = "param1" private val ARG_PARAM2 = "param2" /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @param param1 Parameter 1. * @param param2 Parameter 2. * @return A new instance of fragment PickPowerFragment. */ // TODO: Rename and change types and number of parameters fun newInstance(param1: String, param2: String): PickPowerFragment { val fragment = PickPowerFragment() val args = Bundle() args.putString(ARG_PARAM1, param1) args.putString(ARG_PARAM2, param2) fragment.arguments = args return fragment } } }// Required empty public constructor 

logcat после сбоя: Logcat после сбоя:

Информация, предоставленная отладчиком непосредственно перед сбоем: значения переменной отладчика непосредственно перед сбоем

Редактирование: здесь я добавляю ссылку Git Repository для проекта Git Android Project: HeroMe

Прошу прокомментировать предложение до начала опроса. Я сделаю все возможное, чтобы улучшить мои сообщения. Как новичок в StackOverflow, репутация важна для меня. Поэтому, пожалуйста, напишите комментарий хорошо или плохо, это поможет мне. Спасибо

Вы не можете создать экземпляр Activity, как этот, и вызвать методы класса … (никоим образом не работал в java)

var heroActivity: HeroMe = HeroMe ()
heroActivity.loadPickPowerScreen ()

Сначала добавьте метод loadPickPowerScreen() в MainFragment.OnMainFragmentInteractionListener а затем просто вызовите
var onClick = View.OnClickListener(){view -> mListener.loadPickPowerScreen() }
Я предполагаю, что MainFragment похож на PickPowerFragment в отношении onAttach и onDetach

Эта ссылка – это то, что вы ищете, и, пожалуйста, попробуйте следовать руководству по кодированию 🙂

РЕДАКТИРОВАТЬ

В деятельности HeroMe у вас есть:

 override fun onMainFragmentInteraction(uri: Uri) { var pickpowerfrag = PickPowerFragment() fragmentManager.beginTransaction() .replace(R.id.ReplaceFrame, pickpowerfrag) .addToBackStack(null) .commit() } 

а затем в OnClickListener

 var onClick = View.OnClickListener(){view -> mListener?.onMainFragmentInteraction(someUri) } 
 fun replaceFragment(fragment: Fragment) { mFragmentStack = Stack() val transaction = mFragmentManager?.beginTransaction() transaction?.replace(R.id.layout_frame_content, fragment) (mFragmentStack as Stack<Fragment>).push(fragment) transaction?.commitAllowingStateLoss() } fun addFragment(fragment: Fragment) { if (mFragmentManager != null) { val transaction = (mFragmentManager as FragmentManager).beginTransaction() transaction.add(R.id.layout_frame_content, fragment) mFragmentStack?.lastElement()?.onPause() transaction.hide(mFragmentStack?.lastElement()) mFragmentStack?.push(fragment) transaction.commitAllowingStateLoss() } } 

Вышеуказанные методы могут использоваться для замены и добавления фрагментов в пользовательский стек стека и диспетчер фрагментов

Через 2 дня копания я наконец нашел решение для своей проблемы. Есть только одна ошибка, которую я сделал в методе onClick при преобразовании Java в Kotlin, что приводит к сбою.

Вместо :

 var onClick = View.OnClickListener(){view -> var heroActivity : HeroMe = HeroMe() heroActivity.loadPickPowerScreen() } 

Код должен был быть:

 var onClick = View.OnClickListener(){view -> var heroActivity : HeroMe= activity as HeroMe heroActivity.loadPickPowerScreen() } 

Спасибо всем, кто пытался мне помочь.

Intereting Posts
Можно ли добавить «статическую» функцию расширения для Java-класса? Как добавить приложение create-react-kotlin-app в качестве модуля для проекта kotlin-multiplatform? Нет активного администратора … – блокировка экрана в Android Как преобразовать Int в строку в Kotlin Как сортировать Kotlin MutableList <Int> Архитектура собственного SDK – API асинхронного метода в Котлине Связанная ссылка на вызов не работает с реактором Подписаться Использование hbm2ddl с двумя менеджерами сущностей в Hibernate почему work.map (запуск потока) .foreach (join ()) работает в kotlin? Избегайте приостановления другого приложения для аудиозаписей на YouTubePlayerFragment init Как получить все документы из коллекции Firestore в классе POJO? IncompatibleClassChangeError: класс 'java.lang.VirtualMachineError' не реализует интерфейс 'java.lang.CharSequence' AccessToken.getCurrentAccessToken () всегда возвращает null в Kotlin Объявить окончательное удовольствие в интерфейсе Являются ли столетние нитки Котлина безопасными?