I'm preparing a little game in my app and would like to create a recylerview based on gridlayoutmanager and my problem is that I can't center horizontally all elements inside this view.
I have already tried to fix it by some changes in layout file but it didn't help.
Adapter :
class AdapterCheckYrslf(private val word: String) :
RecyclerView.Adapter<AdapterCheckYrslf.CardViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_checkrslf_letter, parent, false)
return CardViewHolder(view)
}
override fun getItemCount(): Int {
return word.length
}
override fun onBindViewHolder(holder: CardViewHolder, position: Int) {
holder.currentLetter.text = word[position].toUpperCase().toString()
}
class CardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val currentLetter = itemView.findViewById<TextView>(R.id.item_checkyrslf_letter)
}
}
GridSpacingItemDecoration, it makes a space beetwen every item :
class GridSpacingItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View,
parent: RecyclerView, state: RecyclerView.State) {
outRect.left = space
outRect.right = space
outRect.bottom = space
outRect.top = space
}
}
ColumnQty :
class ColumnQty(context: Context, viewId: Int) {
private val width: Int
private val height: Int
private var remaining: Int = 0
private val displayMetrics: DisplayMetrics
init {
val view = View.inflate(context, viewId, null)
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
width = view.measuredWidth
height = view.measuredHeight
displayMetrics = context.resources.displayMetrics
}
fun calculateNoOfColumns(): Int {
var numberOfColumns = displayMetrics.widthPixels / width
remaining = displayMetrics.widthPixels - numberOfColumns * width
if (remaining / (2 * numberOfColumns) < 15) {
numberOfColumns--
remaining = displayMetrics.widthPixels - numberOfColumns * width
}
return numberOfColumns
}
fun calculateSpacing(): Int {
val numberOfColumns = calculateNoOfColumns()
return remaining / (2 * numberOfColumns)
}
}
Activity :
val gridManagerFix = ColumnQty(this, R.layout.item_checkrslf_letter)
check_yrslf_word.layoutManager = GridLayoutManager(this, gridManagerFix.calculateNoOfColumns())
check_yrslf_word.addItemDecoration(GridSpacingItemDecoration(gridManagerFix.calculateSpacing()))
check_yrslf_word.setHasFixedSize(true)
Fragment of layout :
<LinearLayout
android:id="#+id/helper_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="#+id/check_yrslf_end"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/check_yrslf_hand">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/check_yrslf_word"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:clipChildren="true"
android:clipToPadding="true"
android:numColumns="auto_fit"
android:overScrollMode="never"
android:scrollbars="none"
android:scrollingCache="true"
android:stretchMode="columnWidth"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
Item layout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.card.MaterialCardView
android:id="#+id/item_checkyrslf_cardLetter"
style="#style/Widget.MaterialComponents.CardView"
android:layout_width="27dp"
android:layout_height="27dp"
android:layout_marginBottom="5dp"
android:checkable="false"
app:cardBackgroundColor="#color/grey_3"
app:cardElevation="0dp"
app:checkedIconTint="#color/white"
app:strokeColor="#color/colorAccent"
app:strokeWidth="1dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:id="#+id/item_checkyrslf_letter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="#font/poppins_medium"
android:gravity="center"
android:includeFontPadding="false"
android:text="A"
android:textAppearance="#style/TextAppearance.MaterialComponents.Headline1"
android:textColor="#color/textColor"
android:textSize="16sp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
Pictures :
How does this layout look in Preview
That's what I have
I would like to have
Try making the RecyclerView android:layout_width="match_parent" and android:gravity="center"
Edit 1:
Try removing all those added params to your RecyclerView: (Something like this)
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/check_yrslf_word"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_gravity="center_horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Now try it, just for debugging purposes.
I have solved it by changing GridLayoutManager to LinearLayoutManager.
Related
As the official material.io documentation says:
Chips are compact elements that represent an input, attribute, or action.
I want to add chips as attributes (tags) for any blog post, a recyclerview is used to show the list of blog posts:
item_post.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/mcv_container_item_blog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:clickable="true"
android:background="?selectableItemBackground"
app:cardUseCompatPadding="true">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/llc_container_item_project"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/item_margin"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/aciv_item_post_image"
android:layout_width="match_parent"
android:layout_height="#dimen/item_project_Image_size"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
app:srcCompat="#drawable/drawer_bg"/>
<com.google.android.material.textview.MaterialTextView
android:id="#+id/mtv_item_post_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/item_margin"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:textColorHighlight="#color/design_default_color_background"
android:text="Chameleon UI Kit" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/mtv_item_post_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/red_lighten"
android:layout_marginTop="#dimen/user_name_margin_start"
android:layout_marginEnd="#dimen/user_name_margin_start"
android:layout_marginBottom="#dimen/user_name_margin_start"
android:text="10 Sept"/>
<com.google.android.material.textview.MaterialTextView
android:id="#+id/mtv_item_post_short_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/TextAppearance.AppCompat.Small"
android:text="#string/about_me" />
<include layout="#layout/item_divider"/>
<HorizontalScrollView
android:id="#+id/hsv_item_post_tags"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<com.google.android.material.chip.ChipGroup
android:id="#+id/cg_item_post_tags"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleLine="true"/>
</HorizontalScrollView>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.google.android.material.card.MaterialCardView>
then the PostAdapter class:
class PostAdapter(
private val postList: List<Post>
): RecyclerView.Adapter<PostAdapter.PostViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_post, parent, false)
return PostViewHolder(view)
}
override fun onBindViewHolder(holder: PostViewHolder, position: Int) {
val post = postList[position]
holder.postTitle.text = post.postTitle
holder.postDescription.text = post.postDescription
holder.postDate.text = post.postDate
val tagChip = Chip(holder.itemView.context).apply {
id = View.generateViewId()
text = "label"
}
holder.postTagsChipGroup.addView(tagChip)
}
override fun getItemCount(): Int {
return postList.size
}
inner class PostViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val postTitle: MaterialTextView = itemView.findViewById(R.id.mtv_item_post_title)
val postDescription: MaterialTextView = itemView.findViewById(R.id.mtv_item_post_short_description)
val postTagsChipGroup: ChipGroup = itemView.findViewById(R.id.cg_item_post_tags)
val postDate: MaterialTextView = itemView.findViewById(R.id.mtv_item_post_date)
}
}
at this stage a weird thing happens, when I 'scroll recyclerview' other Chips are added from nowhere as you can see this behavior in gif below:
how to avoid such behavior, what changes should I make in adapters onBindViewHolder method?
guys
When I use horizontal RecyclerView ItemDecoration I encounter some problems, I want to achieve different decoration height but horizontal recyclerview decoration height is always the same, pictures and code are below, I used the same code in vertical GridLayoutManger is effective, I saw the source code should be measured when the horizontal recyclerview has special processing, this is normal?
pic
class MainItemDecoration : RecyclerView.ItemDecoration() {
private val space20 = (Resources.getSystem().displayMetrics.density * 20).toInt()
override fun getItemOffsets(
outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
) {
val lp = view.layoutParams as GridLayoutManager.LayoutParams
outRect.left = space20
outRect.right = space20
when (lp.spanIndex) {
0 -> {
outRect.bottom = 0
}
1 -> {
outRect.bottom = space20
}
2 -> {
outRect.bottom = space20 * 2
}
}
}
}
----- MainActivity----
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView: RecyclerView = findViewById(R.id.recycler_view)
recyclerView.apply {
layoutManager = GridLayoutManager(context, 3, GridLayoutManager.HORIZONTAL, false)
adapter = MainAdapter()
addItemDecoration(MainItemDecoration())
}
}
}
--- xml-------
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_red_light"
tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:listitem="#layout/item_main"
tools:orientation="horizontal"
tools:spanCount="3" />
</FrameLayout>
--- item ----
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:background="#android:color/holo_blue_light"
android:gravity="center"
android:textColor="#android:color/white"
android:textSize="16sp"
tools:text="123" />
</FrameLayout>
I need to display items similar to a hamburger.
Each element has a different height, but the distance between them should be always the same. I tried to use LinearLayoutManager, but spaces between items were too big. I created custom LinearLayoutManager but it doesn't work as I expected. How I should make spacing like 16dp or 50 px between ImageView.
I also need to make no spacing for the same type of items, but this problem is less important.
class CustomLinearLayoutManager(context: Context) : LinearLayoutManager(context) {
private val horizontalSpace: Int
get() = width - paddingEnd - paddingStart
private val verticalSpace: Int
get() = height - paddingBottom - paddingTop
override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
return spanLayoutSize(super.generateDefaultLayoutParams())
}
override fun generateLayoutParams(c: Context, attrs: AttributeSet): RecyclerView.LayoutParams {
return spanLayoutSize(super.generateLayoutParams(c, attrs))
}
override fun generateLayoutParams(lp: ViewGroup.LayoutParams): RecyclerView.LayoutParams {
return spanLayoutSize(super.generateLayoutParams(lp))
}
private fun spanLayoutSize(layoutParams: RecyclerView.LayoutParams): RecyclerView.LayoutParams {
if (orientation == HORIZONTAL) {
layoutParams.width = (horizontalSpace / itemCount)
} else if (orientation == VERTICAL) {
layoutParams.height = (verticalSpace / itemCount)
}
return layoutParams
}
override fun canScrollVertically(): Boolean {
return false
}
override fun canScrollHorizontally(): Boolean {
return false
}
}
RecyclerView_item.xml
<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/RecyclerFood_item"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/ingredientPic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:contentDescription="#string/display_image_of_ingredient"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment_layout.xml
<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/DishFragmentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="my.custom.food-app.MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/DishList"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I have tried to search the answer like in this thread: RecyclerView LinearLayoutManager set item count
But it doesn't exactly solve my problem because it shows fixed items.
I want to make RecyclerView like the image below
as you can see in the picture, there are 3 items showing, but also it has incomplete item showing in the right side to give indication that this scroll view can be scrolled. I want to have that partial(3 + 1/4) item in the recyclerView for all screen size.
The xml of item layout I use is like this:
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="150dp"
android:layout_height="250dp"
app:cardCornerRadius="10dp"
android:layout_marginRight="8dp"
app:cardElevation="3dp">
<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/background_light">
<ImageView
android:layout_width="0dp"
android:layout_height="100dp"
app:srcCompat="#drawable/logo_apps"
android:id="#+id/productImageView_Item"
android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintDimensionRatio="w,1:1"/>
<TextView
android:text="#string/product_name"
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/productName_textView_item"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="#+id/productImageView_Item"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="4dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="4dp"
android:textAlignment="center"
android:minLines="1"
android:maxLines="2"
app:autoSizeMinTextSize="8sp"
app:autoSizeMaxTextSize="14sp"
android:layout_marginBottom="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
and the recycler view xml in the activity is like this:
<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"
tools:context=".Fragment.HomeFragment" android:background="#color/colorLightGrayBackground">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="#+id/textView"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="1.0"
android:id="#+id/recyclerView_1"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
and here is the code in the java file:
val layoutManager = LinearLayoutManager(mContext,LinearLayoutManager.HORIZONTAL,false)
recyclerView1.adapter = productAdapter
recyclerView1.layoutManager = layoutManager
here is my adapter:
class ProductListAdapter(val context: Context, val products: List<Product>) : RecyclerView.Adapter<ProductListAdapter.ViewHolderProductList>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderProductList {
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(R.layout.item_product_list,parent, false)
return ViewHolderProductList(cellForRow)
}
override fun getItemCount(): Int {
return products.size
}
override fun onBindViewHolder(holder: ViewHolderProductList, position: Int) {
val product = products[position]
holder.productNameTextView.text = product.name
Glide
.with(context)
.load(product.getFormattedImagePath())
.into(holder.productImageView)
}
inner class ViewHolderProductList(itemView: View) : RecyclerView.ViewHolder(itemView) {
val productImageView = itemView.findViewById<ImageView>(R.id.productImageView_Item)
val productNameTextView = itemView.findViewById<TextView>(R.id.productName_textView_item)
}
}
I recently did this in one of my lists. You want to find out the device's screen width:
val displayMetrics = DisplayMetrics()
(context as NavigationActivity).windowManager.getDefaultDisplay().getMetrics(displayMetrics)
width = displayMetrics.widthPixels
And then divide the width of the device in order to have 3 and a 1/3 blocks cover it, so divide the screen width by around 3.33:
itemWidth = width / 3.33
Now on your onBind method in your list's adapter, you want to change the item's container layout params width to be the itemWidth:
val lp = itemView.container.layoutParams
lp.height = originalHeight
lp.width = itemWidth
itemView.container.layoutParams = lp
You might need to take into consideration padding between items, so instead of:
itemWidth = width / 3.33
Something like:
itemWidth = (width - totalPadding) / 3.33
EDIT
Add it in your code like this:
class ProductListAdapter(val context: Context, val products: List<Product>) : RecyclerView.Adapter<ProductListAdapter.ViewHolderProductList>() {
// holds this device's screen width,
private var screenWidth = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderProductList {
// get screen width
val displayMetrics = DisplayMetrics()
(context as YourActivity).windowManager.getDefaultDisplay().getMetrics(displayMetrics)
screenWidth = displayMetrics.widthPixels
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(R.layout.item_product_list,parent, false)
return ViewHolderProductList(cellForRow)
}
override fun getItemCount(): Int {
return products.size
}
override fun onBindViewHolder(holder: ViewHolderProductList, position: Int) {
val product = products[position]
val itemWidth = screenWidth / 3.33
val lp = holder.cardView.layoutParams
lp.height = lp.height
lp.width = itemWidth
itemView.container.layoutParams = lp
holder.productNameTextView.text = product.name
Glide
.with(context)
.load(product.getFormattedImagePath())
.into(holder.productImageView)
}
inner class ViewHolderProductList(itemView: View) : RecyclerView.ViewHolder(itemView) {
val productImageView = itemView.findViewById<ImageView>(R.id.productImageView_Item)
val productNameTextView = itemView.findViewById<TextView>(R.id.productName_textView_item)
}
}
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>