Kotlin:如何在android studio中用新片段替换已经打开的片段?

我只是学习在android studio中使用片段。 我试图用PickPowerFragement片段替换一个MainFragment片段,但是当我按下MainFragment中的按钮来替换MainPragment与PickPowerFragment应用程序崩溃。 我能够成功地加载在教程中给出的java中的PickPowerFragment,但是当我在Kotlin中尝试这样做时,应用程序崩溃(仅用于练习)。 那么如何使用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) { } } 

这里我从MainFragment调用函数loadPickPowerScreen()

我测试如果按钮(我用一个按钮来替换MainFragment pickPowerFragment)正确或不正确的使用它来修改其上的文本,当按钮被点击,它似乎工作得很好。所以我猜应该不应该与MainFragment.kt有任何问题

这里是MainFragment.kt的onClick()方法

 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 Android项目的 Git仓库链接:HeroMe

请在投票前提出意见,我会尽我所能让我的帖子更好。 作为StackOverflow的初学者,声誉对我很重要。 所以请写评论好坏,它会帮助我。谢谢

你不能像这样实例化Activity,并调用类方法…(没有办法在Java中工作)

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

首先将方法loadPickPowerScreen()添加到MainFragment.OnMainFragmentInteractionListener ,然后调用
var onClick = View.OnClickListener(){view -> mListener.loadPickPowerScreen() }
我假设MainFragmentonAttachonDetach

这个链接是你在找什么,请尝试按照一些编码指南:)

编辑

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() } } 

上面的方法可以用来替换和添加片段到自定义片段堆栈和片段管理器

经过两天的挖掘,我终于找到了解决问题的办法。 在将Java转换为Kotlin导致崩溃时,我在onClick方法中发生了一个错误。

代替 :

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

代码应该是:

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

感谢所有试图帮助我的人。