Recyclerview Item onclick overlays the next fragment instead of replacing it

六月ゝ 毕业季﹏ 提交于 2020-01-25 06:43:30

问题


I have these activity, fragments, its viewmodels, and their adapter. I can already call the next fragment on click of a recyclerview item, but the new fragment overlays on the first fragment.

Refer to screenshot below: Next screenshot is the old fragment view:

As for the mainactivity:

class MainActivity : AppCompatActivity(), RecyclerViewClickListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navView: BottomNavigationView = findViewById(R.id.nav_view)

        val navController = findNavController(R.id.nav_host_fragment)
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        val appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.navigation_home,
                R.id.navigation_messages,
                R.id.navigation_notifications,
                R.id.navigation_account
            )
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)

        if (savedInstanceState == null) {
            supportFragmentManager
                .beginTransaction()
                .add(R.id.fragment_home, HomeFragment.newInstance(), "dormList")
                .commit()
        }
    }

    override fun onRecyclerViewItemClick(view: View, dorms: Dorms) {
        val detailsFragment = dormDetailsFragment.newInstance(dorms)
        supportFragmentManager
            .beginTransaction()
            .replace(R.id.fragment_home, detailsFragment, "Dorm Details")
            .addToBackStack(null)
            .commit()
    }
}

HomeFragment:

class HomeFragment : Fragment(), RecyclerViewClickListener {

    private lateinit var factory: HomeViewModelFactory
    private lateinit var viewModel: HomeViewModel
    private var callback : RecyclerViewClickListener? = null

    companion object {
        fun newInstance(): HomeFragment {
            return HomeFragment()
        }
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)

        if(context is RecyclerViewClickListener) callback = context
        else throw ClassCastException("$context must implement Callback")
    }

    override fun onDetach() {
        super.onDetach()
        callback = null
    }

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

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        val api = DormsAPI()
        val repository = DormRepository(api)

        factory = HomeViewModelFactory(repository)
        viewModel = ViewModelProviders.of(this, factory).get(HomeViewModel::class.java)

        viewModel.getDorms()

        viewModel.dorms.observe(viewLifecycleOwner, Observer { dorms ->
            recyclerViewDorms.also{
                it.layoutManager = LinearLayoutManager(requireContext())
                it.setHasFixedSize(true)
                it.adapter = dormAdapter(dorms, this)
            }
        })
    }

    override fun onRecyclerViewItemClick(view: View, dorms: Dorms) {
        when(view.id){
            R.id.button_reserve -> {
                // TODO: Go to new account if not signed up, etc...
                Toast.makeText(requireContext(), "Reserve button clicked", Toast.LENGTH_LONG).show()
            }
            R.id.layoutBox -> {
                // TODO: Go to Dorm Details
                callback?.onRecyclerViewItemClick(view, dorms)
            }
        }
    }
}

Home View Model

class HomeViewModel(private val repository: DormRepository) : ViewModel() {

    private lateinit var job: Job

    private val _dorms = MutableLiveData<List<Dorms>>()
    val dorms: LiveData<List<Dorms>>
        get() = _dorms

    fun getDorms() {
        job = Coroutines.ioThenMain(
            { repository.getDorms() },
            { _dorms.value = it }
        )
    }

    override fun onCleared() {
        super.onCleared()
        if(::job.isInitialized) job.cancel()
    }
}

Interface:

interface RecyclerViewClickListener {
    fun onRecyclerViewItemClick(view: View, dorms: Dorms)
}

Details Fragment:

class dormDetailsFragment : Fragment() {

    companion object {

        private const val DORMS = "model"
        fun newInstance(dorms: Dorms): dormDetailsFragment{
            val args = Bundle()
            args.putSerializable(DORMS, dorms)
            val fragment = dormDetailsFragment()
            fragment.arguments = args
            return fragment
        }
    }

    private lateinit var viewModel: DormDetailsViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val fragmentDormDetailsBinding =
            FragmentDormDetailsBinding.inflate(inflater,container,false)

        val model = arguments!!.getSerializable(DORMS) as Dorms
        fragmentDormDetailsBinding.dormDetails = model

        return fragmentDormDetailsBinding.root
    }
}

Home Fragment Layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
    android:id="@+id/fragment_home">

    <TextView
        android:id="@+id/text_home"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:textAlignment="center"
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/refreshLayout">

        <androidx.recyclerview.widget.RecyclerView
            tools:listitem="@layout/layout_home"
            android:id="@+id/recyclerViewDorms"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Details Layout

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <import type="android.view.View" />
        <variable
            name="dormDetails"
            type="com.pptt.roomy.data.models.Dorms" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.pptt.roomy.ui.home.dormDetails.DormDetailsFragment"
        android:id="@+id/DormDetailsFrag">

        <ImageView
            app:image="@{dormDetails.image}"
            android:id="@+id/image"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintDimensionRatio="1:1"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            android:background="@drawable/propertysample"
            />

        <TextView
            android:text="@{String.valueOf(dormDetails.dormPrice)}"
            tools:text="Php 2500"
            android:id="@+id/textViewPrice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="6dp"
            android:layout_marginStart="10dp"
            android:textSize="20sp"
            android:textStyle="normal"
            android:textColor="#000000"
            app:layout_constraintTop_toBottomOf="@id/image"
            app:layout_constraintLeft_toLeftOf="parent" />

        <TextView
            android:text="@{dormDetails.dormName}"
            tools:text="Dorm ni Jupa"
            android:id="@+id/textViewPropertyName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="1dp"
            android:layout_marginStart="10dp"
            android:textSize="24sp"
            android:textStyle="bold"
            android:textColor="#000000"
            app:layout_constraintTop_toBottomOf="@id/textViewPrice"
            app:layout_constraintLeft_toLeftOf="parent" />

        <TextView
            android:text="@{dormDetails.dormType}"
            tools:text="1 BR with Dining and Kitchen"
            android:id="@+id/textViewRoomType"
            android:layout_below="@id/textViewPropertyName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="5dp"
            android:layout_marginLeft="40dp"
            android:textSize="16sp"
            app:layout_constraintTop_toBottomOf="@+id/textViewPropertyName"
            app:layout_constraintLeft_toLeftOf="parent"/>

        <TextView
            android:text="@{dormDetails.dormAddress}"
            android:id="@+id/textViewAddress"
            android:layout_marginBottom="5dp"
            tools:text="455 San Jose II St., Brgy. 425, Sampaloc, Manila"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
            android:padding="5dp"
            android:layout_marginLeft="40dp"
            android:layout_width="wrap_content"
            android:textAlignment="center"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@+id/textViewRoomType"
            app:layout_constraintLeft_toLeftOf="parent"/>

        <TextView
            android:text="@{dormDetails.dormDetails}"
            android:id="@+id/textViewDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            tools:text="A very long textarea to contain dorm description. Should be multiline"
            android:padding="5dp"
            android:layout_marginLeft="20dp"
            app:layout_constraintTop_toBottomOf="@id/textViewAddress"
            app:layout_constraintLeft_toLeftOf="parent"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Anything else that's needed will be edited for later.


回答1:


Remove these lines:

if (savedInstanceState == null) {
    supportFragmentManager
        .beginTransaction()
        .add(R.id.fragment_home, HomeFragment.newInstance(), "dormList")
        .commit()
}

You're adding one HomeFragment via the NavHostFragment and another manually. You don't need to manually add Fragment when using Navigation.

You should also be updating your onRecyclerViewItemClick to use navigate() as per the Navigate to a destination documentation:

override fun onRecyclerViewItemClick(view: View, dorms: Dorms) {
    val navController = findNavController(R.id.nav_host_fragment)
    // If you're using Safe Args, use the ID generated from
    // the navigation graph and make sure you have
    // an argument of the correct type
    navController.navigate(
        HomeFragmentDirections.actionHomeToDetails(dorms))
}

You might find it helpful to look at the Pass data between destinations documentation to see how to create an <argument> in your graph for your Dorms object and how to set up Safe Args to generate the Directions class for you.



来源:https://stackoverflow.com/questions/59816157/recyclerview-item-onclick-overlays-the-next-fragment-instead-of-replacing-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!