Viewpager 2 conflict with SwipeRefreshLayout - android-recyclerview

Im trying to use SwipeRefreshLayout to load data whenever user swipe down. It works correctly in Viewpager but when I user Viewpager2 it causes :
2022-03-08 09:12:39.733 6489-6489/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 6489
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at androidx.recyclerview.widget.StaggeredGridLayoutManager$Span.calculateCachedStart(StaggeredGridLayoutManager.java:2531)
at androidx.recyclerview.widget.StaggeredGridLayoutManager$Span.getStartLine(StaggeredGridLayoutManager.java:2548)
at androidx.recyclerview.widget.StaggeredGridLayoutManager.checkSpanForGap(StaggeredGridLayoutManager.java:410)
at androidx.recyclerview.widget.StaggeredGridLayoutManager.hasGapsToFix(StaggeredGridLayoutManager.java:359)
at androidx.recyclerview.widget.StaggeredGridLayoutManager.checkForGaps(StaggeredGridLayoutManager.java:282)
at androidx.recyclerview.widget.StaggeredGridLayoutManager.onScrollStateChanged(StaggeredGridLayoutManager.java:317)
at androidx.recyclerview.widget.RecyclerView.dispatchOnScrollStateChanged(RecyclerView.java:5197)
at androidx.recyclerview.widget.RecyclerView.setScrollState(RecyclerView.java:1550)
at androidx.recyclerview.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:5397)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:727)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)>
It happen when I change to the second page and return to the first page and swipe down to refresh. Below is my layout of the first page.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.example.myapplication.viewmodel.FirstViewModel"/>
</data>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
app:onRefreshListener="#{() -> viewModel.onRefresh()}"
app:refreshing="#{viewModel.spinner}"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
>
<TextView
android:id="#+id/tvContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="News"
android:textAllCaps="true"
android:textSize="30sp"
android:textStyle="bold"
android:gravity="center"
android:onClick="#{() -> viewModel.nextFragment()}"
android:textColor="#color/red"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/csArticles"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#+id/tvContent"
>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvNews"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="50dp"
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
tools:listitem="#layout/item_news" />
<ProgressBar
android:id="#+id/spinner"
android:layout_width="0dp"
android:visibility="gone"
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" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/csNoArticles"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#+id/tvContent"
app:layout_constraintBottom_toBottomOf="parent"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No articles"
android:textSize="25sp"
android:textColor="#color/navy"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</layout>
And the last is the function which I use to init Viewpager2Adapter.
fun ViewPager2.initFragment(
fragment: Fragment,
fragments: MutableList<Fragment>
): ViewPager2 {
adapter = object : FragmentStateAdapter(fragment) {
override fun createFragment(position: Int) = fragments[position]
override fun getItemCount() = fragments.size
}
return this
}
Thank for reading.

Related

how to adjust width of FrameLayout during app startup in kotlin

So I am new to Kotlin, so I realize this may be a bit basic, however, I've done a lot of searching and tried a few different things and not yet having any luck.
So I've got a simple layout I'm aiming for, with the main area a "chess-like" board of cells. I've managed to get everything together and all runs fine, however, when I try to implement resizing things (to accomodate different sized devices/resolutions/etc), I can't seem to figure out exactly how to handle that.
This is a simplified version of what I'm trying to do:
As seen in the image, I have some "items" on the right side of the screen that will take up some space, however, the primary driving item will be the main playing board (for now, that grid of 4x4 buttons).
Explaining it in plain English, I'd like it to:
position the 2 status bars (green/blue ones) on top/bottom edges as shown.
Grid (a FrameLayout holding a TableLayout), is constrained to the top/bottom of these status bars, so the Height should be "set" to that difference. I need to determine the size of each cell ( ie height used by the FrameLayout divided by # of "rows" ).
To make/keep the grid cells "square", I need to resize the widths to match that of their height. I'm trying to set the Framelayout width to that. (in my final version the grid is not actually square, eg 4x6 - but keep in mind, the grid is a fixed size - it's not dynamic, it's just the size of the cells I need to adjust for changes in resolution)
the status bar widths should match the FrameLayout width, once done. They have been constrained to the end of the FrameLayout.
the big textView in Bottom right will use up whatever width is left. It has also been constrained to the end of the FrameLayout.
I've tried to constrain the right side of the FrameLayout (to parent/screen -200), I've also tried setting it to fix width (then adjust).
I've tried some other things like Linear layouts, and had no success with any option.
Here's the activity_main.xml for this sample:
<?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:background="#515151"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#4CAF50"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/frLay01"
app:layout_constraintStart_toStartOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="1"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="2"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#2196F3"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="#+id/frLay01"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="1"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView12"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="2"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView13"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
</LinearLayout>
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_margin="6dp"
app:cardCornerRadius="8dp"
app:cardElevation="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/frLay01">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
<FrameLayout
android:id="#+id/frLay01"
android:layout_width="500dp"
android:layout_height="0dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="200dp"
android:layout_marginBottom="6dp"
app:layout_constraintBottom_toTopOf="#+id/linearLayout2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout">
<TableLayout
android:id="#+id/tblLay01"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/imageButton00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/imageButton10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/imageButton20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton21"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton22"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton23"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/imageButton30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton31"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton32"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/checkbox_off_background" />
</TableRow>
</TableLayout>
</FrameLayout>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginEnd="40dp"
android:text="Button"
android:textColor="#FFFFFF"
app:backgroundTint="#0920A3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
and the MainActivity.kt I'm trying is:
package com.example.test1
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.ViewTreeObserver
import android.widget.FrameLayout
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fun try1 () {
var frLay = findViewById ( R.id.frLay01 ) as FrameLayout
var cellSize = frLay.height / 8
// frLay.getLayoutParams().width = cellSize * 8
Log.i("Test: try1", "cellSize = " + cellSize)
}
fun try2 () {
var frLay = findViewById ( R.id.frLay01 ) as FrameLayout
var cellSize = frLay.getLayoutParams().height / 8
// frLay.getLayoutParams().width = cellSize * 8
Log.i("Test: try2", "cellSize = " + cellSize)
}
fun try3() {
var frLay = findViewById ( R.id.frLay01 ) as FrameLayout
var cellSize : Int = 0
val viewTreeObserver: ViewTreeObserver = frLay.getViewTreeObserver()
if (viewTreeObserver.isAlive) {
viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
frLay.getViewTreeObserver().removeOnGlobalLayoutListener(this)
cellSize = frLay.getHeight() / 8
}
})
}
// frLay.getLayoutParams().width = cellSize * 8
Log.i("Test: try3", "cellSize = " + cellSize)
}
try1()
try2()
try3()
}
}
Every time I run, I can't seem to get a Height for the FrameLayout .. it always comes back as 0. (which makes sense, since it's set to constrained) (I also tried measuredHeight .. also shows 0)
How should I be adjusting the size of this grid ?
or is there some sneaky way to setup the constraints to do it properly with everything set to "match parent" ??
[edit]
this is basically what I'm aiming for .. this is the closest I've gotten:
Board flush with left side, squares of the board are "square", board flush with top/bottom status bars.
width resizes to keep cells square, and status bars match.
Textview on right uses up whatever area is left.
I managed the above using a Recylerview, setting
app:layout_constraintDimensionRatio="W,3:4"
unfortunately, I had to manually hardcode the cell size in Adaptor class
(I was following this tutorial at the time and modifying to my ends:
https://www.youtube.com/watch?v=C2DBDZKkLss
[/edit]
I think actually you should do the game board grid in a separate layout file and then put in the main layout using <include>. This is way easier for manipulating it independently.
I used the below ConstraintLayouts to create this. I don't know what your grid elements are so I just used generic colored Views as placeholders. You can force the included layout into a square using app:layout_constraintDimensionRatio.
Main layout:
<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/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#707070">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/statusBarsDivider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".45" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/statusBarsEnd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="20dp"
app:layout_constraintGuide_percent=".67" />
<View
android:id="#+id/topStatusBarBackground"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="-8dp"
android:background="#0080ff"
app:layout_constraintBottom_toBottomOf="#+id/topTextViewLeft"
app:layout_constraintEnd_toStartOf="#+id/statusBarsEnd"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/topTextViewLeft"
style="#style/text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="TextView"
app:layout_constraintEnd_toStartOf="#+id/statusBarsDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/topTextViewRight"
style="#style/text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="TextView"
app:layout_constraintEnd_toStartOf="#+id/statusBarsEnd"
app:layout_constraintStart_toEndOf="#id/statusBarsDivider"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/bottomStatusBarBackground"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="-8dp"
android:background="#00C864"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/statusBarsEnd"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/bottomTextViewLeft" />
<TextView
android:id="#+id/bottomTextViewLeft"
style="#style/text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/statusBarsDivider"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/bottomTextViewRight"
style="#style/text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/statusBarsEnd"
app:layout_constraintStart_toEndOf="#id/statusBarsDivider" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/horizontalCenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="20dp"
app:layout_constraintGuide_percent=".5" />
<TextView
android:id="#+id/textView3"
style="#style/text_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/statusBarsEnd"
app:layout_constraintTop_toTopOf="#+id/horizontalCenter" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include
layout="#layout/game_board"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="#+id/bottomStatusBarBackground"
app:layout_constraintDimensionRatio="w,1:1"
app:layout_constraintEnd_toStartOf="#+id/statusBarsEnd"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/topStatusBarBackground" />
</androidx.constraintlayout.widget.ConstraintLayout>
The game_board layout:
(There's probably a much better way to do this. I created four horizontal and four vertical view chains and all of the views have 0dp height and width so the ConstraintLayout makes them all take up evenly divided space.)
<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">
<View
android:id="#+id/cellA1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#3F51B5"
app:layout_constraintBottom_toTopOf="#+id/cellB1"
app:layout_constraintEnd_toStartOf="#+id/cellA2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/cellA2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#9C27B0"
app:layout_constraintBottom_toTopOf="#+id/cellB2"
app:layout_constraintEnd_toStartOf="#+id/cellA3"
app:layout_constraintStart_toEndOf="#+id/cellA1"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/cellA3"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#F44336"
app:layout_constraintBottom_toTopOf="#+id/cellB3"
app:layout_constraintEnd_toStartOf="#+id/cellA4"
app:layout_constraintStart_toEndOf="#+id/cellA2"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/cellA4"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#FFEB3B"
app:layout_constraintBottom_toTopOf="#+id/cellB4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/cellA3"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/cellB1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#8BC34A"
app:layout_constraintBottom_toTopOf="#+id/cellC1"
app:layout_constraintEnd_toStartOf="#+id/cellB2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/cellA1" />
<View
android:id="#+id/cellB2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#2196F3"
app:layout_constraintBottom_toTopOf="#+id/cellC2"
app:layout_constraintEnd_toStartOf="#+id/cellB3"
app:layout_constraintStart_toEndOf="#+id/cellB1"
app:layout_constraintTop_toBottomOf="#+id/cellA2" />
<View
android:id="#+id/cellB3"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#009688"
app:layout_constraintBottom_toTopOf="#+id/cellC3"
app:layout_constraintEnd_toStartOf="#+id/cellB4"
app:layout_constraintStart_toEndOf="#+id/cellB2"
app:layout_constraintTop_toBottomOf="#+id/cellA3" />
<View
android:id="#+id/cellB4"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#CDDC39"
app:layout_constraintBottom_toTopOf="#+id/cellC4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/cellB3"
app:layout_constraintTop_toBottomOf="#+id/cellA4" />
<View
android:id="#+id/cellC1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#E91E63"
app:layout_constraintBottom_toTopOf="#+id/cellD1"
app:layout_constraintEnd_toStartOf="#+id/cellC2"
app:layout_constraintTop_toBottomOf="#+id/cellB1"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="#+id/cellC2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#3F51B5"
app:layout_constraintBottom_toTopOf="#+id/cellD2"
app:layout_constraintEnd_toStartOf="#+id/cellC3"
app:layout_constraintTop_toBottomOf="#+id/cellB2"
app:layout_constraintStart_toEndOf="#+id/cellC1" />
<View
android:id="#+id/cellC3"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#CDDC39"
app:layout_constraintBottom_toTopOf="#+id/cellD3"
app:layout_constraintEnd_toStartOf="#+id/cellC4"
app:layout_constraintStart_toEndOf="#+id/cellC2"
app:layout_constraintTop_toBottomOf="#+id/cellB3" />
<View
android:id="#+id/cellC4"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#2196F3"
app:layout_constraintBottom_toTopOf="#+id/cellD4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/cellC3"
app:layout_constraintTop_toBottomOf="#+id/cellB4" />
<View
android:id="#+id/cellD1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#00BCD4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/cellD2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/cellC1" />
<View
android:id="#+id/cellD2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#673AB7"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/cellD3"
app:layout_constraintStart_toEndOf="#+id/cellD1"
app:layout_constraintTop_toBottomOf="#+id/cellC2" />
<View
android:id="#+id/cellD3"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#FF9800"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/cellD4"
app:layout_constraintStart_toEndOf="#+id/cellD2"
app:layout_constraintTop_toBottomOf="#+id/cellC3" />
<View
android:id="#+id/cellD4"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#E91E63"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/cellD3"
app:layout_constraintTop_toBottomOf="#+id/cellC4" />
</androidx.constraintlayout.widget.ConstraintLayout>
ah Ok .. I finally had a Eureka moment .. and thanks to this question
ConstraintLayout aspect ratio
helped me understand what I was doing wrong with the layout_constraintDimensionRatio
used this code:
<?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:background="#515151"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#4CAF50"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/frLay01"
app:layout_constraintStart_toStartOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="1"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="2"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
</LinearLayout>
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#2196F3"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="#+id/frLay01"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="1"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView12"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:layout_weight="2"
app:cardCornerRadius="8dp">
<TextView
android:id="#+id/textView13"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
</LinearLayout>
<androidx.cardview.widget.CardView
android:id="#+id/cardView"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_margin="6dp"
app:cardCornerRadius="8dp"
app:cardElevation="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/frLay01">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:text="TextView" />
</androidx.cardview.widget.CardView>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginEnd="40dp"
android:text="Button"
android:textColor="#FFFFFF"
app:backgroundTint="#0920A3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="#+id/frLay01"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:background="#8A1F1F"
app:layout_constraintBottom_toTopOf="#+id/linearLayout2"
app:layout_constraintDimensionRatio="W,4:3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearLayout">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:background="#3F51B5">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageButton
android:id="#+id/imageButton00"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton01"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton02"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton03"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageButton
android:id="#+id/imageButton10"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton11"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton12"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton13"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageButton
android:id="#+id/imageButton20"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton21"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton22"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
<ImageButton
android:id="#+id/imageButton23"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:srcCompat="#android:drawable/checkbox_off_background" />
</TableRow>
</TableLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Nothing in MainActivity
Key points:
the parent FrameLayout (named: frLay01 ) set constraints:
Left: parent
Top: bottom of top status bar
Bottom: top of bottom status bar
layout_constraintDimensionRatio="W,4:3"
and both:
android:layout_width="0dp"
android:layout_height="0dp"
My first mistake was setting layout_width to "wrap content" .. I didn't realize that the DimensionRatio is considered a constraint, so for it to take effect, we need to set the width to "match constraint" (ie 0dp)
only other trick (which I had already figured out previously)
is to set every child object inside, (and continuing in) to match parent.
and then finally, for the tableRows, set the layout_weight = 1
and of course, the image Buttons, layout_weight = 1 as well.
Once that's done .. viola:
and likewise, if I just add a 5th col of buttons, and change ratio to 5:3 ..
this is good for me .. as I indicated, my board is static size, so just after the auto resizing to the different screen sizes.

Hopefully a simple Kotlin regarding looping through a recycler

I have a recycler in my activity for acrostic poetry. The recycler displays an image of the letters of the word (Stone Age, in this case) and an EditText to enter the acrostic words. What I want to do is read the words that have been entered, so for "Stone Age" I'm creating 8 items in the recycler.
In order to get the words, I have tried to replicate the steps in this question How to iterate over RecyclerView items. I think I'm close, but I can't quite get over the line.
I have this function where I am trying to read the values (at this stage just into the logcat)
I figured that getChildCount returned the items, but this is logging 2 (or sometimes, oddly, 3) rather than the 8 I would expect, so I'm struggling to understand what I am looping.
private fun saveTask() {
var p: String = ""
Log.d(HWG.TAG, "Children: ${acrosticRecycler.getChildCount().toString()}")
for (i in 0 until acrosticRecycler.getChildCount()) {
var holder: AcrosticAdapter.ViewHolder
if(acrosticRecycler.findViewHolderForAdapterPosition(i) != null) {
holder = acrosticRecycler.findViewHolderForAdapterPosition(i) as AcrosticAdapter.ViewHolder
p = holder.txtWord.text.toString()
Log.d(HWG.TAG, "Word: ${p}")
}
}
}
This is the layout of the recycler
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
app:cardCornerRadius="4dp"
app:cardElevation="6dp">
<LinearLayout
android:id="#+id/llTaskList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<ImageView
android:id="#+id/imgLetter"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:adjustViewBounds="true"
android:cropToPadding="true"
android:scaleType="centerCrop"
app:srcCompat="#drawable/icons8_s" />
<EditText
android:id="#+id/txtWord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:hint="Stone Age"
android:textAllCaps="true"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
This is the activity in which the recycler sits
<?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:background="#color/background"
tools:context=".TextualTask">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:background="#color/background"
app:cardCornerRadius="4dp"
app:cardElevation="6dp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="24dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<ImageView
android:id="#+id/subjectImage"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:cropToPadding="true"
android:scaleType="centerCrop"
app:srcCompat="#drawable/icons8_knowledge_sharing_80" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="#+id/txtTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_marginLeft="15dp"
android:text="Acrostic Poem"
android:textAllCaps="true"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_margin="6dp"
android:background="?android:attr/listDivider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<TextView
android:id="#+id/txtPreamble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="15dp"
android:text="Preamble text"
android:textAlignment="center"
android:textSize="14sp"
android:textStyle="bold|italic" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<androidx.cardview.widget.CardView
android:id="#+id/crdWord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
app:cardBackgroundColor="#color/cardback"
app:cardCornerRadius="4dp"
app:cardElevation="6dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<Button
android:id="#+id/btnSubmit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:backgroundTint="#color/start"
android:text="Submit" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/acrosticRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:itemCount="5"
tools:listitem="#layout/acrostic_task" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Oddly enough, sometime the for loop gets the values from items 0-2, but sometimes it doesn't. The call to saveTask is made from btnSubmit as I don't need to get the values at the point the user enters them, just when they're happy to submit.
Could someone point me in the right direction please?
You can't get the correct count from acrosticRecycler.getChildCount().
because acrosticRecycler.getChildCount() will return the count of currently showed item in the RecyclerView. So even if your data is 8, but the showed data in the screen is only 3 items. So you will always get 3 not 8.
It's not good practice to get the data from the ViewHolder in recycler view directly. You should get the data from the list you have inserted to recycler view adapter.
for example, you can create adapter like this :
class AcrosticAdapter(var listData: ArrayList<AcrosticPoetry>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun getItemCount(): Int = listData.size
}
//assuming this is your model class
class AcrosticPoetry() {
var textWord = ""
}
and you can change your code to
private fun saveTask() {
val adapter = acrosticRecycler.adapter as AcrosticAdapter
val data = adapter.listData
for (i in 0 until data.size) {
val word = data[i].txtWord
Log.d(HWG.TAG, "Word: ${word}")
}
}

The addOnScrollListener for my RecyclerView not working as expected

I want to know when I am at the bottom of my recycler view but I can't get why the recyclerView.canScrollVertically(1) is always returning true even if I am at the bottom of the Recycler View.
The recycler view is inside a CoordinatorLayout with an AppBarLayout.
You have the Kotlin code and the XML code for the bigger picture
Thank you.
getDataBinding().shipmentRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
Log.e(TAG,
"onScrollStateChanged 1: This is the bottom shipmentRecyclerView $newState <> ${RecyclerView.SCROLL_STATE_IDLE} ${
recyclerView.canScrollVertically(1)
}")
if (!getDataBinding().shipmentRecyclerView.canScrollVertically(1) && newState == RecyclerView.SCROLL_STATE_IDLE) {
Log.e(TAG, "onScrollStateChanged 2: This is the bottom shipmentRecyclerView")
if (viewModel.currentPage.get()!! < viewModel.totalPages.get()!!) {
viewModel.getShipmentByPage(
viewModel.currentPage.get()!! + 1,
viewModel.request.get()
)
}
}
}
})
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.technifyit.jibheli.presentation.main.fragment.search.SearchViewModel" />
</data>
<com.sothree.slidinguppanel.SlidingUpPanelLayout
android:id="#+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
app:umanoPanelHeight="0dp"
app:umanoShadowHeight="#dimen/margin_4dp"
tools:context=".presentation.main.fragment.search.SearchFragment">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/shipment_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/margin_12dp"
android:clipToPadding="true"
android:fastScrollEnabled="true"
app:layout_anchor="#id/app_bar_layout"
app:layout_anchorGravity="bottom"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:shipment_adapter="#{viewModel}" />
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/dark_color_purple"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
...........
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/dark_color_purple"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:visibility="gone"
app:contentInsetStart="0dp"
app:layout_anchor="#id/app_bar_layout"
app:layout_anchorGravity="bottom"
app:layout_collapseMode="pin"
app:theme="#style/ThemeOverlay.AppCompat.Dark"
app:title="">
.........
</androidx.appcompat.widget.Toolbar>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/custom_web_page_browser"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/margin_40dp"
android:background="#drawable/background_rounded_top"
android:backgroundTint="#color/grey_clair">
<com.technifyit.jibheli.presentation.customView.MontserratBoldTextView
android:id="#+id/url_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_20dp"
android:layout_marginEnd="#dimen/margin_6dp"
android:text="#string/activity_item_details_send_request_button_text"
android:textColor="#color/dark_color_purple"
android:textSize="#dimen/title_size_sign_up"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#id/close"
app:layout_constraintEnd_toStartOf="#id/use_link_image_view"
app:layout_constraintStart_toEndOf="#id/close"
app:layout_constraintTop_toTopOf="#id/close" />
<ImageView
android:id="#+id/close"
android:layout_width="#dimen/icon_24dp"
android:layout_height="#dimen/icon_24dp"
android:layout_margin="#dimen/margin_6dp"
android:background="#drawable/ic_close_gold"
android:backgroundTint="#color/dark_color_purple"
android:padding="#dimen/margin_4dp"
android:src="#drawable/ic_close_native"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="#color/white" />
<com.technifyit.jibheli.presentation.customView.MontserratBoldTextView
android:id="#+id/use_link_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/margin_6dp"
android:background="#drawable/button_rounded_left_only_no_icon"
android:backgroundTint="#color/dark_color_purple"
android:drawableEnd="#drawable/ic_check_native"
android:drawablePadding="#dimen/margin_6dp"
android:gravity="center"
android:paddingStart="#dimen/margin_8dp"
android:paddingEnd="#dimen/margin_8dp"
android:text="#string/select"
android:textAllCaps="false"
android:textColor="#color/white"
app:drawableTint="#color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="#dimen/margin_4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/close">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="#+id/no_item_found_suggested_layout"
layout="#layout/no_item_found_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/requested_shipments_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_6dp"
android:fastScrollEnabled="true"
app:layout_constraintTop_toTopOf="parent"
app:requested_shipment_adapter="#{viewModel}" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/requested_trip_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_6dp"
android:fastScrollEnabled="true"
app:layout_constraintTop_toTopOf="parent"
app:requested_trip_adapter="#{viewModel}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
</layout>
Thank you for your response, i did find a solution by adding to my recycler view in xml
addOnScrolledToBottomListener="#{viewModel}" and then in the bindingAdapter
#BindingAdapter("addOnScrolledToBottomListener")
fun addOnScrolledToBottomListener(recyclerView: RecyclerView, viewModel: SearchViewModel) {
recyclerView.addOnScrollListener(object :
RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (recyclerView.canScrollVertically(1) && newState == RecyclerView.SCROLL_STATE_IDLE) {
if (viewModel.currentPage.get()!! < viewModel.totalPages.get()!!) {
viewModel.getShipmentByPage(
viewModel.currentPage.get()!! + 1,
viewModel.request.get()
)
}
}
}
})
}`
and like that it worked like a charm, Thank you #xinaiz for your help

GridView cannot be cast to ViewPager in Kotlin Custom Calendar

Working on the custom calendar in Kotlin.
On tapping the DateText, this custom calendar widget will be opened in a new fragment.
I used Grid Views to display the dates and I'm getting ClassCastException on navigating to the Calendar Screen(GridView cannot be cast to ViewPager).
Error:
Caused by: java.lang.ClassCastException: com.daimler.myfinance.payment.paymentdate.extensions.CalendarGridView cannot be cast to com.daimler.myfinance.payment.paymentdate.extensions.CalendarViewPager
at com.payment.paymentdate.CalendarView.initUiElements(CalendarView.kt)
CalendarView.kt
open class CalendarView : LinearLayout {
private var mViewPager: CalendarViewPager? = null
private fun initUiElements() {
mViewPager = findViewById<ViewPager>(R.id.calendarViewPager) as CalendarViewPager
}
}
CalendarViewPager.kt
class CalendarViewPager : ViewPager {
constructor(context: Context?) : super(context!!) {
}
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs) {
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var heightMeasureSpec = heightMeasureSpec
var height = 0
for (i in 0 until getChildCount()) {
val child: View = getChildAt(i)
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
val h = child.measuredHeight
if (h > height) {
height = h
}
}
if (height != 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
calendar_view.xml
<?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="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:orientation="vertical">
<!-- date toolbar -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/calendarHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#color/jumio_white"
app:layout_constraintBottom_toTopOf="#+id/abbreviationsBar">
<ImageButton
android:id="#+id/previousButton"
style="#style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="30dp"
android:layout_height="match_parent"
android:src="#drawable/ic_chevron_left"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.uikit.widgets.textviews.MBBody2TextView
android:id="#+id/currentDateLabel"
android:layout_width="wrap_content"
android:layout_height="56dp"
android:gravity="center"
android:textColor="#color/jumio_black"
android:textSize="18sp"
app:layout_constraintLeft_toRightOf="#id/previousButton"
app:layout_constraintRight_toLeftOf="#id/forwardButton"
app:layout_constraintTop_toTopOf="parent"
android:text="April 2020" />
<ImageButton
android:id="#+id/forwardButton"
style="#style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="30dp"
android:layout_height="match_parent"
android:src="#drawable/ic_chevron_right"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- eventDays header -->
<LinearLayout
android:id="#+id/abbreviationsBar"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="#+id/calendarHeader">
<com.\uikit.widgets.textviews.MBBody2TextView
android:id="#+id/mondayLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/material_calendar_monday"
android:textColor="#color/jumio_black" />
<com.uikit.widgets.textviews.MBBody2TextView
android:id="#+id/tuesdayLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/material_calendar_tuesday"
android:textColor="#color/jumio_black" />
<com.uikit.widgets.textviews.MBBody2TextView
android:id="#+id/wednesdayLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/material_calendar_wednesday"
android:textColor="#color/jumio_black" />
<com.uikit.widgets.textviews.MBBody2TextView
android:id="#+id/thursdayLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/material_calendar_thursday"
android:textColor="#color/jumio_black" />
<com.uikit.widgets.textviews.MBBody2TextView
android:id="#+id/fridayLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/material_calendar_friday"
android:textColor="#color/jumio_black" />
<com.uikit.widgets.textviews.MBBody2TextView
android:id="#+id/saturdayLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/material_calendar_saturday"
android:textColor="#color/jumio_black" />
<com.uikit.widgets.textviews.MBBody2TextView
android:id="#+id/sundayLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/material_calendar_sunday"
android:textColor="#color/jumio_black" />
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/gridScroll"
app:layout_constraintTop_toBottomOf="#+id/abbreviationsBar">
<com.payment.paymentdate.extensions.CalendarGridView
android:id="#+id/calendarViewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
Because in your xml you have defined com.payment.paymentdate.extensions.CalendarGridView which is subclassof GridView and you are assigning it to ViewPager wich is type of ViewPager
<com.payment.paymentdate.extensions.CalendarViewPager
android:id="#+id/calendarViewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

why my submodel cannot be cast to java.util.ArrayList

I'm making a recyclerview with multilevel data, and there is a problem when entering data into the sub-adapter. appear error like this "model cannot be cast to java.util.ArrayList android"
my json
[{
"header" : "buah air",
"sub" : {
"warna" : "merah",
"jenis" : "air"
}
},{
"header" : "buah serat",
"sub" : {
"warna" : "hijau",
"jenis" : "serat"
}
}]
my model
data class mTOP (
val header : String,
#SerializedName("sub") val sub : mSubTOP
)
data class mSubTOP(
val warna : String,
val jenis : String
)
my MainActivity
val adapter = adapter_top(response!!.body() as ArrayList<mTOP>)
rv.adapter = adapter
my adapter_top (here an error occurs)
override fun onBindViewHolder(holder: adapter_top.ViewHolder, position: Int) {
holder.tvHeader?.text = Datane[position].header
holder.rvList?.layoutManager = LinearLayoutManager(holder.rvList.context, LinearLayout.VERTICAL, false)
var adapterSub = adapter_sub(Datane[position].sub as ArrayList<mSubTOP>)
holder.rvList?.adapter = adapterSub
}
my adapter_sub
class adapter_sub(val Datane: ArrayList<mSubTOP>): RecyclerView.Adapter<adapter_sub.ViewHolder>() {
}
Because it's not ArrayList at all :) You have to create a list with one element:
adapter_sub(arrayListOf(Datane[position].sub))
this complete my adapter_sub
class adapter_sub(val Datane: ArrayList<mSubTOP>): RecyclerView.Adapter<adapter_sub.ViewHolder>() {
override fun onBindViewHolder(holder: adapter_sub.ViewHolder, position: Int) {
val location = Datane[position]
holder.tvName?.text = location.warna
holder.tvHobi?.text = location.jenis
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): adapter_sub.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.layout_sub, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return Datane.size
}
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val tvName = itemView.findViewById<TextView>(R.id.tvJenis)
val tvHobi = itemView.findViewById<TextView>(R.id.tvWarna)
}
}
layout activity_main.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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/RvMain"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp" >
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
layout layout_top.xml
<?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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:gravity="center_vertical"
android:text="Date"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Large"
android:textColor="#009688"
android:textSize="18sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
layout layout_sub.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/locationBadge"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#drawable/circle_badge"
android:gravity="center_vertical|center_horizontal"
android:text="✓"
android:textColor="#fff"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/tvWarna"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="Name"
android:textSize="18sp" />
<TextView
android:id="#+id/tvJenis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="Address"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
this my stack trace
10-20 06:24:08.445 11624-11624/br.com.mirabilis.jambu_air E/AndroidRuntime: FATAL EXCEPTION: main
Process: br.com.mirabilis.jambu_air, PID: 11624
android.view.InflateException: Binary XML file line #14: Binary XML file line #14: Error inflating class TextView
at android.view.LayoutInflater.inflate(LayoutInflater.java:543)
at android.view.LayoutInflater.inflate(LayoutInflater.java:427)
at br.com.mirabilis.jambu_air.adapter.adapter_sub.onCreateViewHolder(adapter_sub.kt:23)
at br.com.mirabilis.jambu_air.adapter.adapter_sub.onCreateViewHolder(adapter_sub.kt:13)
at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6794)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5975)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3336)
at android.view.View.measure(View.java:18811)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5952)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
at android.view.View.measure(View.java:18811)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5952)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at androidx.cardview.widget.CardView.onMeasure(CardView.java:260)
at android.view.View.measure(View.java:18811)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5952)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
at android.view.View.measure(View.java:18811)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:9119)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1583)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4194)
at android.view.View.layout(View.java:16653)
at android.view.ViewGroup.layout(ViewGroup.java:5438)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
at android.view.View.layout(View.java:16653)
at android.view.ViewGroup.layout(ViewGroup.java:5438)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16653)
at android.view.ViewGroup.layout(ViewGroup.java:5438)
at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:444)
at android.view.View.layout(View.java:16653)
at android.view.ViewGroup.layout(ViewGroup.java:5438)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16653)
at android.view.ViewGroup.layout(ViewGroup.java:5438)
at android.widget.LinearLayout.setCh
10-20 06:24:08.448 11624-11624/br.com.mirabilis.jambu_air E/MQSEventManagerDelegate: failed to get MQSService.
10-20 06:24:08.473 11624-11624/br.com.mirabilis.jambu_air I/Process: Sending signal. PID: 11624 SIG: 9