androidandroid-recyclerviewandroid-scrollview

Android Recyclerview snaps back to item


If I scroll through my recyclerview I can't look at the end of an item and the start at the same time.. it always snaps back to an item to be in the center if I let go... I want to scroll freely through the recyclerview without being send back to some item... how can I stop that?

-- XML layout

<?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="#ffffff"
    tools:context=".activities.ViewNewsSubDiv">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <FrameLayout
            android:id="@+id/title_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:orientation="horizontal">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#ffffff"
                    android:fontFamily="@font/cairo"
                    android:text="Schüler"
                    android:textAlignment="viewEnd"
                    android:textColor="#000000"
                    android:textSize="24sp"
                    android:textStyle="bold" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#ffffff"
                    android:fontFamily="@font/cairo"
                    android:text="Blick"
                    android:textAlignment="gravity"
                    android:textColor="#000000"
                    android:textSize="24sp" />
            </LinearLayout>

            <ImageButton
                android:id="@+id/title_bar_back"
                android:layout_width="85dp"
                android:layout_height="52dp"
                android:background="#ffffffff"
                android:scaleType="fitCenter"
                android:src="@drawable/back"
                app:tint="#000000" />

        </FrameLayout>

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:id="@+id/subview_progress_bar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#00000000"
                android:clickable="true"
                android:focusable="true"
                android:gravity="center"
                android:orientation="vertical">

                <ProgressBar
                    style="?android:attr/progressBarStyle"
                    android:layout_width="225dp"
                    android:layout_height="225dp"
                    android:layout_gravity="center"
                    android:indeterminateTint="#7C7C7C" />

                <TextView
                    android:id="@+id/subview_progress_bar_textview"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="0/100%"
                    android:textColor="#7C7C7C"
                    android:textSize="15pt" />

            </LinearLayout>

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/pdfContent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scrollbars="none"
                android:nestedScrollingEnabled="true"/>

        </FrameLayout>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

-- kotlin code

package com.example.schuelerblick.activities

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.util.Log
import android.widget.ImageButton
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.schuelerblick.R
import com.example.schuelerblick.StartActivity
import android.view.View
import android.view.WindowManager
import android.widget.AbsListView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.whenCreated
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.example.schuelerblick.adapter.PDFAdapter
import com.example.schuelerblick.viewmodel.PDFReaderViewModel
import com.example.schuelerblick.viewmodel.PDFReaderViewModelState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

@Suppress("DEPRECATION")
class ViewNewsSubDiv : AppCompatActivity() {

    private val viewModel by viewModels<PDFReaderViewModel>()

    private val pdfContent: RecyclerView by lazy {
        findViewById(R.id.pdfContent)
    }



    private val progressBar: LinearLayout by lazy {
        findViewById(R.id.subview_progress_bar)
    }

    private val progressBarTextView: TextView by lazy {
        findViewById(R.id.subview_progress_bar_textview)
    }

    private lateinit var adapter: PDFAdapter

    private val totalPDFBitmapList = mutableListOf<Bitmap>()

    private var currentIndex = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.news_subview)

        val backButton = findViewById<ImageButton>(R.id.title_bar_back)

        val pdfContent = findViewById<RecyclerView>(R.id.pdfContent)

        fun setValuesToViews() {

            viewModel.pdf(this, intent.getStringExtra("pdf").toString())

            initFlow()
            initList()

        }

        setValuesToViews()

        backButton.setOnClickListener {
            val intent = Intent(this, StartActivity::class.java)
            startActivity(intent)

        }
    }

    private fun initFlow() {
        lifecycleScope.launch(Dispatchers.Main) {
            whenCreated {
                viewModel.pdfReaderViewModelState.collect {
                    when (it) {
                        is PDFReaderViewModelState.OnPDFFile -> {
                            Log.d("PDFReader.OnPDFFile", "pdf file ${it.file.length()}")
                            hideProgress()

                            viewModel.bitmaps(it.file, getScreenWidth(this@ViewNewsSubDiv))
                        }

                        is PDFReaderViewModelState.OnBitmaps -> {

                            hideProgress()

                            totalPDFBitmapList.clear()
                            totalPDFBitmapList.addAll(it.list)

                            reload()

                        }

                        is PDFReaderViewModelState.Error -> {
                            Toast.makeText(this@ViewNewsSubDiv, "error - ${it.message}", Toast.LENGTH_SHORT).show()
                            hideProgress()
                        }

                        is PDFReaderViewModelState.Empty -> {
                            Toast.makeText(this@ViewNewsSubDiv, "error - empty", Toast.LENGTH_SHORT).show()
                            hideProgress()
                        }
                        is PDFReaderViewModelState.Loading -> {
                            showProgress()
                        }
                        is PDFReaderViewModelState.Progress -> {
                            progressBarTextView.post{
                                progressBarTextView.text = if ( it.progress != 0) {
                                    "${it.progress}/100%"
                                }
                                else {
                                    ""
                                }
                            }
                        }
                        is PDFReaderViewModelState.None -> Unit

                    }
                }
            }
        }
    }

    private fun initList() {

        pdfContent.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)

        adapter = PDFAdapter {
            loadMore()
        }

        pdfContent.adapter = adapter

        pdfContent.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)

                if (newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {

                    currentIndex = (recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()

                    // current page
                }
            }
        })

        PagerSnapHelper().attachToRecyclerView(pdfContent)

    }

    private fun reload() {
        pdfContent.post{
            adapter.reload(fetchData(0, 1))

        }
    }

    private fun loadMore() {
        pdfContent.post{
            adapter.loadMore(fetchData(adapter.itemCount, 3))
        }
    }

    private fun fetchData(offset: Int, limit: Int): List<Bitmap> {
        val list = mutableListOf<Bitmap>()

        for (i in offset until offset + limit) {
            if ( i > totalPDFBitmapList.size - 1){
                break
            }
            list.add(totalPDFBitmapList[i])
        }

        return list
    }

    private fun getScreenWidth(context: Context): Int {
        val outMetrics = DisplayMetrics()

        if (Build.VERSION.SDK_INT >= Build. VERSION_CODES.R) {
            val display = context.display
            display?.getRealMetrics(outMetrics)
        }
        else {
            val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
            display.getMetrics(outMetrics)
        }

        return outMetrics.widthPixels
    }

    private fun showProgress() {
        progressBar.visibility = View.VISIBLE
    }

    private fun hideProgress() {
        progressBar.visibility = View.GONE
    }
}

Solution

  • works now!

    item snapping was enabled...