Android Kotlin:点击按钮实现Fragment间跳转的问题求助
解决Android Fragment跳转与点击事件的错误问题
我是移动应用开发新手,使用Android Studio Dolphin | 2021.3.1 Patch 1,用Kotlin开发应用。需要实现两个功能:
- 点击
fragment_delivery中ID为button_customer_sign的按钮,打开fragment_sign - 用户完成签名后,点击
fragment_sign中ID为button_load_sign的按钮,返回fragment_delivery
当前代码存在导入错误、点击事件逻辑错误以及Fragment跳转逻辑错误,需要修正。
我的build.gradle依赖配置
dependencies { implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.annotation:annotation:1.5.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3' implementation 'androidx.navigation:navigation-ui-ktx:2.5.3' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.kyanogen.signatureview:signature-view:1.2' implementation 'androidx.fragment:fragment-ktx:1.6.0-alpha03' implementation 'androidx.fragment:fragment:1.6.0-alpha03' debugImplementation 'androidx.fragment:fragment-testing:1.6.0-alpha03' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' // google support library --------------------------------------------------------------------- implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.vectordrawable:vectordrawable:1.1.0' implementation 'androidx.browser:browser:1.4.0' }
当前错误的DeliveryFragment.kt代码
import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.TextView import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.example.delivery.R import com.example.delivery.databinding.FragmentDeliveryBinding import com.example.delivery.ui.sign.Sign import android.support.v4.app.Fragment // 错误:旧support库导入,与androidx冲突 import android.support.v4.app.FragmentManager // 错误:同上 import android.support.v4.app.FragmentTransaction // 错误:同上 class DeliveryFragment : Fragment() { private var _binding: FragmentDeliveryBinding? = null private var customerSign: Button? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val deliveryViewModel = ViewModelProvider(this).get(DeliveryViewModel::class.java) _binding = FragmentDeliveryBinding.inflate(inflater, container, false) val root: View = binding.root val customer = resources.getStringArray(R.array.customer_list) val arrayAdapter = ArrayAdapter(requireContext(), R.layout.dropdown_item, customer) binding.autoCompleteTextView.setAdapter(arrayAdapter) return root } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContectView(com.example.delivery.R.layout.content_main) // 错误:Fragment没有setContentView方法 customerSign = findViewById(com.example.delivery.R.id.button_customer_sign) as Button // 错误:onCreate阶段视图未初始化,findViewById会返回null customerSign.setOnClickListener(View.OnClickListener { openSignFragment() }) } fun openSignFragment() { val intent = Intent(this, SignFragment::class.java) // 错误:Intent用于Activity跳转,Fragment跳转不能用Intent startActivity(intent) } override fun onDestroyView() { super.onDestroyView() _binding = null } }
修正步骤与完整代码
1. 修复导入错误
删除所有android.support.v4.app.*的导入,项目使用AndroidX库,对应的核心导入androidx.fragment.app.Fragment已经存在,无需额外导入FragmentManager和FragmentTransaction。
2. 修复点击事件逻辑
Fragment的视图初始化完成在onCreateView之后,应在onViewCreated方法中设置按钮点击监听,利用ViewBinding直接获取按钮实例,避免空指针。
3. 修复Fragment跳转逻辑
推荐使用已添加依赖的Navigation组件实现跳转(官方推荐方案),也可以用FragmentManager手动跳转,以下是两种方案:
方案一:使用Navigation组件跳转
修正后的DeliveryFragment.kt
import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import com.example.delivery.R import com.example.delivery.databinding.FragmentDeliveryBinding class DeliveryFragment : Fragment() { private var _binding: FragmentDeliveryBinding? = null private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val deliveryViewModel = ViewModelProvider(this).get(DeliveryViewModel::class.java) _binding = FragmentDeliveryBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 设置下拉列表 val customer = resources.getStringArray(R.array.customer_list) val arrayAdapter = ArrayAdapter(requireContext(), R.layout.dropdown_item, customer) binding.autoCompleteTextView.setAdapter(arrayAdapter) // 设置签名按钮点击事件,跳转到SignFragment binding.buttonCustomerSign.setOnClickListener { // 替换R.id.action_deliveryFragment_to_signFragment为你导航图中对应的action ID findNavController().navigate(R.id.action_deliveryFragment_to_signFragment) } } override fun onDestroyView() { super.onDestroyView() _binding = null } }
SignFragment中返回按钮逻辑
import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import com.example.delivery.databinding.FragmentSignBinding class SignFragment : Fragment() { private var _binding: FragmentSignBinding? = null private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentSignBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 设置返回按钮点击事件 binding.buttonLoadSign.setOnClickListener { // 返回上一个Fragment findNavController().popBackStack() } } override fun onDestroyView() { super.onDestroyView() _binding = null } }
方案二:使用FragmentManager手动跳转
修正后的DeliveryFragment.kt
import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter import androidx.fragment.app.Fragment import androidx.fragment.app.commit import androidx.lifecycle.ViewModelProvider import com.example.delivery.R import com.example.delivery.databinding.FragmentDeliveryBinding import com.example.delivery.ui.sign.SignFragment class DeliveryFragment : Fragment() { private var _binding: FragmentDeliveryBinding? = null private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val deliveryViewModel = ViewModelProvider(this).get(DeliveryViewModel::class.java) _binding = FragmentDeliveryBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 设置下拉列表 val customer = resources.getStringArray(R.array.customer_list) val arrayAdapter = ArrayAdapter(requireContext(), R.layout.dropdown_item, customer) binding.autoCompleteTextView.setAdapter(arrayAdapter) // 设置签名按钮点击事件,跳转到SignFragment binding.buttonCustomerSign.setOnClickListener { parentFragmentManager.commit { replace(R.id.fragment_container, SignFragment()) // 替换R.id.fragment_container为你的Fragment容器ID addToBackStack(null) // 添加到返回栈,支持返回 } } } override fun onDestroyView() { super.onDestroyView() _binding = null } }
SignFragment中返回按钮逻辑
import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import com.example.delivery.databinding.FragmentSignBinding class SignFragment : Fragment() { private var _binding: FragmentSignBinding? = null private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentSignBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 设置返回按钮点击事件 binding.buttonLoadSign.setOnClickListener { parentFragmentManager.popBackStack() // 从返回栈弹出,回到DeliveryFragment } } override fun onDestroyView() { super.onDestroyView() _binding = null } }
内容的提问来源于stack exchange,提问作者DevNoob
相关产品推荐
相关产品推荐

