recyclerview not visible at run time - android

I implemented a simple recyclerview using databinding using kotlin language.
In xml, recyclerview seems to be the default,
but when I run it, it doesn't show up as default.
Other buttons and views included in the fragment appear normally when executed, but only the recyclerview is not visible. Which part is wrong?
class WorkFragment : Fragment() {
private var _binding: FragmentWorkBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentWorkBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val data = mutableListOf<WorkList>()
val adapter = WorkAdapter()
adapter.data = data
binding.recycler1.adapter = adapter
binding.recycler1.layoutManager = LinearLayoutManager(requireContext())
}
}
class WorkAdapter : RecyclerView.Adapter<WorkAdapter.ViewHolder>() {
var data = mutableListOf<WorkList>()
class ViewHolder(val binding: RecyclerviewWorkItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(workList: WorkList) {
binding.tvStarttime.text = workList.Starttime
binding.tvAdmin.text = workList.Admin
binding.tvPart.text = workList.Part
binding.tvStoptime.text = workList.Stoptime
binding.tvWorkers.text = workList.Workers.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WorkAdapter.ViewHolder {
val binding = RecyclerviewWorkItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: WorkAdapter.ViewHolder, position: Int) {
holder.bind(data[position])
}
override fun getItemCount(): Int {
return data.size
}
// fun replaceList(newList: MutableList<WorkList>) {
// data = newList.toMutableList()
// notifyDataSetChanged()
// }
}
Is there something wrong with my code?
For reference, I just used a fragment, not an activity.

its typically for the RecyclerView to behave like its hidden but actually its not. the reason is you are passing an empty list so the recycler will not be extended or show because there is no items in the list.

Related

How do I filter cards in a RecyclerView through a SearchView (Kotlin)?

I am currently working on a simple journal app where the user can make new entries, which get stored into a room database and displayed through a RecyclerView using cards. I am currently trying to implement a way to filter card entries based on the text within them using a SearchView. However, everything that I've found online seems to be entirely in Java, just filtering a list, etc, so I'm not sure how I would go about doing this. Any help would be massively appreciated!
Here is my code (without imports):
Fragment that displays entries through RecyclerView:
class HomeFragment : BaseFragment() {
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recycler_view.setHasFixedSize(true)
recycler_view.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
launch {
context?.let {
var journal = JournalDatabase.getDatabase(it).JournalDao().allJournal()
recycler_view.adapter = JournalAdapter(journal)
}
}
newEntryButton.setOnClickListener {
Navigation.findNavController(view).navigate(R.id.action_nav_home_to_nav_new_entry)
}
}
}
My adapter:
class JournalAdapter(val arrList: List<Journal>) :
RecyclerView.Adapter<JournalAdapter.JournalViewHolder>() {
class JournalViewHolder(view: View) : RecyclerView.ViewHolder(view) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JournalViewHolder {
return JournalViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_entry, parent, false))
}
override fun onBindViewHolder(holder: JournalViewHolder, position: Int) {
holder.itemView.rvTitle.text = arrList[position].title
holder.itemView.rvText.text = arrList[position].journalText
holder.itemView.rvDateTime.text = arrList[position].dateTime
}
override fun getItemCount(): Int {
return arrList.size
}
}

How to Read Data from RecyclerView and send in BottomSheet

I am using recyclerView to show list of apps installed in device
image - Link
and for more details I use bottomSheet on LongPress i.e. in ViewHolder Class, but How to send data of selected tab to bottomSheet with more details(such as package name, API level etc.)...for reference see images
I want - Link
I get from below coding - Link
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.adapter = Adapter // I set adapter here with function getApps()
recyclerView.layoutManager = LinearLayoutManager(this)
private fun getApps(): List<DataClass> {
// here I get apps icon,name,size and return list<DataClass>
return list
}
Adapter.kt
class Adapter(private val listOfApps: List<AppData>) :
RecyclerView.Adapter<Adapter.ViewHolder>() {
class ViewHolder(appView: View) : RecyclerView.ViewHolder(appView), View.OnClickListener,
View.OnLongClickListener {
init {
appView.setOnClickListener(this)
appView.setOnLongClickListener(this)
}
val icon: ImageView = appView.App_icon
val name: TextView = appView.App_name
val size: TextView = appView.App_size
override fun onClick(v: View?) {
Toast.makeText(v?.context, "OnClick", Toast.LENGTH_SHORT).show()
}
override fun onLongClick(v: View?): Boolean {
// I want here on Long press BottomSheet appears with details
val bottomSheetDialog = BottomSheetDialog()
// Show bottomSheet on LongPress
bottomSheetDialog.show(
(v?.context as FragmentActivity).supportFragmentManager, bottomSheetDialog.tag
)
return true
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(
R.layout.list_apps, parent, false
)
return ViewHolder(view)
}
override fun getItemCount() = listOfApps.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = listOfApps[position]
holder.icon.setImageDrawable(currentItem.icon)
holder.name.text = currentItem.name
holder.size.text = currentItem.size
}
}
BottomSheetDialog.kt
class BottomSheetDialog: BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.bottom_sheet, container, false)
}
override fun getTheme(): Int = R.style.RoundBottomSheetDialog
}
DataClass
data class AppData(
val icon: Drawable,
val name: String,
val size: String,
)
With your current code the easiest solution would be:
Modify your BottomSheetDialog to include AppData in the constructor
class BottomSheetDialog(val appData: AppData): BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.bottom_sheet, container, false)
}
override fun getTheme(): Int = R.style.RoundBottomSheetDialog
}
Add onBind method inside your ViewHolder class:
fun onBind(appData: AppData) {
icon.setImageDrawable(currentItem.icon)
name.text = currentItem.name
size.text = currentItem.size
}
Modify your onBindViewHolder method inside the Adapter to call that onBind method:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.onBind(listOfApps[position])
}
Inside your ViewHolder add lateinit var currentItem: AppData that will be set inside onBind and we can use it in onLongClick:
class ViewHolder(appView: View) : RecyclerView.ViewHolder(appView), View.OnClickListener,
View.OnLongClickListener {
.
.
.
override fun onLongClick(v: View?): Boolean {
// I want here on Long press BottomSheet appears with details
**val bottomSheetDialog = BottomSheetDialog(currentItem)**
// Show bottomSheet on LongPress
bottomSheetDialog.show(
(v?.context as FragmentActivity).supportFragmentManager, bottomSheetDialog.tag
)
return true
}
**private lateinit var currentItem: AppData**
fun onBind(appData: AppData) {
**currentItem = appData**
icon.setImageDrawable(currentItem.icon)
name.text = currentItem.name
size.text = currentItem.size
}
attach your currentItem list item to ViewHolder inside onBindViewHolder and inside onLongClick pass this data to freshly created BottomSheetDialog, which is extending Fragment (so you may use Bundle - setArgument method). then inside onCreateView set your data to Views
Create an interface
interface OnListItemClicked {
fun onClicked(data : AppData)
}
Implement that interface in BottomSheetDialog
class BottomSheetDialog: BottomSheetDialogFragment(), OnListItemClicked {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.bottom_sheet, container, false)
}
override fun onClicked(data: AppData) {
//show Details here
}
override fun getTheme(): Int = R.style.RoundBottomSheetDialog
}
Pass extra callback to the adapter from main activity.
Adapter(private val listOfApps: List<AppData>, val onClick: (AppData) -> Unit)
Invoke the click listener from adapter with listOfAppData[position]
On MainActivity pass a function into the Adapter initialisation.
fun passDataToBottomSheet(data: AppData) {
val listener = OnListItemClicked()
listener.onClicked(data)
}
Adapter(list, ::passDataToBottomSheet)
That's it. It should work now.

Display RecyclerView in FrameLayout Kotlin

I'm getting E/RecyclerView: No adapter attached; skipping layout all the time.
Gave my best on my own, but didn't seem to get it fixed.
Browsing here for a while and found some similar problems, but I don't know what to change in my specific
case.
If you need more info feel free to ask.
class ProdItemAdapter(private val prodList: List<ProduktItem>) :
RecyclerView.Adapter<ProdItemAdapter.ProdItemViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProdItemViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.card_view_prod, parent, false)
return ProdItemViewHolder(itemView)
}
override fun onBindViewHolder(holder: ProdItemViewHolder, position: Int) {
val currentItem = prodList[position]
holder.cvProdName.text = currentItem.name
holder.cvProdCode.text = currentItem.code
}
override fun getItemCount() = prodList.size
class ProdItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val cvProdName: TextView = itemView.cv_name
val cvProdCode: TextView = itemView.cv_code
}
}
RecyclerView-Adapter: Adding some Breakpoints inside this class, all get passed.
class FragProd : Fragment() {
private var param1: Int? = null
private var listener: OnFragmentInteractionListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getInt(ARG_SECTION_NUMBER)
}
val pl = getList()
rvProd.adapter = ProdItemAdapter(pl)
rvProd.layoutManager = LinearLayoutManager(context)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_frag_prod, container, false)
}
.......................
Fragment
Try this code, call your adapter in OnCreateView.
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
View view = inflater.inflate(R.layout.fragment_frag_prod, container, false)
val pl = getList()
rvProd.adapter = ProdItemAdapter(pl)
rvProd.layoutManager = LinearLayoutManager(context)
return view
}

System services not available to Activities before onCreate(), with Android RecyclerView inside a fragment Kotlin

I'm having trouble with Android RecyclerView in Kotlin inside a fragment who is in Home activity.
Here's my code:
myFragmentLayout:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvChapterList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
myFragmentCode:
val chaptersList: ArrayList<String> = ArrayList()
private lateinit var layoutManager: RecyclerView.LayoutManager
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.courses_layout, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
chaptersList.add("Android")
chaptersList.add("Kotlin")
chaptersList.add("RecyclerView")
layoutManager = LinearLayoutManager(context)
rvChapterList.layoutManager = layoutManager
rvChapterList.adapter = ChapterAdapter(Home(), chaptersList)
}
and myChapterAdapter:
class ChapterAdapter(private val context: Home, private val chaptersList: ArrayList<String>) : RecyclerView.Adapter<ChapterAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.list_item, parent, false))
}
override fun getItemCount(): Int {
return chaptersList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.chapterName?.text = chaptersList.get(position)
holder.itemView.setOnClickListener {
Toast.makeText(context, chaptersList.get(position), Toast.LENGTH_LONG).show()
}
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val chapterName = view.tvChapterName
}
}
It got this code from this tutorial, it's working inside an activity but not iside a fragment.
rvChapterList.adapter = ChapterAdapter(Home(), chaptersList)
Never create an Activity or other type of Context yourself. You always obtain them from the framework.
Replace that with:
rvChapterList.adapter = ChapterAdapter(requireActivity(), chaptersList)
and change the context property in ChapterAdapter to be a Context or Activity, not Home.

Fragment inside a viewpager doesnt show when is in recyclerview

Maybe this is a stupid question, but this is ruining my day...
I have a recyclerview in a fragment
override fun setUpRecyclerView(pics: List<Pictures>) {
recyclerView.setHasFixedSize(true)
layoutManager = LinearLayoutManager(context)
recyclerView.setLayoutManager(layoutManager)
mAdapter = NewsAdapter(pics, childFragmentManager)
recyclerView.setAdapter(mAdapter)
}
the NewsAdapter is:
class NewsAdapter
(private val mDataset: List<Pictures>, private val fragmentManager: FragmentManager)
: RecyclerView.Adapter<NewsAdapter.ViewHolder>() {
class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
var authorTextView: TextView
var viewPager: ViewPager
var indicator: CircleIndicator
init {
authorTextView = v.findViewById<View>(R.id.tv_author) as TextView
viewPager = v.findViewById<View>(R.id.viewPager) as ViewPager
indicator = v.findViewById<View>(R.id.indicator) as CircleIndicator
}
}
override fun onCreateViewHolder(parent: ViewGroup,
viewType: Int): NewsAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.item_preview, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val pictureList = mDataset.get(position)
holder.titleTextView.text = pictureList.title
holder.authorTextView.text = pictureList.author
showContent(pictureList.content, holder.viewPager, holder.indicator)
}
fun showContent(contentModel: List<ContentModel>, viewPager: ViewPager, indicator: CircleIndicator) {
if (contentModel.size <= 1) {
indicator.hide()
}
viewPager.adapter = GalleryContentAdapter(fragmentManager, contentModel)
indicator.setViewPager(viewPager)
}
override fun getItemCount(): Int = mDataset.size
}
the GalleryContentAdapter is:
class GalleryContentAdapter(fm: FragmentManager, val contentModels: List<ContentModel>) : FragmentPagerAdapter(fm) {
val galleryContentFactory: GalleryContentFactory = GalleryContentFactory()
override fun getItem(position: Int): Fragment = galleryContentFactory.getFragment(contentModels[position])
override fun getCount(): Int = contentModels.size
}
From now I am only handling a kind of content and the factory is so easy, but this is the code:
class GalleryContentFactory {
fun getFragment(contentModel: ContentModel): Fragment {
when (contentModel.type) {
"PICTURE" -> return PictureFragment.newInstance(contentModel.value)
}
return PictureFragment.newInstance(contentModel.value)
}
}
and the last is the PictureFragment:
class PictureFragment : NewsContentFragment() {
companion object {
val KEY = "PictureFragment.URL"
fun newInstance(url: String): NewsContentFragment {
val fragment = PictureFragment()
val bundle = Bundle()
bundle.putString(KEY, url)
fragment.arguments = bundle
return fragment
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_news_gif, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
arguments?.getString(KEY).let {
view.image.loadUrl(it!!)
}
}
}
When I debug the code, I check that the line view.image.loadUrl(it!!) is being executed, but nothing is rendered.
The loadUrl method is a extended function of imageviews that loads an image using Glide like this
fun ImageView.loadUrl(url: String) {
GlideApp.with(context).load(url).into(this)
}
and is being called correctly.
I also tried with PagerStateAdapter and take into account that I am passing the ChildFragmentManager to the adapter of the ViewPager.
If you can help me, you will save my day. Thanks in advance
This doesn't work. The way to go is a recycler into a recycler. If you want simulate as a ViewPager, you may use https://github.com/rubensousa/RecyclerViewSnap with a MATCH_PARENT in the
child views.

Categories

Resources