I researched around 20 - 30 answers and still not found a working way to:
- get the image and text from --> view --> viewHolder --> recyclerview --> Fragment ( one image and one text fills 1 screen). ( NullPointerException)
- I need them as quote: String and imgRes: Int to input them in a viewModel DAO method to save them to favourites.
- Ideally if the user clicks the heart button, the present image + text goes in the favourites. If it is not possible, or overly complicated, then if the user clicks anywhere in the screen the image + text should go to favourites.
- In the adapter I need the context to get a random quote from the database (I understand that Context in Adapter is a big no-no) - can you recommend a cleaner way to do it?
- Please advise on how to implement the clicklistener so it gets the image and text! Thank you!
Adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.data.DataSource
import com.example.data.DataSource.prepareManualQuote
import com.example.databinding.SlidingItemBinding
class SlidingItemAdapter(context: Context) :
RecyclerView.Adapter<SlidingItemAdapter.SlidingItemViewHolder>() {
// does NOT WORK TO PASS CONTEXT HERE, NEITHER IN DATABASE, OR VIEWMODEL,
// but it is needed to get the drawable resources programatically
// that is why we pass a private constructor
private var imgList: MutableList<Int> = DataSource.getThemAll(context)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SlidingItemViewHolder {
val binding = SlidingItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return SlidingItemViewHolder(binding)
}
// the prepareManualQuote is still a random quote - but passed through Database this time,
// not viewmodel
override fun onBindViewHolder(holder: SlidingItemViewHolder, position: Int) {
// we take a random quote and a random image
val randomPos: Int = (imgList.indices).random()
val imgRes: Int = imgList[randomPos]
val manualQuote: String = prepareManualQuote(holder.itemView.context)
holder.binding.imageViewManual.setImageResource(imgRes)
holder.binding.quoteManual.setText(manualQuote)
}
class SlidingItemViewHolder(val binding: SlidingItemBinding):
RecyclerView.ViewHolder(binding.root)
override fun getItemCount(): Int {
return imgList.size
}
}
SlidingFragment
class SlidingPhotosFragment : Fragment() {
private var _bindingManual: FragmentManualSlidingRecyclerviewBinding? = null
private val bindingManual get() = _bindingManual!!
// Anything used in onCreate and OnviewCreated, etc - declare it here
lateinit var isAuto: String
/*** Standard implementation to work with databases */
private val viewModel: SpiritViewModel by activityViewModels {
SpiritViewModelFactory(
(requireActivity().application as ConnectRoomDatabaseApplication).roomDatabase.itemDao()
)
}
var randomPos: Int = 5
var quote: String = ""
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_bindingManual = FragmentManualSlidingRecyclerviewBinding.inflate(inflater, container,false)
return bindingManual.root
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bindingManual.lifecycleOwner = viewLifecycleOwner
// slidesrecyclerView is the binding name gave to recyclerview id in fragment_manual_sliding_recyclerview
bindingManual.slidesRecyclerview.adapter = context?.let { SlidingItemAdapter(it) }
// Extracting stuff from the recyclerview
val linearManager = LinearLayoutManager(context)
bindingManual.heartFavouriteButton.setOnClickListener {
val position: Int = linearManager.findFirstCompletelyVisibleItemPosition()
val row: View? = bindingManual.slidesRecyclerview.layoutManager!!.findViewByPosition(position)
val quoteManual: TextView = row!!.findViewById(R.id.quoteManual)
val imageViewManual: ImageView = row.findViewById(R.id.imageViewManual)
println("dra in manual sliders were extracted this quote and this imageViewId" + quoteManual.text + imageViewManual.getDrawable())
}
// Snap implementation
val pgSnaphelper: SnapHelper = PagerSnapHelper()
// By using a pagerSnap Helper the snap goes strictly to only 1 slide - not scrolling through many more
bindingManual.slidesRecyclerview.layoutManager?.let {
bindingManual.slidesRecyclerview.layoutManager!!.getChildAt(0)
?.let { it1 -> pgSnaphelper.calculateDistanceToFinalSnap(it, it1) }
}
pgSnaphelper.attachToRecyclerView(bindingManual.slidesRecyclerview)
}
}
XML fragment_manual_sliding_recyclerview
<?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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:navigationBarColor="@color/nav_icons_default"
tools:context=".ui.fragments.SlidingPhotosFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/slides_recyclerview"
android:clipToPadding="false"
android:layout_width="0dp"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/heartFavouriteButton"
style="@android:style/Widget.Holo.ImageButton"
android:layout_width="33dp"
android:layout_height="32dp"
android:layout_marginEnd="250dp"
android:adjustViewBounds="true"
android:background="@color/material_on_primary_disabled"
app:layout_constraintBottom_toTopOf="@+id/heartRedFavouriteButton"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_heart_svgrepo_com"
android:contentDescription="@string/save_slider_to_favourites" />
<ImageButton
android:id="@+id/heartRedFavouriteButton"
style="@android:style/Widget.Holo.ImageButton"
android:layout_width="33dp"
android:layout_height="32dp"
android:layout_marginEnd="250dp"
android:layout_marginBottom="100dp"
android:adjustViewBounds="true"
android:background="@color/material_on_primary_disabled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_heart_svgrepo_com2"/>
<!-- tools:visibility="visible" />-->
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<!-- tools:visibility="visible"-->