kandi background
Explore Kits

RecyclerViewPager | A ViewPager implemention base on RecyclerView | RecyclerView library

 by   lsjwzh Java Version: v1.2.0 License: Apache-2.0

 by   lsjwzh Java Version: v1.2.0 License: Apache-2.0

Download this library from

kandi X-RAY | RecyclerViewPager Summary

RecyclerViewPager is a Java library typically used in User Interface, RecyclerView applications. RecyclerViewPager has no vulnerabilities, it has build file available, it has a Permissive License and it has medium support. However RecyclerViewPager has 3 bugs. You can download it from GitHub, Maven.
A ViewPager implemention base on RecyclerView. Support fling operation like gallary.
Support
Support
Quality
Quality
Security
Security
License
License
Reuse
Reuse

kandi-support Support

  • RecyclerViewPager has a medium active ecosystem.
  • It has 3529 star(s) with 680 fork(s). There are 92 watchers for this library.
  • It had no major release in the last 12 months.
  • There are 121 open issues and 69 have been closed. On average issues are closed in 119 days. There are 3 open pull requests and 0 closed requests.
  • It has a neutral sentiment in the developer community.
  • The latest version of RecyclerViewPager is v1.2.0
RecyclerViewPager Support
Best in #RecyclerView
Average in #RecyclerView
RecyclerViewPager Support
Best in #RecyclerView
Average in #RecyclerView

quality kandi Quality

  • RecyclerViewPager has 3 bugs (0 blocker, 1 critical, 0 major, 2 minor) and 76 code smells.
RecyclerViewPager Quality
Best in #RecyclerView
Average in #RecyclerView
RecyclerViewPager Quality
Best in #RecyclerView
Average in #RecyclerView

securitySecurity

  • RecyclerViewPager has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
  • RecyclerViewPager code analysis shows 0 unresolved vulnerabilities.
  • There are 5 security hotspots that need review.
RecyclerViewPager Security
Best in #RecyclerView
Average in #RecyclerView
RecyclerViewPager Security
Best in #RecyclerView
Average in #RecyclerView

license License

  • RecyclerViewPager is licensed under the Apache-2.0 License. This license is Permissive.
  • Permissive licenses have the least restrictions, and you can use them in most projects.
RecyclerViewPager License
Best in #RecyclerView
Average in #RecyclerView
RecyclerViewPager License
Best in #RecyclerView
Average in #RecyclerView

buildReuse

  • RecyclerViewPager releases are available to install and integrate.
  • Deployable package is available in Maven.
  • Build file is available. You can build the component from source.
  • Installation instructions are not available. Examples and code snippets are available.
  • RecyclerViewPager saves you 1252 person hours of effort in developing the same functionality from scratch.
  • It has 2816 lines of code, 190 functions and 51 files.
  • It has medium code complexity. Code complexity directly impacts maintainability of the code.
RecyclerViewPager Reuse
Best in #RecyclerView
Average in #RecyclerView
RecyclerViewPager Reuse
Best in #RecyclerView
Average in #RecyclerView
Top functions reviewed by kandi - BETA

kandi has reviewed RecyclerViewPager and discovered the below as its top functions. This is intended to give you an instant insight into RecyclerViewPager implemented functionality, and help decide if they suit your requirements.

  • Set the current scroll state .
  • Set up the RecyclerView .
  • Initialize viewpager
  • Transforms an inner position to an inner position .
  • Invoked when a view is recycled .
  • On create view .
  • Setup a new tab layout with a view .
  • Returns the offsets of the items in the RecyclerView .
  • Get a random drawable name .
  • Checks if child view is inside center y

RecyclerViewPager Key Features

Deprecated

how to import?

copy iconCopydownload iconDownload
// Yes, I have switched to jitpack.io.

repositories {
    ...
    maven { url "https://jitpack.io" }
    ...
}

dependencies {
    ...
    compile 'com.github.lsjwzh.RecyclerViewPager:lib:v1.2.0@aar'
    ...
}

Basic Usage:

copy iconCopydownload iconDownload
<com.lsjwzh.widget.recyclerviewpager.RecyclerViewPager
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="15dp"
    android:paddingRight="15dp"
    app:rvp_triggerOffset="0.1"
    app:rvp_singlePageFling="true"
    android:clipToPadding="false"/>

Support TabLayout:

copy iconCopydownload iconDownload
dependencies {
    ...
    compile 'com.github.lsjwzh.RecyclerViewPager:tablayoutsupport:v1.1.2@aar'
    ...
}

Infinite Loop ViewPager:

copy iconCopydownload iconDownload
<com.lsjwzh.widget.recyclerviewpager.LoopRecyclerViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="20dp"
        android:clipToPadding="false"
        android:paddingTop="15dp"
        android:paddingBottom="15dp"/>

Release Notes:

copy iconCopydownload iconDownload
1.2.0 update support lib to 26.0.2
1.1.2 merge some fix.
1.1.1 merge some fix.
1.1.0stable fix bug:LoopViewPager position confusion;LoopViewPager non stop spinning;
1.1.0beta5 feat: TabLayoutSupport Lib supports LoopViewPager
1.1.0beta4 fix bug:support ItemDecorations;
1.1.0beta3 support reverse;
1.1.0 refactor;support TabLayout;
1.0.11 support infinite loop
1.0.10 make touch gesture smother;
1.0.8 override swapAdapter;support singlePageFling;
1.0.7 remove redandunt codes; support cancel action
1.0.6 resolve potential id conflicting on FragmentViewPagerApdater
1.0.4 fix bug : exception happens if  ItemView LayoutParam is not MarginLayoutParam
1.0.3 add method: getCurrentPosition
1.0.2 support FragmentViewPager, add OnPageChangedListener
1.0.1 fix bug: smoothScrollToPosition index out of range
1.0.0 reimplement RecyclerViewPager without coping RecyclerView's codes.

0.5.4 add 'HorizontalCenterLayoutManager' to implement ViewPager
0.5.3 fix bug: setHasStableIds not work
0.1.0

License

copy iconCopydownload iconDownload
Copyright 2015 lsjwzh

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Could not find multidex.jar (com.android.support:multidex:1.0.2)

copy iconCopydownload iconDownload
apply from: 'buildsystem/dependencies.gradle'

buildscript {
   repositories {
      jcenter()
      mavenCentral()
      maven { url 'https://maven.fabric.io/public' }
      google()
      //maven {
      //    url 'https://maven.google.com'
      //}
    }
    dependencies {
       //Update it to the latest version: 3.1.3
       classpath 'com.android.tools.build:gradle:3.1.3' 
       classpath 'com.frogermcs.androiddevmetrics:androiddevmetrics-plugin:0.5'
       classpath 'com.google.gms:google-services:3.1.2'
       classpath 'io.fabric.tools:gradle:1.25.1'
    }
}

allprojects {
   ext {
     androidApplicationId = 'com.medikoe.connect'
     androidVersionCode = 23
     androidVersionName = "1.7.2"
     testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
     testApplicationId = 'com.medikoe.test'
   }

   repositories {
     google()
     jcenter()
   }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
// Remove these lines
// repositories {
//    google()
// }
-----------------------
repositories {
    maven {
            url 'https://maven.google.com'
        }
    jcenter()
    // Add your other repositories here
}
repositories {
    google()
    jcenter()
    // Add your other repositories here
}
-----------------------
repositories {
    maven {
            url 'https://maven.google.com'
        }
    jcenter()
    // Add your other repositories here
}
repositories {
    google()
    jcenter()
    // Add your other repositories here
}
-----------------------
 maven { url 'https://maven.google.com' }
jcenter()
-----------------------
 maven { url 'https://maven.google.com' }
jcenter()

How to implement RecyclerViewPager in kotlin?

copy iconCopydownload iconDownload
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager_2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator
        android:id="@+id/dots_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"/>

</LinearLayout>
class MainActivity : AppCompatActivity() {

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

        setupViewPager2()
    }

    private fun setupViewPager2() {
        val viewPager2 = findViewById<ViewPager2>(R.id.view_pager_2)
        val dotsIndicator = findViewById<WormDotsIndicator>(R.id.dots_indicator)

        viewPager2.adapter = PagerAdapter(this)
        dotsIndicator.setViewPager2(viewPager2)
    }
}
class PagerAdapter(fa:FragmentActivity): FragmentStateAdapter(fa) {

    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return when(position){
            0 -> SampleFragment.newInstance("One", "desc 1")
            1 -> SampleFragment.newInstance("Two", "desc 2")
            2 -> SampleFragment.newInstance("Three", "desc 3")
            else -> throw Exception("No such position")
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".SampleFragment">
    <TextView
        android:id="@+id/txt_header"
        tools:text="Header 1"
        android:textAlignment="center"
        android:textSize="24sp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/txt_desc"
        tools:text="Desc 1"
        android:textAlignment="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
class SampleFragment : Fragment() {

    private var header: String? = null
    private var desc: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            header = it.getString(ARG_Header)
            desc = it.getString(ARG_Desc)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_sample, container, false)
        setView(view)
        return view
    }

    private fun setView(view:View){
        val headerText = view.findViewById<TextView>(R.id.txt_header)
        headerText.text = header
        val descText = view.findViewById<TextView>(R.id.txt_desc)
        descText.text = desc

    }

    companion object {

        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            SampleFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_Header, param1)
                    putString(ARG_Desc, param2)
                }
            }
    }
}
-----------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager_2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator
        android:id="@+id/dots_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"/>

</LinearLayout>
class MainActivity : AppCompatActivity() {

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

        setupViewPager2()
    }

    private fun setupViewPager2() {
        val viewPager2 = findViewById<ViewPager2>(R.id.view_pager_2)
        val dotsIndicator = findViewById<WormDotsIndicator>(R.id.dots_indicator)

        viewPager2.adapter = PagerAdapter(this)
        dotsIndicator.setViewPager2(viewPager2)
    }
}
class PagerAdapter(fa:FragmentActivity): FragmentStateAdapter(fa) {

    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return when(position){
            0 -> SampleFragment.newInstance("One", "desc 1")
            1 -> SampleFragment.newInstance("Two", "desc 2")
            2 -> SampleFragment.newInstance("Three", "desc 3")
            else -> throw Exception("No such position")
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".SampleFragment">
    <TextView
        android:id="@+id/txt_header"
        tools:text="Header 1"
        android:textAlignment="center"
        android:textSize="24sp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/txt_desc"
        tools:text="Desc 1"
        android:textAlignment="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
class SampleFragment : Fragment() {

    private var header: String? = null
    private var desc: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            header = it.getString(ARG_Header)
            desc = it.getString(ARG_Desc)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_sample, container, false)
        setView(view)
        return view
    }

    private fun setView(view:View){
        val headerText = view.findViewById<TextView>(R.id.txt_header)
        headerText.text = header
        val descText = view.findViewById<TextView>(R.id.txt_desc)
        descText.text = desc

    }

    companion object {

        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            SampleFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_Header, param1)
                    putString(ARG_Desc, param2)
                }
            }
    }
}
-----------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager_2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator
        android:id="@+id/dots_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"/>

</LinearLayout>
class MainActivity : AppCompatActivity() {

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

        setupViewPager2()
    }

    private fun setupViewPager2() {
        val viewPager2 = findViewById<ViewPager2>(R.id.view_pager_2)
        val dotsIndicator = findViewById<WormDotsIndicator>(R.id.dots_indicator)

        viewPager2.adapter = PagerAdapter(this)
        dotsIndicator.setViewPager2(viewPager2)
    }
}
class PagerAdapter(fa:FragmentActivity): FragmentStateAdapter(fa) {

    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return when(position){
            0 -> SampleFragment.newInstance("One", "desc 1")
            1 -> SampleFragment.newInstance("Two", "desc 2")
            2 -> SampleFragment.newInstance("Three", "desc 3")
            else -> throw Exception("No such position")
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".SampleFragment">
    <TextView
        android:id="@+id/txt_header"
        tools:text="Header 1"
        android:textAlignment="center"
        android:textSize="24sp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/txt_desc"
        tools:text="Desc 1"
        android:textAlignment="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
class SampleFragment : Fragment() {

    private var header: String? = null
    private var desc: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            header = it.getString(ARG_Header)
            desc = it.getString(ARG_Desc)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_sample, container, false)
        setView(view)
        return view
    }

    private fun setView(view:View){
        val headerText = view.findViewById<TextView>(R.id.txt_header)
        headerText.text = header
        val descText = view.findViewById<TextView>(R.id.txt_desc)
        descText.text = desc

    }

    companion object {

        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            SampleFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_Header, param1)
                    putString(ARG_Desc, param2)
                }
            }
    }
}
-----------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager_2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator
        android:id="@+id/dots_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"/>

</LinearLayout>
class MainActivity : AppCompatActivity() {

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

        setupViewPager2()
    }

    private fun setupViewPager2() {
        val viewPager2 = findViewById<ViewPager2>(R.id.view_pager_2)
        val dotsIndicator = findViewById<WormDotsIndicator>(R.id.dots_indicator)

        viewPager2.adapter = PagerAdapter(this)
        dotsIndicator.setViewPager2(viewPager2)
    }
}
class PagerAdapter(fa:FragmentActivity): FragmentStateAdapter(fa) {

    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return when(position){
            0 -> SampleFragment.newInstance("One", "desc 1")
            1 -> SampleFragment.newInstance("Two", "desc 2")
            2 -> SampleFragment.newInstance("Three", "desc 3")
            else -> throw Exception("No such position")
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".SampleFragment">
    <TextView
        android:id="@+id/txt_header"
        tools:text="Header 1"
        android:textAlignment="center"
        android:textSize="24sp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/txt_desc"
        tools:text="Desc 1"
        android:textAlignment="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
class SampleFragment : Fragment() {

    private var header: String? = null
    private var desc: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            header = it.getString(ARG_Header)
            desc = it.getString(ARG_Desc)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_sample, container, false)
        setView(view)
        return view
    }

    private fun setView(view:View){
        val headerText = view.findViewById<TextView>(R.id.txt_header)
        headerText.text = header
        val descText = view.findViewById<TextView>(R.id.txt_desc)
        descText.text = desc

    }

    companion object {

        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            SampleFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_Header, param1)
                    putString(ARG_Desc, param2)
                }
            }
    }
}
-----------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager_2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator
        android:id="@+id/dots_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"/>

</LinearLayout>
class MainActivity : AppCompatActivity() {

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

        setupViewPager2()
    }

    private fun setupViewPager2() {
        val viewPager2 = findViewById<ViewPager2>(R.id.view_pager_2)
        val dotsIndicator = findViewById<WormDotsIndicator>(R.id.dots_indicator)

        viewPager2.adapter = PagerAdapter(this)
        dotsIndicator.setViewPager2(viewPager2)
    }
}
class PagerAdapter(fa:FragmentActivity): FragmentStateAdapter(fa) {

    override fun getItemCount(): Int = 3

    override fun createFragment(position: Int): Fragment {
        return when(position){
            0 -> SampleFragment.newInstance("One", "desc 1")
            1 -> SampleFragment.newInstance("Two", "desc 2")
            2 -> SampleFragment.newInstance("Three", "desc 3")
            else -> throw Exception("No such position")
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".SampleFragment">
    <TextView
        android:id="@+id/txt_header"
        tools:text="Header 1"
        android:textAlignment="center"
        android:textSize="24sp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/txt_desc"
        tools:text="Desc 1"
        android:textAlignment="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
class SampleFragment : Fragment() {

    private var header: String? = null
    private var desc: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            header = it.getString(ARG_Header)
            desc = it.getString(ARG_Desc)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_sample, container, false)
        setView(view)
        return view
    }

    private fun setView(view:View){
        val headerText = view.findViewById<TextView>(R.id.txt_header)
        headerText.text = header
        val descText = view.findViewById<TextView>(R.id.txt_desc)
        descText.text = desc

    }

    companion object {

        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            SampleFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_Header, param1)
                    putString(ARG_Desc, param2)
                }
            }
    }
}

How to snap RecyclerView items so that every X items would be considered like a single unit to snap to?

copy iconCopydownload iconDownload
// For LinearLayoutManager horizontal orientation
recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));

// For GridLayoutManager vertical orientation
recyclerView.setLayoutManager(new GridLayoutManager(this, SPAN_COUNT, RecyclerView.VERTICAL, false));
SnapToBlock snapToBlock = new SnapToBlock(mMaxFlingPages);
snapToBlock.attachToRecyclerView(recyclerView);
snapToBlock.setSnapBlockCallback(new SnapToBlock.SnapBlockCallback() {
    @Override
    public void onBlockSnap(int snapPosition) {
        ...
    }

    @Override
    public void onBlockSnapped(int snapPosition) {
        ...
    }
});
/*  The number of items in the RecyclerView should be a multiple of block size; otherwise, the
    extra item views will not be positioned on a block boundary when the end of the data is reached.
    Pad out with empty item views if needed.

    Updated to accommodate RTL layouts.
 */

public class SnapToBlock extends SnapHelper {
    private RecyclerView mRecyclerView;

    // Total number of items in a block of view in the RecyclerView
    private int mBlocksize;

    // Maximum number of positions to move on a fling.
    private int mMaxPositionsToMove;

    // Width of a RecyclerView item if orientation is horizonal; height of the item if vertical
    private int mItemDimension;

    // Maxim blocks to move during most vigorous fling.
    private final int mMaxFlingBlocks;

    // Callback interface when blocks are snapped.
    private SnapBlockCallback mSnapBlockCallback;

    // When snapping, used to determine direction of snap.
    private int mPriorFirstPosition = RecyclerView.NO_POSITION;

    // Our private scroller
    private Scroller mScroller;

    // Horizontal/vertical layout helper
    private OrientationHelper mOrientationHelper;

    // LTR/RTL helper
    private LayoutDirectionHelper mLayoutDirectionHelper;

    // Borrowed from ViewPager.java
    private static final Interpolator sInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            // _o(t) = t * t * ((tension + 1) * t + tension)
            // o(t) = _o(t - 1) + 1
            t -= 1.0f;
            return t * t * t + 1.0f;
        }
    };

    SnapToBlock(int maxFlingBlocks) {
        super();
        mMaxFlingBlocks = maxFlingBlocks;
    }

    @Override
    public void attachToRecyclerView(@Nullable final RecyclerView recyclerView)
        throws IllegalStateException {

        if (recyclerView != null) {
            mRecyclerView = recyclerView;
            final LinearLayoutManager layoutManager =
                (LinearLayoutManager) recyclerView.getLayoutManager();
            if (layoutManager.canScrollHorizontally()) {
                mOrientationHelper = OrientationHelper.createHorizontalHelper(layoutManager);
                mLayoutDirectionHelper =
                    new LayoutDirectionHelper(ViewCompat.getLayoutDirection(mRecyclerView));
            } else if (layoutManager.canScrollVertically()) {
                mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
                // RTL doesn't matter for vertical scrolling for this class.
                mLayoutDirectionHelper = new LayoutDirectionHelper(RecyclerView.LAYOUT_DIRECTION_LTR);
            } else {
                throw new IllegalStateException("RecyclerView must be scrollable");
            }
            mScroller = new Scroller(mRecyclerView.getContext(), sInterpolator);
            initItemDimensionIfNeeded(layoutManager);
        }
        super.attachToRecyclerView(recyclerView);
    }

    // Called when the target view is available and we need to know how much more
    // to scroll to get it lined up with the side of the RecyclerView.
    @NonNull
    @Override
    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,
                                              @NonNull View targetView) {
        int[] out = new int[2];

        if (layoutManager.canScrollHorizontally()) {
            out[0] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (layoutManager.canScrollVertically()) {
            out[1] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (mSnapBlockCallback != null) {
            if (out[0] == 0 && out[1] == 0) {
                mSnapBlockCallback.onBlockSnapped(layoutManager.getPosition(targetView));
            } else {
                mSnapBlockCallback.onBlockSnap(layoutManager.getPosition(targetView));
            }
        }
        return out;
    }

    // We are flinging and need to know where we are heading.
    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager,
                                      int velocityX, int velocityY) {
        LinearLayoutManager lm = (LinearLayoutManager) layoutManager;

        initItemDimensionIfNeeded(layoutManager);
        mScroller.fling(0, 0, velocityX, velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE,
                        Integer.MIN_VALUE, Integer.MAX_VALUE);

        if (velocityX != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalX(), mItemDimension);
        }

        if (velocityY != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalY(), mItemDimension);
        }

        return RecyclerView.NO_POSITION;
    }

    // We have scrolled to the neighborhood where we will snap. Determine the snap position.
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        // Snap to a view that is either 1) toward the bottom of the data and therefore on screen,
        // or, 2) toward the top of the data and may be off-screen.
        int snapPos = calcTargetPosition((LinearLayoutManager) layoutManager);
        View snapView = (snapPos == RecyclerView.NO_POSITION)
            ? null : layoutManager.findViewByPosition(snapPos);

        if (snapView == null) {
            Log.d(TAG, "<<<<findSnapView is returning null!");
        }
        Log.d(TAG, "<<<<findSnapView snapos=" + snapPos);
        return snapView;
    }

    // Does the heavy lifting for findSnapView.
    private int calcTargetPosition(LinearLayoutManager layoutManager) {
        int snapPos;
        int firstVisiblePos = layoutManager.findFirstVisibleItemPosition();

        if (firstVisiblePos == RecyclerView.NO_POSITION) {
            return RecyclerView.NO_POSITION;
        }
        initItemDimensionIfNeeded(layoutManager);
        if (firstVisiblePos >= mPriorFirstPosition) {
            // Scrolling toward bottom of data
            int firstCompletePosition = layoutManager.findFirstCompletelyVisibleItemPosition();
            if (firstCompletePosition != RecyclerView.NO_POSITION
                && firstCompletePosition % mBlocksize == 0) {
                snapPos = firstCompletePosition;
            } else {
                snapPos = roundDownToBlockSize(firstVisiblePos + mBlocksize);
            }
        } else {
            // Scrolling toward top of data
            snapPos = roundDownToBlockSize(firstVisiblePos);
            // Check to see if target view exists. If it doesn't, force a smooth scroll.
            // SnapHelper only snaps to existing views and will not scroll to a non-existant one.
            // If limiting fling to single block, then the following is not needed since the
            // views are likely to be in the RecyclerView pool.
            if (layoutManager.findViewByPosition(snapPos) == null) {
                int[] toScroll = mLayoutDirectionHelper.calculateDistanceToScroll(layoutManager, snapPos);
                mRecyclerView.smoothScrollBy(toScroll[0], toScroll[1], sInterpolator);
            }
        }
        mPriorFirstPosition = firstVisiblePos;

        return snapPos;
    }

    private void initItemDimensionIfNeeded(final RecyclerView.LayoutManager layoutManager) {
        if (mItemDimension != 0) {
            return;
        }

        View child;
        if ((child = layoutManager.getChildAt(0)) == null) {
            return;
        }

        if (layoutManager.canScrollHorizontally()) {
            mItemDimension = child.getWidth();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getWidth() / mItemDimension);
        } else if (layoutManager.canScrollVertically()) {
            mItemDimension = child.getHeight();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getHeight() / mItemDimension);
        }
        mMaxPositionsToMove = mBlocksize * mMaxFlingBlocks;
    }

    private int getSpanCount(RecyclerView.LayoutManager layoutManager) {
        return (layoutManager instanceof GridLayoutManager)
            ? ((GridLayoutManager) layoutManager).getSpanCount()
            : 1;
    }

    private int roundDownToBlockSize(int trialPosition) {
        return trialPosition - trialPosition % mBlocksize;
    }

    private int roundUpToBlockSize(int trialPosition) {
        return roundDownToBlockSize(trialPosition + mBlocksize - 1);
    }

    @Nullable
    protected LinearSmoothScroller createScroller(RecyclerView.LayoutManager layoutManager) {
        if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
            return null;
        }
        return new LinearSmoothScroller(mRecyclerView.getContext()) {
            @Override
            protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
                int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(),
                                                                   targetView);
                final int dx = snapDistances[0];
                final int dy = snapDistances[1];
                final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
                if (time > 0) {
                    action.update(dx, dy, time, sInterpolator);
                }
            }

            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
            }
        };
    }

    public void setSnapBlockCallback(@Nullable SnapBlockCallback callback) {
        mSnapBlockCallback = callback;
    }

    /*
        Helper class that handles calculations for LTR and RTL layouts.
     */
    private class LayoutDirectionHelper {

        // Is the layout an RTL one?
        private final boolean mIsRTL;

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        LayoutDirectionHelper(int direction) {
            mIsRTL = direction == View.LAYOUT_DIRECTION_RTL;
        }

        /*
            Calculate the amount of scroll needed to align the target view with the layout edge.
         */
        int getScrollToAlignView(View targetView) {
            return (mIsRTL)
                ? mOrientationHelper.getDecoratedEnd(targetView) - mRecyclerView.getWidth()
                : mOrientationHelper.getDecoratedStart(targetView);
        }

        /**
         * Calculate the distance to final snap position when the view corresponding to the snap
         * position is not currently available.
         *
         * @param layoutManager LinearLayoutManager or descendent class
         * @param targetPos     - Adapter position to snap to
         * @return int[2] {x-distance in pixels, y-distance in pixels}
         */
        int[] calculateDistanceToScroll(LinearLayoutManager layoutManager, int targetPos) {
            int[] out = new int[2];

            int firstVisiblePos;

            firstVisiblePos = layoutManager.findFirstVisibleItemPosition();
            if (layoutManager.canScrollHorizontally()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    if (mIsRTL) {
                        View lastView = layoutManager.findViewByPosition(layoutManager.findLastVisibleItemPosition());
                        out[0] = mOrientationHelper.getDecoratedEnd(lastView)
                            + (firstVisiblePos - targetPos) * mItemDimension;
                    } else {
                        View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                        out[0] = mOrientationHelper.getDecoratedStart(firstView)
                            - (firstVisiblePos - targetPos) * mItemDimension;
                    }
                }
            }
            if (layoutManager.canScrollVertically()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                    out[1] = firstView.getTop() - (firstVisiblePos - targetPos) * mItemDimension;
                }
            }

            return out;
        }

        /*
            Calculate the number of positions to move in the RecyclerView given a scroll amount
            and the size of the items to be scrolled. Return integral multiple of mBlockSize not
            equal to zero.
         */
        int getPositionsToMove(LinearLayoutManager llm, int scroll, int itemSize) {
            int positionsToMove;

            positionsToMove = roundUpToBlockSize(Math.abs(scroll) / itemSize);

            if (positionsToMove < mBlocksize) {
                // Must move at least one block
                positionsToMove = mBlocksize;
            } else if (positionsToMove > mMaxPositionsToMove) {
                // Clamp number of positions to move so we don't get wild flinging.
                positionsToMove = mMaxPositionsToMove;
            }

            if (scroll < 0) {
                positionsToMove *= -1;
            }
            if (mIsRTL) {
                positionsToMove *= -1;
            }

            if (mLayoutDirectionHelper.isDirectionToBottom(scroll < 0)) {
                // Scrolling toward the bottom of data.
                return roundDownToBlockSize(llm.findFirstVisibleItemPosition()) + positionsToMove;
            }
            // Scrolling toward the top of the data.
            return roundDownToBlockSize(llm.findLastVisibleItemPosition()) + positionsToMove;
        }

        boolean isDirectionToBottom(boolean velocityNegative) {
            //noinspection SimplifiableConditionalExpression
            return mIsRTL ? velocityNegative : !velocityNegative;
        }
    }

    public interface SnapBlockCallback {
        void onBlockSnap(int snapPosition);

        void onBlockSnapped(int snapPosition);

    }

    private static final float MILLISECONDS_PER_INCH = 100f;
    @SuppressWarnings("unused")
    private static final String TAG = "SnapToBlock";
}
-----------------------
// For LinearLayoutManager horizontal orientation
recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));

// For GridLayoutManager vertical orientation
recyclerView.setLayoutManager(new GridLayoutManager(this, SPAN_COUNT, RecyclerView.VERTICAL, false));
SnapToBlock snapToBlock = new SnapToBlock(mMaxFlingPages);
snapToBlock.attachToRecyclerView(recyclerView);
snapToBlock.setSnapBlockCallback(new SnapToBlock.SnapBlockCallback() {
    @Override
    public void onBlockSnap(int snapPosition) {
        ...
    }

    @Override
    public void onBlockSnapped(int snapPosition) {
        ...
    }
});
/*  The number of items in the RecyclerView should be a multiple of block size; otherwise, the
    extra item views will not be positioned on a block boundary when the end of the data is reached.
    Pad out with empty item views if needed.

    Updated to accommodate RTL layouts.
 */

public class SnapToBlock extends SnapHelper {
    private RecyclerView mRecyclerView;

    // Total number of items in a block of view in the RecyclerView
    private int mBlocksize;

    // Maximum number of positions to move on a fling.
    private int mMaxPositionsToMove;

    // Width of a RecyclerView item if orientation is horizonal; height of the item if vertical
    private int mItemDimension;

    // Maxim blocks to move during most vigorous fling.
    private final int mMaxFlingBlocks;

    // Callback interface when blocks are snapped.
    private SnapBlockCallback mSnapBlockCallback;

    // When snapping, used to determine direction of snap.
    private int mPriorFirstPosition = RecyclerView.NO_POSITION;

    // Our private scroller
    private Scroller mScroller;

    // Horizontal/vertical layout helper
    private OrientationHelper mOrientationHelper;

    // LTR/RTL helper
    private LayoutDirectionHelper mLayoutDirectionHelper;

    // Borrowed from ViewPager.java
    private static final Interpolator sInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            // _o(t) = t * t * ((tension + 1) * t + tension)
            // o(t) = _o(t - 1) + 1
            t -= 1.0f;
            return t * t * t + 1.0f;
        }
    };

    SnapToBlock(int maxFlingBlocks) {
        super();
        mMaxFlingBlocks = maxFlingBlocks;
    }

    @Override
    public void attachToRecyclerView(@Nullable final RecyclerView recyclerView)
        throws IllegalStateException {

        if (recyclerView != null) {
            mRecyclerView = recyclerView;
            final LinearLayoutManager layoutManager =
                (LinearLayoutManager) recyclerView.getLayoutManager();
            if (layoutManager.canScrollHorizontally()) {
                mOrientationHelper = OrientationHelper.createHorizontalHelper(layoutManager);
                mLayoutDirectionHelper =
                    new LayoutDirectionHelper(ViewCompat.getLayoutDirection(mRecyclerView));
            } else if (layoutManager.canScrollVertically()) {
                mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
                // RTL doesn't matter for vertical scrolling for this class.
                mLayoutDirectionHelper = new LayoutDirectionHelper(RecyclerView.LAYOUT_DIRECTION_LTR);
            } else {
                throw new IllegalStateException("RecyclerView must be scrollable");
            }
            mScroller = new Scroller(mRecyclerView.getContext(), sInterpolator);
            initItemDimensionIfNeeded(layoutManager);
        }
        super.attachToRecyclerView(recyclerView);
    }

    // Called when the target view is available and we need to know how much more
    // to scroll to get it lined up with the side of the RecyclerView.
    @NonNull
    @Override
    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,
                                              @NonNull View targetView) {
        int[] out = new int[2];

        if (layoutManager.canScrollHorizontally()) {
            out[0] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (layoutManager.canScrollVertically()) {
            out[1] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (mSnapBlockCallback != null) {
            if (out[0] == 0 && out[1] == 0) {
                mSnapBlockCallback.onBlockSnapped(layoutManager.getPosition(targetView));
            } else {
                mSnapBlockCallback.onBlockSnap(layoutManager.getPosition(targetView));
            }
        }
        return out;
    }

    // We are flinging and need to know where we are heading.
    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager,
                                      int velocityX, int velocityY) {
        LinearLayoutManager lm = (LinearLayoutManager) layoutManager;

        initItemDimensionIfNeeded(layoutManager);
        mScroller.fling(0, 0, velocityX, velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE,
                        Integer.MIN_VALUE, Integer.MAX_VALUE);

        if (velocityX != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalX(), mItemDimension);
        }

        if (velocityY != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalY(), mItemDimension);
        }

        return RecyclerView.NO_POSITION;
    }

    // We have scrolled to the neighborhood where we will snap. Determine the snap position.
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        // Snap to a view that is either 1) toward the bottom of the data and therefore on screen,
        // or, 2) toward the top of the data and may be off-screen.
        int snapPos = calcTargetPosition((LinearLayoutManager) layoutManager);
        View snapView = (snapPos == RecyclerView.NO_POSITION)
            ? null : layoutManager.findViewByPosition(snapPos);

        if (snapView == null) {
            Log.d(TAG, "<<<<findSnapView is returning null!");
        }
        Log.d(TAG, "<<<<findSnapView snapos=" + snapPos);
        return snapView;
    }

    // Does the heavy lifting for findSnapView.
    private int calcTargetPosition(LinearLayoutManager layoutManager) {
        int snapPos;
        int firstVisiblePos = layoutManager.findFirstVisibleItemPosition();

        if (firstVisiblePos == RecyclerView.NO_POSITION) {
            return RecyclerView.NO_POSITION;
        }
        initItemDimensionIfNeeded(layoutManager);
        if (firstVisiblePos >= mPriorFirstPosition) {
            // Scrolling toward bottom of data
            int firstCompletePosition = layoutManager.findFirstCompletelyVisibleItemPosition();
            if (firstCompletePosition != RecyclerView.NO_POSITION
                && firstCompletePosition % mBlocksize == 0) {
                snapPos = firstCompletePosition;
            } else {
                snapPos = roundDownToBlockSize(firstVisiblePos + mBlocksize);
            }
        } else {
            // Scrolling toward top of data
            snapPos = roundDownToBlockSize(firstVisiblePos);
            // Check to see if target view exists. If it doesn't, force a smooth scroll.
            // SnapHelper only snaps to existing views and will not scroll to a non-existant one.
            // If limiting fling to single block, then the following is not needed since the
            // views are likely to be in the RecyclerView pool.
            if (layoutManager.findViewByPosition(snapPos) == null) {
                int[] toScroll = mLayoutDirectionHelper.calculateDistanceToScroll(layoutManager, snapPos);
                mRecyclerView.smoothScrollBy(toScroll[0], toScroll[1], sInterpolator);
            }
        }
        mPriorFirstPosition = firstVisiblePos;

        return snapPos;
    }

    private void initItemDimensionIfNeeded(final RecyclerView.LayoutManager layoutManager) {
        if (mItemDimension != 0) {
            return;
        }

        View child;
        if ((child = layoutManager.getChildAt(0)) == null) {
            return;
        }

        if (layoutManager.canScrollHorizontally()) {
            mItemDimension = child.getWidth();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getWidth() / mItemDimension);
        } else if (layoutManager.canScrollVertically()) {
            mItemDimension = child.getHeight();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getHeight() / mItemDimension);
        }
        mMaxPositionsToMove = mBlocksize * mMaxFlingBlocks;
    }

    private int getSpanCount(RecyclerView.LayoutManager layoutManager) {
        return (layoutManager instanceof GridLayoutManager)
            ? ((GridLayoutManager) layoutManager).getSpanCount()
            : 1;
    }

    private int roundDownToBlockSize(int trialPosition) {
        return trialPosition - trialPosition % mBlocksize;
    }

    private int roundUpToBlockSize(int trialPosition) {
        return roundDownToBlockSize(trialPosition + mBlocksize - 1);
    }

    @Nullable
    protected LinearSmoothScroller createScroller(RecyclerView.LayoutManager layoutManager) {
        if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
            return null;
        }
        return new LinearSmoothScroller(mRecyclerView.getContext()) {
            @Override
            protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
                int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(),
                                                                   targetView);
                final int dx = snapDistances[0];
                final int dy = snapDistances[1];
                final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
                if (time > 0) {
                    action.update(dx, dy, time, sInterpolator);
                }
            }

            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
            }
        };
    }

    public void setSnapBlockCallback(@Nullable SnapBlockCallback callback) {
        mSnapBlockCallback = callback;
    }

    /*
        Helper class that handles calculations for LTR and RTL layouts.
     */
    private class LayoutDirectionHelper {

        // Is the layout an RTL one?
        private final boolean mIsRTL;

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        LayoutDirectionHelper(int direction) {
            mIsRTL = direction == View.LAYOUT_DIRECTION_RTL;
        }

        /*
            Calculate the amount of scroll needed to align the target view with the layout edge.
         */
        int getScrollToAlignView(View targetView) {
            return (mIsRTL)
                ? mOrientationHelper.getDecoratedEnd(targetView) - mRecyclerView.getWidth()
                : mOrientationHelper.getDecoratedStart(targetView);
        }

        /**
         * Calculate the distance to final snap position when the view corresponding to the snap
         * position is not currently available.
         *
         * @param layoutManager LinearLayoutManager or descendent class
         * @param targetPos     - Adapter position to snap to
         * @return int[2] {x-distance in pixels, y-distance in pixels}
         */
        int[] calculateDistanceToScroll(LinearLayoutManager layoutManager, int targetPos) {
            int[] out = new int[2];

            int firstVisiblePos;

            firstVisiblePos = layoutManager.findFirstVisibleItemPosition();
            if (layoutManager.canScrollHorizontally()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    if (mIsRTL) {
                        View lastView = layoutManager.findViewByPosition(layoutManager.findLastVisibleItemPosition());
                        out[0] = mOrientationHelper.getDecoratedEnd(lastView)
                            + (firstVisiblePos - targetPos) * mItemDimension;
                    } else {
                        View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                        out[0] = mOrientationHelper.getDecoratedStart(firstView)
                            - (firstVisiblePos - targetPos) * mItemDimension;
                    }
                }
            }
            if (layoutManager.canScrollVertically()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                    out[1] = firstView.getTop() - (firstVisiblePos - targetPos) * mItemDimension;
                }
            }

            return out;
        }

        /*
            Calculate the number of positions to move in the RecyclerView given a scroll amount
            and the size of the items to be scrolled. Return integral multiple of mBlockSize not
            equal to zero.
         */
        int getPositionsToMove(LinearLayoutManager llm, int scroll, int itemSize) {
            int positionsToMove;

            positionsToMove = roundUpToBlockSize(Math.abs(scroll) / itemSize);

            if (positionsToMove < mBlocksize) {
                // Must move at least one block
                positionsToMove = mBlocksize;
            } else if (positionsToMove > mMaxPositionsToMove) {
                // Clamp number of positions to move so we don't get wild flinging.
                positionsToMove = mMaxPositionsToMove;
            }

            if (scroll < 0) {
                positionsToMove *= -1;
            }
            if (mIsRTL) {
                positionsToMove *= -1;
            }

            if (mLayoutDirectionHelper.isDirectionToBottom(scroll < 0)) {
                // Scrolling toward the bottom of data.
                return roundDownToBlockSize(llm.findFirstVisibleItemPosition()) + positionsToMove;
            }
            // Scrolling toward the top of the data.
            return roundDownToBlockSize(llm.findLastVisibleItemPosition()) + positionsToMove;
        }

        boolean isDirectionToBottom(boolean velocityNegative) {
            //noinspection SimplifiableConditionalExpression
            return mIsRTL ? velocityNegative : !velocityNegative;
        }
    }

    public interface SnapBlockCallback {
        void onBlockSnap(int snapPosition);

        void onBlockSnapped(int snapPosition);

    }

    private static final float MILLISECONDS_PER_INCH = 100f;
    @SuppressWarnings("unused")
    private static final String TAG = "SnapToBlock";
}
-----------------------
// For LinearLayoutManager horizontal orientation
recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));

// For GridLayoutManager vertical orientation
recyclerView.setLayoutManager(new GridLayoutManager(this, SPAN_COUNT, RecyclerView.VERTICAL, false));
SnapToBlock snapToBlock = new SnapToBlock(mMaxFlingPages);
snapToBlock.attachToRecyclerView(recyclerView);
snapToBlock.setSnapBlockCallback(new SnapToBlock.SnapBlockCallback() {
    @Override
    public void onBlockSnap(int snapPosition) {
        ...
    }

    @Override
    public void onBlockSnapped(int snapPosition) {
        ...
    }
});
/*  The number of items in the RecyclerView should be a multiple of block size; otherwise, the
    extra item views will not be positioned on a block boundary when the end of the data is reached.
    Pad out with empty item views if needed.

    Updated to accommodate RTL layouts.
 */

public class SnapToBlock extends SnapHelper {
    private RecyclerView mRecyclerView;

    // Total number of items in a block of view in the RecyclerView
    private int mBlocksize;

    // Maximum number of positions to move on a fling.
    private int mMaxPositionsToMove;

    // Width of a RecyclerView item if orientation is horizonal; height of the item if vertical
    private int mItemDimension;

    // Maxim blocks to move during most vigorous fling.
    private final int mMaxFlingBlocks;

    // Callback interface when blocks are snapped.
    private SnapBlockCallback mSnapBlockCallback;

    // When snapping, used to determine direction of snap.
    private int mPriorFirstPosition = RecyclerView.NO_POSITION;

    // Our private scroller
    private Scroller mScroller;

    // Horizontal/vertical layout helper
    private OrientationHelper mOrientationHelper;

    // LTR/RTL helper
    private LayoutDirectionHelper mLayoutDirectionHelper;

    // Borrowed from ViewPager.java
    private static final Interpolator sInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            // _o(t) = t * t * ((tension + 1) * t + tension)
            // o(t) = _o(t - 1) + 1
            t -= 1.0f;
            return t * t * t + 1.0f;
        }
    };

    SnapToBlock(int maxFlingBlocks) {
        super();
        mMaxFlingBlocks = maxFlingBlocks;
    }

    @Override
    public void attachToRecyclerView(@Nullable final RecyclerView recyclerView)
        throws IllegalStateException {

        if (recyclerView != null) {
            mRecyclerView = recyclerView;
            final LinearLayoutManager layoutManager =
                (LinearLayoutManager) recyclerView.getLayoutManager();
            if (layoutManager.canScrollHorizontally()) {
                mOrientationHelper = OrientationHelper.createHorizontalHelper(layoutManager);
                mLayoutDirectionHelper =
                    new LayoutDirectionHelper(ViewCompat.getLayoutDirection(mRecyclerView));
            } else if (layoutManager.canScrollVertically()) {
                mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
                // RTL doesn't matter for vertical scrolling for this class.
                mLayoutDirectionHelper = new LayoutDirectionHelper(RecyclerView.LAYOUT_DIRECTION_LTR);
            } else {
                throw new IllegalStateException("RecyclerView must be scrollable");
            }
            mScroller = new Scroller(mRecyclerView.getContext(), sInterpolator);
            initItemDimensionIfNeeded(layoutManager);
        }
        super.attachToRecyclerView(recyclerView);
    }

    // Called when the target view is available and we need to know how much more
    // to scroll to get it lined up with the side of the RecyclerView.
    @NonNull
    @Override
    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,
                                              @NonNull View targetView) {
        int[] out = new int[2];

        if (layoutManager.canScrollHorizontally()) {
            out[0] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (layoutManager.canScrollVertically()) {
            out[1] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (mSnapBlockCallback != null) {
            if (out[0] == 0 && out[1] == 0) {
                mSnapBlockCallback.onBlockSnapped(layoutManager.getPosition(targetView));
            } else {
                mSnapBlockCallback.onBlockSnap(layoutManager.getPosition(targetView));
            }
        }
        return out;
    }

    // We are flinging and need to know where we are heading.
    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager,
                                      int velocityX, int velocityY) {
        LinearLayoutManager lm = (LinearLayoutManager) layoutManager;

        initItemDimensionIfNeeded(layoutManager);
        mScroller.fling(0, 0, velocityX, velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE,
                        Integer.MIN_VALUE, Integer.MAX_VALUE);

        if (velocityX != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalX(), mItemDimension);
        }

        if (velocityY != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalY(), mItemDimension);
        }

        return RecyclerView.NO_POSITION;
    }

    // We have scrolled to the neighborhood where we will snap. Determine the snap position.
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        // Snap to a view that is either 1) toward the bottom of the data and therefore on screen,
        // or, 2) toward the top of the data and may be off-screen.
        int snapPos = calcTargetPosition((LinearLayoutManager) layoutManager);
        View snapView = (snapPos == RecyclerView.NO_POSITION)
            ? null : layoutManager.findViewByPosition(snapPos);

        if (snapView == null) {
            Log.d(TAG, "<<<<findSnapView is returning null!");
        }
        Log.d(TAG, "<<<<findSnapView snapos=" + snapPos);
        return snapView;
    }

    // Does the heavy lifting for findSnapView.
    private int calcTargetPosition(LinearLayoutManager layoutManager) {
        int snapPos;
        int firstVisiblePos = layoutManager.findFirstVisibleItemPosition();

        if (firstVisiblePos == RecyclerView.NO_POSITION) {
            return RecyclerView.NO_POSITION;
        }
        initItemDimensionIfNeeded(layoutManager);
        if (firstVisiblePos >= mPriorFirstPosition) {
            // Scrolling toward bottom of data
            int firstCompletePosition = layoutManager.findFirstCompletelyVisibleItemPosition();
            if (firstCompletePosition != RecyclerView.NO_POSITION
                && firstCompletePosition % mBlocksize == 0) {
                snapPos = firstCompletePosition;
            } else {
                snapPos = roundDownToBlockSize(firstVisiblePos + mBlocksize);
            }
        } else {
            // Scrolling toward top of data
            snapPos = roundDownToBlockSize(firstVisiblePos);
            // Check to see if target view exists. If it doesn't, force a smooth scroll.
            // SnapHelper only snaps to existing views and will not scroll to a non-existant one.
            // If limiting fling to single block, then the following is not needed since the
            // views are likely to be in the RecyclerView pool.
            if (layoutManager.findViewByPosition(snapPos) == null) {
                int[] toScroll = mLayoutDirectionHelper.calculateDistanceToScroll(layoutManager, snapPos);
                mRecyclerView.smoothScrollBy(toScroll[0], toScroll[1], sInterpolator);
            }
        }
        mPriorFirstPosition = firstVisiblePos;

        return snapPos;
    }

    private void initItemDimensionIfNeeded(final RecyclerView.LayoutManager layoutManager) {
        if (mItemDimension != 0) {
            return;
        }

        View child;
        if ((child = layoutManager.getChildAt(0)) == null) {
            return;
        }

        if (layoutManager.canScrollHorizontally()) {
            mItemDimension = child.getWidth();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getWidth() / mItemDimension);
        } else if (layoutManager.canScrollVertically()) {
            mItemDimension = child.getHeight();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getHeight() / mItemDimension);
        }
        mMaxPositionsToMove = mBlocksize * mMaxFlingBlocks;
    }

    private int getSpanCount(RecyclerView.LayoutManager layoutManager) {
        return (layoutManager instanceof GridLayoutManager)
            ? ((GridLayoutManager) layoutManager).getSpanCount()
            : 1;
    }

    private int roundDownToBlockSize(int trialPosition) {
        return trialPosition - trialPosition % mBlocksize;
    }

    private int roundUpToBlockSize(int trialPosition) {
        return roundDownToBlockSize(trialPosition + mBlocksize - 1);
    }

    @Nullable
    protected LinearSmoothScroller createScroller(RecyclerView.LayoutManager layoutManager) {
        if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
            return null;
        }
        return new LinearSmoothScroller(mRecyclerView.getContext()) {
            @Override
            protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
                int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(),
                                                                   targetView);
                final int dx = snapDistances[0];
                final int dy = snapDistances[1];
                final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
                if (time > 0) {
                    action.update(dx, dy, time, sInterpolator);
                }
            }

            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
            }
        };
    }

    public void setSnapBlockCallback(@Nullable SnapBlockCallback callback) {
        mSnapBlockCallback = callback;
    }

    /*
        Helper class that handles calculations for LTR and RTL layouts.
     */
    private class LayoutDirectionHelper {

        // Is the layout an RTL one?
        private final boolean mIsRTL;

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        LayoutDirectionHelper(int direction) {
            mIsRTL = direction == View.LAYOUT_DIRECTION_RTL;
        }

        /*
            Calculate the amount of scroll needed to align the target view with the layout edge.
         */
        int getScrollToAlignView(View targetView) {
            return (mIsRTL)
                ? mOrientationHelper.getDecoratedEnd(targetView) - mRecyclerView.getWidth()
                : mOrientationHelper.getDecoratedStart(targetView);
        }

        /**
         * Calculate the distance to final snap position when the view corresponding to the snap
         * position is not currently available.
         *
         * @param layoutManager LinearLayoutManager or descendent class
         * @param targetPos     - Adapter position to snap to
         * @return int[2] {x-distance in pixels, y-distance in pixels}
         */
        int[] calculateDistanceToScroll(LinearLayoutManager layoutManager, int targetPos) {
            int[] out = new int[2];

            int firstVisiblePos;

            firstVisiblePos = layoutManager.findFirstVisibleItemPosition();
            if (layoutManager.canScrollHorizontally()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    if (mIsRTL) {
                        View lastView = layoutManager.findViewByPosition(layoutManager.findLastVisibleItemPosition());
                        out[0] = mOrientationHelper.getDecoratedEnd(lastView)
                            + (firstVisiblePos - targetPos) * mItemDimension;
                    } else {
                        View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                        out[0] = mOrientationHelper.getDecoratedStart(firstView)
                            - (firstVisiblePos - targetPos) * mItemDimension;
                    }
                }
            }
            if (layoutManager.canScrollVertically()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                    out[1] = firstView.getTop() - (firstVisiblePos - targetPos) * mItemDimension;
                }
            }

            return out;
        }

        /*
            Calculate the number of positions to move in the RecyclerView given a scroll amount
            and the size of the items to be scrolled. Return integral multiple of mBlockSize not
            equal to zero.
         */
        int getPositionsToMove(LinearLayoutManager llm, int scroll, int itemSize) {
            int positionsToMove;

            positionsToMove = roundUpToBlockSize(Math.abs(scroll) / itemSize);

            if (positionsToMove < mBlocksize) {
                // Must move at least one block
                positionsToMove = mBlocksize;
            } else if (positionsToMove > mMaxPositionsToMove) {
                // Clamp number of positions to move so we don't get wild flinging.
                positionsToMove = mMaxPositionsToMove;
            }

            if (scroll < 0) {
                positionsToMove *= -1;
            }
            if (mIsRTL) {
                positionsToMove *= -1;
            }

            if (mLayoutDirectionHelper.isDirectionToBottom(scroll < 0)) {
                // Scrolling toward the bottom of data.
                return roundDownToBlockSize(llm.findFirstVisibleItemPosition()) + positionsToMove;
            }
            // Scrolling toward the top of the data.
            return roundDownToBlockSize(llm.findLastVisibleItemPosition()) + positionsToMove;
        }

        boolean isDirectionToBottom(boolean velocityNegative) {
            //noinspection SimplifiableConditionalExpression
            return mIsRTL ? velocityNegative : !velocityNegative;
        }
    }

    public interface SnapBlockCallback {
        void onBlockSnap(int snapPosition);

        void onBlockSnapped(int snapPosition);

    }

    private static final float MILLISECONDS_PER_INCH = 100f;
    @SuppressWarnings("unused")
    private static final String TAG = "SnapToBlock";
}
-----------------------
// For LinearLayoutManager horizontal orientation
recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));

// For GridLayoutManager vertical orientation
recyclerView.setLayoutManager(new GridLayoutManager(this, SPAN_COUNT, RecyclerView.VERTICAL, false));
SnapToBlock snapToBlock = new SnapToBlock(mMaxFlingPages);
snapToBlock.attachToRecyclerView(recyclerView);
snapToBlock.setSnapBlockCallback(new SnapToBlock.SnapBlockCallback() {
    @Override
    public void onBlockSnap(int snapPosition) {
        ...
    }

    @Override
    public void onBlockSnapped(int snapPosition) {
        ...
    }
});
/*  The number of items in the RecyclerView should be a multiple of block size; otherwise, the
    extra item views will not be positioned on a block boundary when the end of the data is reached.
    Pad out with empty item views if needed.

    Updated to accommodate RTL layouts.
 */

public class SnapToBlock extends SnapHelper {
    private RecyclerView mRecyclerView;

    // Total number of items in a block of view in the RecyclerView
    private int mBlocksize;

    // Maximum number of positions to move on a fling.
    private int mMaxPositionsToMove;

    // Width of a RecyclerView item if orientation is horizonal; height of the item if vertical
    private int mItemDimension;

    // Maxim blocks to move during most vigorous fling.
    private final int mMaxFlingBlocks;

    // Callback interface when blocks are snapped.
    private SnapBlockCallback mSnapBlockCallback;

    // When snapping, used to determine direction of snap.
    private int mPriorFirstPosition = RecyclerView.NO_POSITION;

    // Our private scroller
    private Scroller mScroller;

    // Horizontal/vertical layout helper
    private OrientationHelper mOrientationHelper;

    // LTR/RTL helper
    private LayoutDirectionHelper mLayoutDirectionHelper;

    // Borrowed from ViewPager.java
    private static final Interpolator sInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            // _o(t) = t * t * ((tension + 1) * t + tension)
            // o(t) = _o(t - 1) + 1
            t -= 1.0f;
            return t * t * t + 1.0f;
        }
    };

    SnapToBlock(int maxFlingBlocks) {
        super();
        mMaxFlingBlocks = maxFlingBlocks;
    }

    @Override
    public void attachToRecyclerView(@Nullable final RecyclerView recyclerView)
        throws IllegalStateException {

        if (recyclerView != null) {
            mRecyclerView = recyclerView;
            final LinearLayoutManager layoutManager =
                (LinearLayoutManager) recyclerView.getLayoutManager();
            if (layoutManager.canScrollHorizontally()) {
                mOrientationHelper = OrientationHelper.createHorizontalHelper(layoutManager);
                mLayoutDirectionHelper =
                    new LayoutDirectionHelper(ViewCompat.getLayoutDirection(mRecyclerView));
            } else if (layoutManager.canScrollVertically()) {
                mOrientationHelper = OrientationHelper.createVerticalHelper(layoutManager);
                // RTL doesn't matter for vertical scrolling for this class.
                mLayoutDirectionHelper = new LayoutDirectionHelper(RecyclerView.LAYOUT_DIRECTION_LTR);
            } else {
                throw new IllegalStateException("RecyclerView must be scrollable");
            }
            mScroller = new Scroller(mRecyclerView.getContext(), sInterpolator);
            initItemDimensionIfNeeded(layoutManager);
        }
        super.attachToRecyclerView(recyclerView);
    }

    // Called when the target view is available and we need to know how much more
    // to scroll to get it lined up with the side of the RecyclerView.
    @NonNull
    @Override
    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager,
                                              @NonNull View targetView) {
        int[] out = new int[2];

        if (layoutManager.canScrollHorizontally()) {
            out[0] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (layoutManager.canScrollVertically()) {
            out[1] = mLayoutDirectionHelper.getScrollToAlignView(targetView);
        }
        if (mSnapBlockCallback != null) {
            if (out[0] == 0 && out[1] == 0) {
                mSnapBlockCallback.onBlockSnapped(layoutManager.getPosition(targetView));
            } else {
                mSnapBlockCallback.onBlockSnap(layoutManager.getPosition(targetView));
            }
        }
        return out;
    }

    // We are flinging and need to know where we are heading.
    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager,
                                      int velocityX, int velocityY) {
        LinearLayoutManager lm = (LinearLayoutManager) layoutManager;

        initItemDimensionIfNeeded(layoutManager);
        mScroller.fling(0, 0, velocityX, velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE,
                        Integer.MIN_VALUE, Integer.MAX_VALUE);

        if (velocityX != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalX(), mItemDimension);
        }

        if (velocityY != 0) {
            return mLayoutDirectionHelper
                .getPositionsToMove(lm, mScroller.getFinalY(), mItemDimension);
        }

        return RecyclerView.NO_POSITION;
    }

    // We have scrolled to the neighborhood where we will snap. Determine the snap position.
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        // Snap to a view that is either 1) toward the bottom of the data and therefore on screen,
        // or, 2) toward the top of the data and may be off-screen.
        int snapPos = calcTargetPosition((LinearLayoutManager) layoutManager);
        View snapView = (snapPos == RecyclerView.NO_POSITION)
            ? null : layoutManager.findViewByPosition(snapPos);

        if (snapView == null) {
            Log.d(TAG, "<<<<findSnapView is returning null!");
        }
        Log.d(TAG, "<<<<findSnapView snapos=" + snapPos);
        return snapView;
    }

    // Does the heavy lifting for findSnapView.
    private int calcTargetPosition(LinearLayoutManager layoutManager) {
        int snapPos;
        int firstVisiblePos = layoutManager.findFirstVisibleItemPosition();

        if (firstVisiblePos == RecyclerView.NO_POSITION) {
            return RecyclerView.NO_POSITION;
        }
        initItemDimensionIfNeeded(layoutManager);
        if (firstVisiblePos >= mPriorFirstPosition) {
            // Scrolling toward bottom of data
            int firstCompletePosition = layoutManager.findFirstCompletelyVisibleItemPosition();
            if (firstCompletePosition != RecyclerView.NO_POSITION
                && firstCompletePosition % mBlocksize == 0) {
                snapPos = firstCompletePosition;
            } else {
                snapPos = roundDownToBlockSize(firstVisiblePos + mBlocksize);
            }
        } else {
            // Scrolling toward top of data
            snapPos = roundDownToBlockSize(firstVisiblePos);
            // Check to see if target view exists. If it doesn't, force a smooth scroll.
            // SnapHelper only snaps to existing views and will not scroll to a non-existant one.
            // If limiting fling to single block, then the following is not needed since the
            // views are likely to be in the RecyclerView pool.
            if (layoutManager.findViewByPosition(snapPos) == null) {
                int[] toScroll = mLayoutDirectionHelper.calculateDistanceToScroll(layoutManager, snapPos);
                mRecyclerView.smoothScrollBy(toScroll[0], toScroll[1], sInterpolator);
            }
        }
        mPriorFirstPosition = firstVisiblePos;

        return snapPos;
    }

    private void initItemDimensionIfNeeded(final RecyclerView.LayoutManager layoutManager) {
        if (mItemDimension != 0) {
            return;
        }

        View child;
        if ((child = layoutManager.getChildAt(0)) == null) {
            return;
        }

        if (layoutManager.canScrollHorizontally()) {
            mItemDimension = child.getWidth();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getWidth() / mItemDimension);
        } else if (layoutManager.canScrollVertically()) {
            mItemDimension = child.getHeight();
            mBlocksize = getSpanCount(layoutManager) * (mRecyclerView.getHeight() / mItemDimension);
        }
        mMaxPositionsToMove = mBlocksize * mMaxFlingBlocks;
    }

    private int getSpanCount(RecyclerView.LayoutManager layoutManager) {
        return (layoutManager instanceof GridLayoutManager)
            ? ((GridLayoutManager) layoutManager).getSpanCount()
            : 1;
    }

    private int roundDownToBlockSize(int trialPosition) {
        return trialPosition - trialPosition % mBlocksize;
    }

    private int roundUpToBlockSize(int trialPosition) {
        return roundDownToBlockSize(trialPosition + mBlocksize - 1);
    }

    @Nullable
    protected LinearSmoothScroller createScroller(RecyclerView.LayoutManager layoutManager) {
        if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) {
            return null;
        }
        return new LinearSmoothScroller(mRecyclerView.getContext()) {
            @Override
            protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
                int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(),
                                                                   targetView);
                final int dx = snapDistances[0];
                final int dy = snapDistances[1];
                final int time = calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
                if (time > 0) {
                    action.update(dx, dy, time, sInterpolator);
                }
            }

            @Override
            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
            }
        };
    }

    public void setSnapBlockCallback(@Nullable SnapBlockCallback callback) {
        mSnapBlockCallback = callback;
    }

    /*
        Helper class that handles calculations for LTR and RTL layouts.
     */
    private class LayoutDirectionHelper {

        // Is the layout an RTL one?
        private final boolean mIsRTL;

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        LayoutDirectionHelper(int direction) {
            mIsRTL = direction == View.LAYOUT_DIRECTION_RTL;
        }

        /*
            Calculate the amount of scroll needed to align the target view with the layout edge.
         */
        int getScrollToAlignView(View targetView) {
            return (mIsRTL)
                ? mOrientationHelper.getDecoratedEnd(targetView) - mRecyclerView.getWidth()
                : mOrientationHelper.getDecoratedStart(targetView);
        }

        /**
         * Calculate the distance to final snap position when the view corresponding to the snap
         * position is not currently available.
         *
         * @param layoutManager LinearLayoutManager or descendent class
         * @param targetPos     - Adapter position to snap to
         * @return int[2] {x-distance in pixels, y-distance in pixels}
         */
        int[] calculateDistanceToScroll(LinearLayoutManager layoutManager, int targetPos) {
            int[] out = new int[2];

            int firstVisiblePos;

            firstVisiblePos = layoutManager.findFirstVisibleItemPosition();
            if (layoutManager.canScrollHorizontally()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    if (mIsRTL) {
                        View lastView = layoutManager.findViewByPosition(layoutManager.findLastVisibleItemPosition());
                        out[0] = mOrientationHelper.getDecoratedEnd(lastView)
                            + (firstVisiblePos - targetPos) * mItemDimension;
                    } else {
                        View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                        out[0] = mOrientationHelper.getDecoratedStart(firstView)
                            - (firstVisiblePos - targetPos) * mItemDimension;
                    }
                }
            }
            if (layoutManager.canScrollVertically()) {
                if (targetPos <= firstVisiblePos) { // scrolling toward top of data
                    View firstView = layoutManager.findViewByPosition(firstVisiblePos);
                    out[1] = firstView.getTop() - (firstVisiblePos - targetPos) * mItemDimension;
                }
            }

            return out;
        }

        /*
            Calculate the number of positions to move in the RecyclerView given a scroll amount
            and the size of the items to be scrolled. Return integral multiple of mBlockSize not
            equal to zero.
         */
        int getPositionsToMove(LinearLayoutManager llm, int scroll, int itemSize) {
            int positionsToMove;

            positionsToMove = roundUpToBlockSize(Math.abs(scroll) / itemSize);

            if (positionsToMove < mBlocksize) {
                // Must move at least one block
                positionsToMove = mBlocksize;
            } else if (positionsToMove > mMaxPositionsToMove) {
                // Clamp number of positions to move so we don't get wild flinging.
                positionsToMove = mMaxPositionsToMove;
            }

            if (scroll < 0) {
                positionsToMove *= -1;
            }
            if (mIsRTL) {
                positionsToMove *= -1;
            }

            if (mLayoutDirectionHelper.isDirectionToBottom(scroll < 0)) {
                // Scrolling toward the bottom of data.
                return roundDownToBlockSize(llm.findFirstVisibleItemPosition()) + positionsToMove;
            }
            // Scrolling toward the top of the data.
            return roundDownToBlockSize(llm.findLastVisibleItemPosition()) + positionsToMove;
        }

        boolean isDirectionToBottom(boolean velocityNegative) {
            //noinspection SimplifiableConditionalExpression
            return mIsRTL ? velocityNegative : !velocityNegative;
        }
    }

    public interface SnapBlockCallback {
        void onBlockSnap(int snapPosition);

        void onBlockSnapped(int snapPosition);

    }

    private static final float MILLISECONDS_PER_INCH = 100f;
    @SuppressWarnings("unused")
    private static final String TAG = "SnapToBlock";
}
-----------------------
<com.takusemba.multisnaprecyclerview.MultiSnapRecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:msrv_gravity="start"
    app:msrv_snap_count="3" />

How to get soon-to-be-selected page while settling snapping feature on RecyclerView and ViewPager

copy iconCopydownload iconDownload
    val inflater = LayoutInflater.from(this)
    val viewPagerHolders = HashMap<Int, ViewPagerViewHolder>()
    viewPager.adapter = object : RecyclerPagerAdapter<ViewPagerViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolder {
            return ViewPagerViewHolder(inflater.inflate(R.layout.cell, parent, false))
        }

        override fun getItemCount(): Int = 100

        override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) {
            holder.textView.text = position.toString()
            viewPagerHolders.remove(holder.adapterPosition)
            holder.adapterPosition = position
            viewPagerHolders[position] = holder

        }
    }
    viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
        var selectedHolder: ViewPagerViewHolder? = null

        override fun onPageScrollStateChanged(state: Int) {}
        override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}

        override fun onPageSelected(position: Int) {
            val holder = viewPagerHolders[position]
            if (holder != null) {
                if (selectedHolder != null && selectedHolder != holder)
                    selectedHolder!!.textView.text = selectedHolder!!.adapterPosition.toString()
                holder.textView.text = "selected:${position.toString()}"
                selectedHolder = holder
            }
        }
    })
class ViewPagerViewHolder(itemView: View) : RecyclerPagerAdapter.ViewHolder(itemView) {
    val textView: TextView = itemView.findViewById(android.R.id.text1)
    var adapterPosition: Int = Int.MIN_VALUE
}
-----------------------
    val inflater = LayoutInflater.from(this)
    val viewPagerHolders = HashMap<Int, ViewPagerViewHolder>()
    viewPager.adapter = object : RecyclerPagerAdapter<ViewPagerViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolder {
            return ViewPagerViewHolder(inflater.inflate(R.layout.cell, parent, false))
        }

        override fun getItemCount(): Int = 100

        override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) {
            holder.textView.text = position.toString()
            viewPagerHolders.remove(holder.adapterPosition)
            holder.adapterPosition = position
            viewPagerHolders[position] = holder

        }
    }
    viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
        var selectedHolder: ViewPagerViewHolder? = null

        override fun onPageScrollStateChanged(state: Int) {}
        override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}

        override fun onPageSelected(position: Int) {
            val holder = viewPagerHolders[position]
            if (holder != null) {
                if (selectedHolder != null && selectedHolder != holder)
                    selectedHolder!!.textView.text = selectedHolder!!.adapterPosition.toString()
                holder.textView.text = "selected:${position.toString()}"
                selectedHolder = holder
            }
        }
    })
class ViewPagerViewHolder(itemView: View) : RecyclerPagerAdapter.ViewHolder(itemView) {
    val textView: TextView = itemView.findViewById(android.R.id.text1)
    var adapterPosition: Int = Int.MIN_VALUE
}

Adding Youtube API in application using Firebase in Android

copy iconCopydownload iconDownload
youTubePlayerView.initialize("YOUR API KEY",
            new YouTubePlayer.OnInitializedListener() {
                @Override
                public void onInitializationSuccess(YouTubePlayer.Provider provider,
                        YouTubePlayer youTubePlayer, boolean b) {


                    youTubePlayer.loadVideo("VIDEO_ID_HERE");
                }
                @Override
                public void onInitializationFailure(YouTubePlayer.Provider provider,
                        YouTubeInitializationResult youTubeInitializationResult) {

                }
    });

how to add fragment in recycler adapter?

copy iconCopydownload iconDownload
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
public RecyclerViewConstructor(Activity hostActivity) {
    super();
    this.hostActivity = hostActivity;
    lastClickTime = 0;
}

Activity host
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View rootView = LayoutInflater.from(mContext).inflate(R.layout.item_fragment, null);
    return new ViewHolder(rootView);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    YourFragment yourFragment = YourFragment.newInstance();
    FragmentManager fm = hostActivity.getSupportFragmentManager();
    fm.addOnBackStackChangedListener(this);
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.fragment_container, fragment, tag);
}
-----------------------
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
public RecyclerViewConstructor(Activity hostActivity) {
    super();
    this.hostActivity = hostActivity;
    lastClickTime = 0;
}

Activity host
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View rootView = LayoutInflater.from(mContext).inflate(R.layout.item_fragment, null);
    return new ViewHolder(rootView);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    YourFragment yourFragment = YourFragment.newInstance();
    FragmentManager fm = hostActivity.getSupportFragmentManager();
    fm.addOnBackStackChangedListener(this);
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.fragment_container, fragment, tag);
}
-----------------------
public class ViewHolderInds extends RecyclerView.ViewHolder {
...
    public final int frameId; //Unique identifier for ValueFrame
...
    public ViewHolderInds(View view) {
        super(view);
...
        frameId = view.generateViewId();
        ((FrameLayout) view.findViewById(R.id.valueFrame)).setId(frameId);
...
    }
}
    @Override
    public void onBindViewHolder(@NonNull ViewHolderInds holder, int position) {
        getActivity().getSupportFragmentManager().
                beginTransaction().
                replace(holder.frameId, EditFragment.newInstance(...)).
                commit();
...
-----------------------
public class ViewHolderInds extends RecyclerView.ViewHolder {
...
    public final int frameId; //Unique identifier for ValueFrame
...
    public ViewHolderInds(View view) {
        super(view);
...
        frameId = view.generateViewId();
        ((FrameLayout) view.findViewById(R.id.valueFrame)).setId(frameId);
...
    }
}
    @Override
    public void onBindViewHolder(@NonNull ViewHolderInds holder, int position) {
        getActivity().getSupportFragmentManager().
                beginTransaction().
                replace(holder.frameId, EditFragment.newInstance(...)).
                commit();
...

Android build gradle fail on specific device

copy iconCopydownload iconDownload
compile 'com.squareup.okhttp3:okhttp:3.8.1'
compile 'com.squareup.picasso:picasso:2.5.2'
android {
  configurations{
     all*.exclude module: 'okhttp'
     all*.exclude module: 'okio'
   }
}
-----------------------
compile 'com.squareup.okhttp3:okhttp:3.8.1'
compile 'com.squareup.picasso:picasso:2.5.2'
android {
  configurations{
     all*.exclude module: 'okhttp'
     all*.exclude module: 'okio'
   }
}
-----------------------
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'

Android Build Tools 3.1.1 failed build finished with non-zero exit value 1

copy iconCopydownload iconDownload
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

ConstraintLayout inside DrawerLayout causes some problems

copy iconCopydownload iconDownload
<ScrollView
    android:id="@+id/scrollViewDashboard"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

Android, AsyncTask not calling onProgressUpdate and onPostExecute

copy iconCopydownload iconDownload
 new GetPlaylistAsyncTask(mYouTubeDataApi,getContext()) {
            @Override
            public void onPostExecute(Pair<String, List<Video>> result) {
                handleGetPlaylistResult(playlistVideos, result);
            }
        }.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
 new GetPlaylistAsyncTask(mYouTubeDataApi,getContext(),YouTubeRecyclerViewFragment.this)
          .execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());

    @Override
    public void handleGetPlaylistResult(PlaylistVideos playlistVideos, Pair<String, List<Video>> result) {
        if (result == null) return;
        if (playlistVideos == null){
             playlistVideos = mPlaylistVideos;
        }
        final int positionStart = playlistVideos.size();
        playlistVideos.setNextPageToken(result.first);
        playlistVideos.addAll(result.second);
        mPlaylistCardAdapter.notifyItemRangeInserted(positionStart, result.second.size());
    }
 public class GetPlaylistAsyncTask{

 private AsyncResponse theListener;

 public GetPlaylistAsyncTask(YouTube api, Context context, YouTubeRecyclerViewFragment frag ) {
    mYouTubeDataApi = api;
    mContext = context;
    theListener = (AsyncResponse)frag;
 }

 @Override
       public void onPostExecute(Pair<String, List<Video>> result) {
          progressBar.dismiss();
          theListener.handleGetPlaylistResult(null,result);
      }
}
-----------------------
 new GetPlaylistAsyncTask(mYouTubeDataApi,getContext()) {
            @Override
            public void onPostExecute(Pair<String, List<Video>> result) {
                handleGetPlaylistResult(playlistVideos, result);
            }
        }.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
 new GetPlaylistAsyncTask(mYouTubeDataApi,getContext(),YouTubeRecyclerViewFragment.this)
          .execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());

    @Override
    public void handleGetPlaylistResult(PlaylistVideos playlistVideos, Pair<String, List<Video>> result) {
        if (result == null) return;
        if (playlistVideos == null){
             playlistVideos = mPlaylistVideos;
        }
        final int positionStart = playlistVideos.size();
        playlistVideos.setNextPageToken(result.first);
        playlistVideos.addAll(result.second);
        mPlaylistCardAdapter.notifyItemRangeInserted(positionStart, result.second.size());
    }
 public class GetPlaylistAsyncTask{

 private AsyncResponse theListener;

 public GetPlaylistAsyncTask(YouTube api, Context context, YouTubeRecyclerViewFragment frag ) {
    mYouTubeDataApi = api;
    mContext = context;
    theListener = (AsyncResponse)frag;
 }

 @Override
       public void onPostExecute(Pair<String, List<Video>> result) {
          progressBar.dismiss();
          theListener.handleGetPlaylistResult(null,result);
      }
}
-----------------------
 new GetPlaylistAsyncTask(mYouTubeDataApi,getContext()) {
            @Override
            public void onPostExecute(Pair<String, List<Video>> result) {
                handleGetPlaylistResult(playlistVideos, result);
            }
        }.execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());
 new GetPlaylistAsyncTask(mYouTubeDataApi,getContext(),YouTubeRecyclerViewFragment.this)
          .execute(playlistVideos.playlistId, playlistVideos.getNextPageToken());

    @Override
    public void handleGetPlaylistResult(PlaylistVideos playlistVideos, Pair<String, List<Video>> result) {
        if (result == null) return;
        if (playlistVideos == null){
             playlistVideos = mPlaylistVideos;
        }
        final int positionStart = playlistVideos.size();
        playlistVideos.setNextPageToken(result.first);
        playlistVideos.addAll(result.second);
        mPlaylistCardAdapter.notifyItemRangeInserted(positionStart, result.second.size());
    }
 public class GetPlaylistAsyncTask{

 private AsyncResponse theListener;

 public GetPlaylistAsyncTask(YouTube api, Context context, YouTubeRecyclerViewFragment frag ) {
    mYouTubeDataApi = api;
    mContext = context;
    theListener = (AsyncResponse)frag;
 }

 @Override
       public void onPostExecute(Pair<String, List<Video>> result) {
          progressBar.dismiss();
          theListener.handleGetPlaylistResult(null,result);
      }
}

Community Discussions

Trending Discussions on RecyclerViewPager
  • Could not find multidex.jar (com.android.support:multidex:1.0.2)
  • How to implement RecyclerViewPager in kotlin?
  • How to snap RecyclerView items so that every X items would be considered like a single unit to snap to?
  • How to get soon-to-be-selected page while settling snapping feature on RecyclerView and ViewPager
  • Adding Youtube API in application using Firebase in Android
  • how to add fragment in recycler adapter?
  • No content displays when app runs on recyclerViewPager
  • Android build gradle fail on specific device
  • Android Build Tools 3.1.1 failed build finished with non-zero exit value 1
  • ConstraintLayout inside DrawerLayout causes some problems
Trending Discussions on RecyclerViewPager

QUESTION

Could not find multidex.jar (com.android.support:multidex:1.0.2)

Asked 2020-May-21 at 11:15

Could not find multidex.jar (com.android.support:multidex:1.0.2). Searched in the following locations: https://jcenter.bintray.com/com/android/support/multidex/1.0.2/multidex

I have just installed latest version of Android Studio 3.1.3 When i tried to sync my project it shows failed to resolve : multidex

Also i tried https://jcenter.bintray.com/com/android/support/multidex/1.0.2/multidex this link which shows 404 error. Please help

Project Level :

// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: 'buildsystem/dependencies.gradle'

buildscript {
    repositories {
        jcenter()
        mavenCentral()
        maven { url 'https://maven.fabric.io/public' }
        maven {
            url 'https://maven.google.com'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath 'com.frogermcs.androiddevmetrics:androiddevmetrics-plugin:0.5'
        classpath 'com.google.gms:google-services:3.1.2'
        classpath 'io.fabric.tools:gradle:1.25.1'
    }
}

allprojects {
    ext {
        androidApplicationId = 'com.medikoe.connect'
        androidVersionCode = 23
        androidVersionName = "1.7.2"
        testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
        testApplicationId = 'com.medikoe.test'
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
repositories {
    google()
}

App Level :

apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
apply plugin: 'com.frogermcs.androiddevmetrics'

configurations {
    devDebugCompile
    devSignedDebugCompile
    devPreReleaseCompile
    devReleaseCompile
    prodDebugCompile
    prodSignedDebugCompile
    prodPreReleaseCompile
    prodReleaseCompile
}


android {
    def globalConfiguration = rootProject.extensions.getByName("ext")

    compileSdkVersion globalConfiguration.getAt("androidCompileSdkVersion")
    buildToolsVersion globalConfiguration.getAt("androidBuildToolsVersion")

    defaultConfig {
        minSdkVersion globalConfiguration.getAt("androidMinSdkVersion")
        targetSdkVersion globalConfiguration.getAt("androidTargetSdkVersion")
        versionCode globalConfiguration.getAt("androidVersionCode")
        applicationId globalConfiguration.getAt("androidApplicationId")
        testInstrumentationRunner globalConfiguration.getAt("testInstrumentationRunner")
        testApplicationId globalConfiguration.getAt("testApplicationId")

        multiDexEnabled true

        vectorDrawables.useSupportLibrary = true
    }

    dexOptions {

        jumboMode true
        javaMaxHeapSize "6g"

    }

    compileOptions {
        targetCompatibility 1.8
        sourceCompatibility 1.8
    }

    packagingOptions {
        exclude 'LICENSE.txt'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/ASL2.0'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
    }

    lintOptions {
        quiet true
        abortOnError false
        ignoreWarnings true
        disable 'InvalidPackage'            //Some libraries have issues with this.
        disable 'OldTargetApi'
        //Lint gives this warning but SDK 20 would be Android L Beta.
        disable 'IconDensities'             //For testing purpose. This is safe to remove.
        disable 'IconMissingDensityFolder'  //For testing purpose. This is safe to remove.
    }


    signingConfigs {
        debug {
            storeFile file('../buildsystem/debug.keystore')
            storePassword 'android'
            keyAlias '********'
            keyPassword '******'
        }

        signedDebug {
            storeFile file('../buildsystem/keystore_medikoe.jks')
            storePassword '*********'
            keyAlias '*********'
            keyPassword '**********'
        }
        preRelease {
            storeFile file('../buildsystem/keystore_medikoe.jks')
            storePassword '**********'
            keyAlias '******'
            keyPassword '********'
        }

        release {
            storeFile file('../buildsystem/keystore_medikoe.jks')
            storePassword '************'
            keyAlias '**********'
            keyPassword '************'
        }
    }

    dataBinding {
        enabled = false
    }

    flavorDimensions "default"

    productFlavors {
        dev {
            // Enable pre-dexing to produce an APK that can be tested on
            // Android 5.0+ without the time-consuming DEX build processes.
            minSdkVersion 19
        }
        prod {
            // The actual minSdkVersion for the production version.
            minSdkVersion globalConfiguration.getAt("androidMinSdkVersion")
        }
    }

    buildTypes {

        debug {
            signingConfig signingConfigs.debug
            applicationIdSuffix ".debug"
            resValue "string", "app_name", "Connect-D"
            buildConfigField "boolean", "PRE_RELEASE", "false"
        }
        signedDebug {
            minifyEnabled true
            zipAlignEnabled true
            shrinkResources true
            debuggable true
            signingConfig signingConfigs.signedDebug
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            applicationIdSuffix ".signeddebug"
            resValue "string", "app_name", "Connect-SD"
            buildConfigField "boolean", "PRE_RELEASE", "false"
        }
        preRelease {
            minifyEnabled true
            zipAlignEnabled true
            shrinkResources true
            debuggable false
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            applicationIdSuffix ".prerelease"
            resValue "string", "app_name", "Connect-PR"
            buildConfigField "boolean", "PRE_RELEASE", "true"
        }
        release {
            minifyEnabled true
            zipAlignEnabled true
            shrinkResources true
            debuggable false
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            resValue "string", "app_name", "Medikoe Connect"
            buildConfigField "boolean", "PRE_RELEASE", "false"
        }
    }

}

dependencies {
    def presentationDependencies = rootProject.ext.presentationDependencies
    def presentationTestDependencies = rootProject.ext.presentationTestDependencies
    def developmentDependencies = rootProject.ext.developmentDependencies

    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.android.support:support-v4:27+'
    compile project(':Domain')

    devDebugCompile project(path: ':Data')
    devSignedDebugCompile project(path: ':Data')
    devPreReleaseCompile project(path: ':Data')
    devReleaseCompile project(path: ':Data')
    prodDebugCompile project(path: ':Data')
    prodSignedDebugCompile project(path: ':Data')
    prodPreReleaseCompile project(path: ':Data')
    prodReleaseCompile project(path: ':Data')

    devDebugCompile project(path: ':Infrastructure')
    devSignedDebugCompile project(path: ':Infrastructure')
    devPreReleaseCompile project(path: ':Infrastructure')
    devReleaseCompile project(path: ':Infrastructure')
    prodDebugCompile project(path: ':Infrastructure')
    prodSignedDebugCompile project(path: ':Infrastructure')
    prodPreReleaseCompile project(path: ':Infrastructure')
    prodReleaseCompile project(path: ':Infrastructure')

    //compile files('libs/date4j.jar')
    //compile files('libs/commons-collections4-4.1.jar')

    annotationProcessor presentationDependencies.daggerCompiler
    compile presentationDependencies.dagger
    compile presentationDependencies.rxJava
    compile presentationDependencies.rxAndroid
    provided presentationDependencies.javaxAnnotation
    //compile presentationDependencies.autoFactory
    compile presentationDependencies.butterKnife
    annotationProcessor presentationDependencies.butterKnifeCompiler

    compile presentationDependencies.designLibrary
    compile presentationDependencies.recyclerView
    compile presentationDependencies.cardView
    compile presentationDependencies.percent
    compile presentationDependencies.glide
    compile presentationDependencies.glideOkhttp3
    compile presentationDependencies.nineOldAndroids
    //compile presentationDependencies.ahBottomNav
    //compile presentationDependencies.lapismSearch
    //compile presentationDependencies.FragmentNavigator
    compile presentationDependencies.flexibleDivider
    compile presentationDependencies.materialDialogsCore
    compile presentationDependencies.materialFavoriteButton
    compile presentationDependencies.fancyButtons
    compile presentationDependencies.simpleRatingBar
    compile presentationDependencies.circularImageView
    compile presentationDependencies.waveLoadingView
    compile presentationDependencies.googleAutoFactory
    annotationProcessor presentationDependencies.googleAutoFactory
    compile presentationDependencies.playServicesPlaces
    compile presentationDependencies.playServicesLocation
    //compile presentationDependencies.tagGroup
    //compile presentationDependencies.expandableTextView
    //compile presentationDependencies.expandableLayout
    //compile presentationDependencies.touchImageView
    //compile presentationDependencies.sublimePicker
    compile presentationDependencies.rxpermissions
    compile presentationDependencies.rxActivityResult
    compile presentationDependencies.rxBinding
    compile presentationDependencies.rxPaparazzo
    compile presentationDependencies.rxBinding
    compile presentationDependencies.parcelerApi
    annotationProcessor presentationDependencies.parceler
    compile presentationDependencies.guava
    compile presentationDependencies.weekView
    compile presentationDependencies.jodaTime
    compile presentationDependencies.rxPaparazzo
    //compile presentationDependencies.collection
    compile presentationDependencies.RecyclerViewPager
    //compile presentationDependencies.googleAnalytics
    compile presentationDependencies.SpotsProgressDialog
    compile presentationDependencies.CustomActivityOnCrash

    compile presentationDependencies.multiDex
    compile presentationDependencies.SaripaarVersion
    //compile presentationDependencies.RazorPay
    compile presentationDependencies.Timecon
    compile presentationDependencies.ClansFab
    compile presentationDependencies.MPAndroidChart
    compile presentationDependencies.FragNav
    compile presentationDependencies.CircularFillableLoaders
    compile presentationDependencies.AvatarImageView
    compile presentationDependencies.AVLoadingIndicatorView
    compile presentationDependencies.Epoxy
    annotationProcessor presentationDependencies.EpoxyProcessor
    compile presentationDependencies.RelativeTimeTextView
    //compile presentationDependencies.AudioPlayerView
    compile presentationDependencies.EasyVideoPlayer
    compile presentationDependencies.ThreeTenAndroid
    //compile presentationDependencies.Steppers
    //compile presentationDependencies.RxAccountManager
    compile presentationDependencies.MaterialProgressBar
    compile presentationDependencies.FloatingView
//    compile presentationDependencies.HashtagView{
//        //Guava appears to be included explicitly in the list-services.jar
//        //Skip the redundant dependency
//        exclude group: 'com.google.guava'
//    }
    compile('com.github.greenfrvr:hashtag-view:1.3.1@aar') {
        transitive = false
    }

    androidTestCompile presentationTestDependencies.mockito
    androidTestCompile presentationTestDependencies.dexmaker
    androidTestCompile presentationTestDependencies.dexmakerMockito
    androidTestCompile presentationTestDependencies.espresso
    androidTestCompile presentationTestDependencies.testingSupportLib
    androidTestCompile presentationTestDependencies.androidAnnotations
    androidTestCompile presentationTestDependencies.autoFactory
//    androidTestCompile presentationTestDependencies.guava

    //Development
    compile developmentDependencies.leakCanary
    compile developmentDependencies.DebugDatabase
    compile 'com.facebook.stetho:stetho:1.4.1'
    compile 'com.facebook.stetho:stetho-okhttp3:1.4.1'
    compile('com.razorpay:checkout:1.4.4')
    compile 'com.aurelhubert:ahbottomnavigation:2.1.0'
    compile 'com.github.florent37:materialtextfield:1.0.7'
    compile 'com.github.rahatarmanahmed:circularprogressview:2.5.0'
    compile('com.github.ganfra:material-spinner:2.0.0')
    compile 'com.wdullaer:materialdatetimepicker:3.5.0'
    compile 'com.myhexaville:smart-image-picker:1.0'
    compile 'com.github.blikoon:QRCodeScanner:0.1.2'
    compile 'de.hdodenhof:circleimageview:2.2.0'
    compile 'com.github.IntruderShanky:Frisson:2.1.1'
    compile 'com.jsibbold:zoomage:1.1.0'
    compile 'com.github.emrekose26:PinchZoom:-SNAPSHOT'
    compile 'com.ablanco.zoomy:zoomy:1.0.0'
    compile 'xyz.danoz:recyclerviewfastscroller:0.1.3'
    compile 'com.irozon.sneaker:sneaker:1.0.2'
    compile 'com.kyanogen.signatureview:signature-view:1.2'
    compile 'com.getkeepsafe.taptargetview:taptargetview:1.11.0'
    compile 'com.rengwuxian.materialedittext:library:2.1.4'
    implementation 'com.github.takusemba:multisnaprecyclerview:1.3.3'
    compile 'com.github.chahine:pageindicator:0.2.6'
    compile 'com.github.florent37:tutoshowcase:1.0.1'
    implementation 'io.supercharge:shimmerlayout:2.1.0'

    compile 'com.github.yeriomin:play-store-api:0.19'
    compile 'com.squareup.okhttp3:okhttp:3.8.1'

    implementation 'com.github.antonKozyriatskyi:CircularProgressIndicator:1.0.5'}

configurations.all {
    exclude group: 'com.android.support', module: 'support-v13'
}
apply plugin: 'com.google.gms.google-services'

ANSWER

Answered 2018-Jun-11 at 07:07

Since you are developing using Android Studio 3.1.3, try to update your build.gradle dependencies and plugin as well to their latest version.

And move your repository google() to the buildscript.

You can try this:

Top-level build.gradle

apply from: 'buildsystem/dependencies.gradle'

buildscript {
   repositories {
      jcenter()
      mavenCentral()
      maven { url 'https://maven.fabric.io/public' }
      google()
      //maven {
      //    url 'https://maven.google.com'
      //}
    }
    dependencies {
       //Update it to the latest version: 3.1.3
       classpath 'com.android.tools.build:gradle:3.1.3' 
       classpath 'com.frogermcs.androiddevmetrics:androiddevmetrics-plugin:0.5'
       classpath 'com.google.gms:google-services:3.1.2'
       classpath 'io.fabric.tools:gradle:1.25.1'
    }
}

allprojects {
   ext {
     androidApplicationId = 'com.medikoe.connect'
     androidVersionCode = 23
     androidVersionName = "1.7.2"
     testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
     testApplicationId = 'com.medikoe.test'
   }

   repositories {
     google()
     jcenter()
   }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
// Remove these lines
// repositories {
//    google()
// }

Some other tips:

For your app build.gradle, try to change compile to implementation, since it will be deprecated soon.

Source https://stackoverflow.com/questions/50781608

Community Discussions, Code Snippets contain sources that include Stack Exchange Network

Vulnerabilities

No vulnerabilities reported

Install RecyclerViewPager

You can download it from GitHub, Maven.
You can use RecyclerViewPager like any standard Java library. Please include the the jar files in your classpath. You can also use any IDE and you can run and debug the RecyclerViewPager component as you would do with any other Java program. Best practice is to use a build tool that supports dependency management such as Maven or Gradle. For Maven installation, please refer maven.apache.org. For Gradle installation, please refer gradle.org .

Support

For any new features, suggestions and bugs create an issue on GitHub. If you have any questions check and ask questions on community page Stack Overflow .

DOWNLOAD this Library from

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

Explore Related Topics

Share this Page

share link
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

  • © 2022 Open Weaver Inc.