I have an issue with my custom adapter (I think) I'm getting my data using retrofit, that comes just fine, once I get the data I call another function to populate my recycle view, as follows.
I really appreciate if some one could help me on this...
private fun createMyOrdersTable(myOrders: List<OrderAssigned>){
val ordersCount = myOrders.size
val rv = myorder_rv
rv.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
val ordersList = ArrayList<OrderAssigned>()
if (ordersCount > 0){
myOrders.forEach {
ordersList.add(it)
}
// order.add(OrderAssigned("123","123213","123123","1231231","123123","123123","123123","123123"))
// order.add(OrderAssigned("123","123213","123123","1231231","123123","123123","123123","123123"))
println(ordersList)
val adapter = CustomAdapterMyOrders(ordersList)
rv.adapter = adapter
}else{
Toast.makeText(context, "You don't have any assigned order", Toast.LENGTH_LONG).show()
}
}
And this is my adapter:
package com.davesm.swiftdemexico
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.davesm.swiftdemexico.Model.OrderAssigned
import kotlinx.android.synthetic.main.myorders_layout.view.*
class CustomAdapterMyOrders(private val orders: ArrayList<OrderAssigned>): RecyclerView.Adapter<CustomAdapterMyOrders.ViewHolder>() {
inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val orderID = itemView.orderID!!
val clientName = itemView.clientName!!
val no_rem = itemView.orderRem!!
val orderDate = itemView.orderDate!!
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
//
val v = LayoutInflater.from(parent?.context).inflate(R.layout.myorders_layout, parent, false)
return ViewHolder(v);
}
override fun getItemCount(): Int {
//
return orders.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val model = orders[position]
holder.orderID.text = "ID: "+model.id
holder.clientName.text = model.nom_cte
holder.no_rem.text = "RemisiĆ³n"+model.no_rem
holder.orderDate.text = model.falta_rem
}
}
When I execute my app it shows only one "row" which is a card view even when I add more than one item in the foreach in the "createMyOrdersTable" I had tried to add it manually as in the commented code but still not working, I send the data as an ArrayList.
Here is the xml files for the views:
myorder_layout.xml
<?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">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/myorder_rv"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is my items layout.
myorders_layout.xml
<?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">
<androidx.cardview.widget.CardView
android:id="#+id/cardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="10dp"
app:cardCornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:padding="10dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/rounder_button_primary_color"
tools:ignore="MissingConstraints">
<TextView
android:id="#+id/orderID"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Order ID"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Large" />
<TextView
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:text="Client Name"
android:id="#+id/clientName"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/orderRem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RemisiĆ³n" />
<TextView
android:id="#+id/orderDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Date" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
It is not creating 1 row, it is creating many, but they are all as tall as the screen.
Change your item layout to use wrap_content for the height
<?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="wrap_content">
Related
I am trying to create a CardView within a RecyclerView but I can't get it to launch since the app crashes after starting with this error "RecyclerView has no LayoutManager". I've tried to apply fixes suggested by other posts regarding the same problem but got no luck so far.
Thank you in advance.
HomeActivity.kt
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
// Retrieves data from source
val arrayList = ArrayList<PreviewCardModel>()
arrayList.add(PreviewCardModel("Product A","500mg / 1000mg", R.drawable.image, 500))
arrayList.add(PreviewCardModel("Product D","Sample", R.drawable.image, 5040))
arrayList.add(PreviewCardModel("Product E","Sample", R.drawable.image, 5500))
arrayList.add(PreviewCardModel("Product F","Sample", R.drawable.image, 2500))
val myAdapter = CardAdapter(arrayList, this)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,false)
recyclerView.adapter = myAdapter
CardAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.sample.appname.R
import com.sample.appname.model.PreviewCardModel
import kotlinx.android.synthetic.main.preview_card.view.*
class CardAdapter (private val arrayList: ArrayList<PreviewCardModel>, val context: Context) :
RecyclerView.Adapter<CardAdapter.CardViewHolder>() {
class CardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems (model: PreviewCardModel) {
itemView.previewName.text = model.title
itemView.previewDesc.text = model.desc
itemView.previewPrice.text = model.price.toString()
itemView.previewImage.setImageResource(model.image)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.preview_card, parent, false)
return CardViewHolder(view)
}
// Returns size of data list
override fun getItemCount(): Int {
return arrayList.size
}
// Displays data at a certain position
override fun onBindViewHolder(holder: CardViewHolder, position: Int) {
holder.bindItems(arrayList[position])
}
}
activity_home.xml
<?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:padding="16dp"
tools:context=".HomeActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#color/browser_actions_title_color"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:orientation="horizontal"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
This is the error I am encountering.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sample.appname, PID: 5333
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample.appname/com.sample.appname.HomeActivity}: android.view.InflateException: Binary XML file line #54 in com.sample.appname:layout/activity_home: RecyclerView has no LayoutManager androidx.recyclerview.widget.RecyclerView{b2c2d71 VFED..... ......I. 0,0-0,0 #7f09016f app:id/recyclerView}, adapter:null, layout:null, context:com.sample.appname.HomeActivity#5dcb507
preview_card.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="120dp"
android:padding="10sp"
app:cardCornerRadius="3dp"
app:cardElevation="3dp"
app:cardUseCompatPadding="true">
<ImageView
android:id="#+id/previewImage"
android:layout_width="80dp"
android:layout_height="80dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="#drawable/heart"
android:contentDescription="#string/product_image" />
<TextView
android:id="#+id/previewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/product_name"
android:textSize="11sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/previewImage" />
<TextView
android:id="#+id/previewDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SAMPLE"
android:textSize="8sp"
android:textColor="#color/colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/previewName"
tools:ignore="SmallSp" />
<TextView
android:id="#+id/previewPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="#string/samplePrice"
android:textColor="#color/colorPrimary"
android:textSize="11sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.cardview.widget.CardView>
This error occurs when you've created same layout for multiple SDK or orientation and not mentioned the view in all the layout files, say for: activity_main.xml(v21)or activity_main(land) and so on. All the layouts should contain all the views with same IDs.
FIX: I had another activity_home(v21) layout that was cause the problems. Make sure you don't have multiple layouts that will cause problems. It was detecting no LayoutManager in the v21 version layout.
I've made a little sample of something I'm trying to do in a real app, and I can't figure out how to solve my issue. The current solution looks like this.
So I have a vertical list of movie categories, where within each genre, I have a horizontal list of movies. The first row, is showing The Exorcist as the first element, but it's not centered. The second row in Action, shows how it looks when I've scrolled a bit to the right. Last row is showing how the end of the row looks like.
I'd like to have the first and last of the rows, to be centered as well when they're "selected".
My main activity looks like this:
<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:background="#android:color/white">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/moviesListRecyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="#layout/movie_category_item_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
The movie_category_item_view looks like this:
<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:id="#+id/movieListLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/movieCategoryTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="40dp"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Horror" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/moviesRecyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:orientation="horizontal"
android:visibility="visible"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/movieCategoryTitle"
tools:listitem="#layout/movie_horizontal_item_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
And the movie_horizontal_item_view like this:
<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="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/movieTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Horror" />
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/image"
android:layout_width="237dp"
android:layout_height="209dp"
android:background="#android:color/black"
android:src="#drawable/ic_launcher_foreground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/movieTitle"
tools:src="#drawable/ic_launcher_foreground" />
</androidx.constraintlayout.widget.ConstraintLayout>
Hopefully what I'm asking for makes sense!
In case you want to try it out for yourself and see what I mean, it can be found on github here
use carouselview.CarouselView
<alirezat775.lib.carouselview.CarouselView
android:id="#+id/carousel_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"/>
the adapter
class MyAdapter(var ctx: Context) : CarouselAdapter() {
private var vh: CarouselViewHolder? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CarouselViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.home_list_item, parent, false)
vh = MyViewHolder(v)
return vh as MyViewHolder
}
override fun onBindViewHolder(holder: CarouselViewHolder, position: Int) {
}
inner class MyViewHolder(itemView: View) : CarouselViewHolder(itemView) {
}
}
the activity
class MainActivity : AppCompatActivity() {
var carousel: Carousel? = null
val adapter = MyAdapter(this)
override fun onCreate(savedInstanceState: Bundle?) {
carousel = Carousel(this, carousel_view, adapter)
carousel!!.setOrientation(CarouselView.HORIZONTAL, false)
// carousel!!.autoScroll(true, 5000, true)
// carousel!!.scaleView(true)
}
}
I have a grid supported by recyclerview inside a ConstraintLayout inside a ScrollView.
Although 20 items are inserted in setList() (I debugged it), only 9 items are displayed when using ScrollView
When I switch to NestedScrollView all 20 items are displayed, but the items in the middle are streched. Not the images, but it seems that there is a background behind streched 3 times the actual size of the item/image.
I'm using androidx libraries.
Fragment layout
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimaryDark"
tools:context=".ui.details.DetailsFragment">
<ImageView
android:id="#+id/detail_backdrop"
android:layout_width="match_parent"
android:layout_height="220dp"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
android:scaleType="centerCrop"
android:src="#drawable/clapperboard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/play_symbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="#+id/detail_backdrop"
app:layout_constraintEnd_toEndOf="#+id/detail_backdrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/detail_backdrop"
app:srcCompat="#drawable/ic_play_circle_outline_white_96dp" />
<ProgressBar
android:id="#+id/details_progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Some other views...
<TextView
android:id="#+id/tv_my_list_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/my_list_at_details"
app:layout_constraintEnd_toEndOf="#+id/wish_list_btn"
app:layout_constraintStart_toStartOf="#+id/wish_list_btn"
app:layout_constraintTop_toBottomOf="#id/wish_list_btn" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_recommended"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_my_list_details"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
List item layout
<androidx.cardview.widget.CardView 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:id="#+id/movie_card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_marginTop="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/movie_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/iv_poster"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="#drawable/clapperboard" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Adapter
package com.lacourt.myapplication.ui.details
import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Point
import android.graphics.drawable.Drawable
import android.util.DisplayMetrics
import android.util.Log
import android.view.Display
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.lacourt.myapplication.AppConstants
import com.lacourt.myapplication.R
import com.lacourt.myapplication.dto.DbMovieDTO
import com.lacourt.myapplication.ui.OnItemClick
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.movie_list_item.view.*
class RecommendedAdapter(
private val context: Context?,
private val onItemClick: OnItemClick,
private var list: ArrayList<DbMovieDTO>
) : RecyclerView.Adapter<RecommendedHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecommendedHolder {
val view =
LayoutInflater.from(context).inflate(R.layout.list_item_recommended, parent, false)
return RecommendedHolder(view)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: RecommendedHolder, position: Int) {
Log.d("grid-log", "onBindViewHolder() called, position = $position, list.size = ${list.size}")
// get device dimensions
val displayMetrics = DisplayMetrics()
(context as Activity).windowManager.defaultDisplay.getMetrics(displayMetrics)
val width = displayMetrics.widthPixels
val maxHeight= width.div(3) * 1.5
holder.poster.minimumHeight = maxHeight.toInt()
holder.apply {
Picasso.get()
.load("${AppConstants.TMDB_IMAGE_BASE_URL_W185}${list[position].poster_path}")
.placeholder(R.drawable.clapperboard)
.into(poster)
cardView.setOnClickListener {
val id = list[position].id
if (id != null)
onItemClick.onItemClick(id)
else
Toast.makeText(
context,
"Sorry. Can not load this movie. :/",
Toast.LENGTH_SHORT
).show()
}
}
}
fun setList(list: List<DbMovieDTO>) {
Log.d("grid-log", "setList() called")
this.list.clear()
this.list.addAll(list)
notifyDataSetChanged()
}
}
class RecommendedHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var poster = itemView.iv_poster
var cardView = itemView.movie_card_view
}
Any solutions for this strange behavior?
Since it may help someone in the future, I found a solution:
I just added holder.cardView.layoutParams.height = maxHeight.toInt() to onBindViewHolder of my adapter class and now every item layout is in the correct size.
Since you are using a constraint layout, you should let the constraints set the size, in general.
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_recommended"
android:layout_width="0dp"
android:layout_height="dp"
...
0dp in this case means let the constraints set the value.
I got an error when I scroll down the list view. When scroll reached to bottom of activity, the error occurred. And one strange thing is here. On kotlin code, there is "DataController.getDataList()" function. This function get 10 data list as ArrayList, but I got only 9 data in my emulator. What's wrong with my code?
activity_spiral_test_list.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=".spiralTestListActivity"
android:background="#color/Background">
<ListView
android:id="#+id/patientList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ViewStub
android:id="#+id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout="#layout/empty"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="80dp"
android:layout_height="80dp"
android:src="#drawable/add"
android:layout_margin="40dp"
android:scaleType="center"
android:tint="#android:color/white"
android:backgroundTint="#color/Primary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:borderWidth="0dp"/>
</android.support.constraint.ConstraintLayout>
patient_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:orientation="vertical">
<TextView
android:id="#+id/patientName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Patient"
android:textSize="40sp"
android:textColor="#android:color/black"
android:textStyle="bold"/>
<TextView
android:id="#+id/patientDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Explanation"
android:textSize="25sp"/>
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginEnd="40dp"
android:orientation="vertical">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="#drawable/assignment"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test"
android:textSize="20sp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
spiralTestListActivity.kt
import android.content.Context
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import myPackage.DataController
import myPackage.PatientData
import kotlinx.android.synthetic.main.activity_spiral_test_list.*
class spiralTestListActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_spiral_test_list)
patientList.adapter = patientAdapter(this, DataController.getDataList())
patientList.emptyView = empty
}
private inner class ViewHolder {
lateinit var name: TextView
lateinit var description: TextView
}
inner class patientAdapter(context: Context, val listItem: ArrayList<PatientData>) : BaseAdapter() {
private val mInflator: LayoutInflater = LayoutInflater.from(context)
override fun getCount(): Int {
return this.listItem.size
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItem(position: Int): Any {
return this.listItem[position]
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View
val holder: ViewHolder
if (convertView == null) {
view = mInflator.inflate(R.layout.patient_list_item, parent, false)
holder = ViewHolder()
holder.name = view.findViewById(R.id.patientName) as TextView
holder.description = view.findViewById(R.id.patientDescription) as TextView
}
else {
view = convertView
holder = convertView.tag as ViewHolder
}
val patient = getItem(position) as PatientData
val name = holder.name
val description = holder.description
name.text = patient.name
description.text = patient.description
return view
}
}
}
I solve this problem. This problem is occurred because of thread. Surely, controller of data is adapter. But, I add data in my dialog class.(There are some different part of code above. I changed it..) So, when thread ask to get data from adapter, the data is different with ListView's data. It occurred an error.
I fix the code in my adapter class and dialog class. In the adapter class, I add a function named add.
fun add(data: PatientData) {
DataController.addData(data)
}
Also, there is one more thing. In SpiralTestListActivity.ky, I don't add
convertView.tag = holder
above the else part in Adapter class..!!
These parts make my app work correctly..!
I've been scratching my head about this problem. I have a recyclerview inside a recyclerview that shows a grid layout where you can scroll both vertically and horizontally.
I decided to enlarge the width and height of each item. Previously, width and height were: 80 x 100
<?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"
android:id="#+id/book_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/inner_dropshadow"
android:layout_width="80dp"
android:layout_height="100dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/bookdropshadow" />
</android.support.constraint.ConstraintLayout>
And then I enlarged it to 150x 180. And then Level 4-6 row completely disappeared no matter how much I scroll up. I only expected the recyclerview to display larger images. Why does this happen?
[EDIT] I ran a debug and it seems only 3 positions are bound in the outer adapter when the app is run on a phone but there are 4 positions when run on a tablet.
<?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"
android:id="#+id/book_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/inner_dropshadow"
android:layout_width="150dp"
android:layout_height="180dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/bookdropshadow" />
</android.support.constraint.ConstraintLayout>
Please note that this also happens when I run the app on a device. In a tablet, it shows all the Levels, while on a phone, it only shows Levels 1-3.
Outer recyclerview layout
<?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"
android:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/color_white">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/swiperefresh"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/toolbar">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="always">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/browsebooksheader_layout"
android:id="#+id/bb_header"
app:layout_constraintBottom_toTopOf="#+id/guidelinetop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"/>
<android.support.constraint.Guideline
android:id="#+id/guidelinetop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.30"/>
<Button
android:id="#+id/btn_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:background="#drawable/search_btn_border"
android:padding="8dp"
android:text="Search"
android:textSize="#dimen/browse_search_textsize"
android:textColor="#android:color/darker_gray"
app:layout_constraintBottom_toTopOf="#+id/recyclerview_main"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/bb_header" />
<ProgressBar
android:id="#+id/main_progressbar"
style="?android:attr/progressBarStyleSmall"
android:layout_marginTop="16dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:indeterminateTint="#color/color_grey"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btn_search"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false"
android:background="#color/color_white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btn_search"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/toolbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/swiperefresh"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<include layout="#layout/toolbar_layout_wo_learn"/>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
Inner recyclerview layout
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/book_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Category Title"
android:textColor="#color/defaultdark_color"
android:textSize="#dimen/browse_category_textsize"
android:fontFamily="#font/vagroundedstd_bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="#dimen/browse_seeall_imagesize"
android:layout_height="#dimen/browse_seeall_imagesize"
android:layout_marginBottom="2dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="8dp"
android:id="#+id/see_all_btn"
android:src="#drawable/seeall"
app:layout_constraintBottom_toTopOf="#+id/inner_recyclerview"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="#+id/inner_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
android:background="#color/color_white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/book_category"/>
<TextView
android:id="#+id/h_line"
android:layout_width="match_parent"
android:layout_height="0.8dp"
android:background="#color/color_grey"
android:gravity="center"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:alpha="0.5"
app:layout_constraintTop_toBottomOf="#id/inner_recyclerview"/>
</android.support.constraint.ConstraintLayout>
Outer Adapter
class BrowseBooksAdapter : RecyclerView.Adapter<BrowseBooksAdapter.SimpleViewHolder>() {
private var sortedList : SortedMap<String, List<ResourcesList>> = emptyMap<String, List<ResourcesList>>().toSortedMap()
fun setData(sortedList : SortedMap<String, List<ResourcesList>>) {
if (this.sortedList != sortedList) {
this.sortedList = sortedList
notifyDataSetChanged()
}
}
override fun getItemCount(): Int {
return sortedList.count()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.browsebooks_layout, parent, false)
return SimpleViewHolder(view)
}
override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
val dataList = ArrayList(sortedList.values)[position]
holder.category_text.text = ArrayList(sortedList.keys)[position]
holder.booksByCategory = dataList
holder.horizontalAdapter.setData(dataList)
}
class SimpleViewHolder(v: View, var booksByCategory : List<ResourcesList>? = null) : RecyclerView.ViewHolder(v) {
var recyclerView : RecyclerView = v.findViewById(R.id.inner_recyclerview)
var category_text : TextView = v.findViewById(R.id.book_category)
var fragmentCallback: FragmentCallback? = null
val horizontalAdapter: BooksByCategoryAdapter
init {
recyclerView.layoutManager = object : LinearLayoutManager(v.context, LinearLayoutManager.HORIZONTAL, false) {
override fun canScrollHorizontally(): Boolean {
return true
}
override fun canScrollVertically(): Boolean {
return false
}
}
horizontalAdapter = BooksByCategoryAdapter()
recyclerView.adapter = horizontalAdapter
fragmentCallback = v.context as FragmentCallback
var mLastClickTime : Long = 0
v.see_all_btn.setOnClickListener {
val category = v.book_category.text.toString()
// double-clicking prevention, using threshold of 1000 ms
if (!(SystemClock.elapsedRealtime() - mLastClickTime < 1000)){
mLastClickTime = SystemClock.elapsedRealtime()
if(fragmentCallback != null){
fragmentCallback!!.callBackSeeAllFragment(booksByCategory!!, category)
}
}
}
}
}
}
Inner Adapter
class BooksByCategoryAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var booksByCategory: List<ResourcesList> = emptyList()
fun setData(data: List<ResourcesList>) {
if (this.booksByCategory != data) {
this.booksByCategory = data
notifyDataSetChanged()
}
}
override fun getItemCount(): Int {
return booksByCategory.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(R.layout.bookcontainer_layout, parent, false)
return CustomVH(cellForRow)
}
override fun onBindViewHolder(rawHolder: RecyclerView.ViewHolder, position: Int) {
val holder = rawHolder as CustomVH
val booksProcessModel = BooksProcessModel()
booksProcessModel.setItem(booksByCategory[position])
holder.booksByCategory = booksByCategory[position]
Picasso.get().load(booksByCategory[position].coverURI).into(holder.inner_bookcover)
}
private inner class CustomVH(v: View, var booksByCategory : ResourcesList? = null): RecyclerView.ViewHolder(v) {
var inner_bookcover : ImageView = v.findViewById(R.id.inner_bookcover)
var fragmentCallback: FragmentCallback? = null
var ctx : Context = v.context
var mLastClickTime : Long = 0
init {
fragmentCallback = ctx as FragmentCallback
v.setOnClickListener {
// double-clicking prevention, using threshold of 1000 ms
if (!(SystemClock.elapsedRealtime() - mLastClickTime < 1000)){
mLastClickTime = SystemClock.elapsedRealtime()
if(fragmentCallback != null){
fragmentCallback!!.callBackDownloadBookFragment(booksByCategory!!)
}
}
}
}
}
class BooksProcessModel {
private var processBooks : ResourcesList? = null
fun setItem(books: ResourcesList) {
this.processBooks = books
}
fun setVisibility(ctx: Context) : Int {
val sp = PreferenceManager.getDefaultSharedPreferences(ctx)
val page = sp.getString(processBooks!!.id.toString(), "")
if (page != "") {
return View.VISIBLE
}
return View.INVISIBLE
}
}
}
You need to change the layout_height of the outer recycler view to wrap_content.
Nevermind, figured it out. I should be using a NestedScrollView instead of a ScrollView. The missing items were still there. It's just that I couldn't scroll the nested recyclerview.
In my case it was because I had the RecyclerView directly and even though it scrolled (horizontally), the same thing happened to me if for example the keyboard appeared.
Solution: Put the RecyclerView inside a NestedScrollView and delegate the scroll to it, like this:
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/item"/>
</androidx.core.widget.NestedScrollView>