Custom ViewPager that allows to block swiping right or left where the ViewPager child fragments set the scroll direction and handle blocked swipe events. The library also comes with an adapter that can handle different view pages views and can control the view pager scrolling from within view pager pages.
repositories {
maven {
url "https://jitpack.io"
}
}
dependencies {
implementation 'com.github.kibotu:SwipeDirectionViewPager:-SNAPSHOT'
}
1 Create adapter
// use Fragment#childFragmentManager in nested fragments
var adapter: ViewPagerPresenterAdapter<PageModel, ViewPagerModel> = ViewPagerPresenterAdapter(supportFragmentManager)
2 add to view pager
viewPager.adapter = adapter
3 add listeners
adapter.swipeLeftEdgeListener = Runnable {
snackbar(this, "has swiped left on first page")
}
adapter.swipeRightEdgeListener = Runnable {
snackbar(this, "has swiped right on last page")
}
4 add view pager fragments
(0 until 5).forEach {
adapter.append(PageModel(text = "Page $it")) { TextPage() }
adapter.append(PageModel(imageUrl = createRandomImageUrl())) { ImagePage() }
}
// don't forget to notify updates
adapter.notifyDataSetChanged()
5 implement ViewPagerPresenterAdapter.ViewPagerPresenter<PageModel, ViewPagerModel> interface in your view pager fragments, e.g.:
class Page : Fragment(), ViewPagerPresenterAdapter.ViewPagerPresenter<PageModel, ViewPagerModel> {
/**
* into pages injected adapter
*/
override var viewPagerPresenterAdapter: ViewPagerPresenterAdapter<PageModel, ViewPagerModel>? = null
/**
* gets called when allowSwipeDirection is set and user scrolls to the previous or next page.
* basically, you set 'only swipe left' and when user swipes right, you can give the user feedback
*/
override fun onSwipeIntercepted(direction: SwipeDirection){
}
/**
* set page specific swipe allowed direction
*/
override fun allowSwipeDirection(): SwipeDirection {
return SwipeDirection.ALL
}
}
Adding a new page to the end
adapter.append(PageModel(text = "Page $it")) { TextPage() }
Adding a new page to the beginning
adapter.prepend(PageModel(text = "Page $it")) { TextPage() }
var fragment = viewPagerPresenterAdapter?.getFragment(adapterPosition); // don't use #getItemPosition, it interferes with fragment updates
using adapter position
var model = viewPagerPresenterAdapter?.model(adapterPosition);
using a fragment
var model = viewPagerPresenterAdapter?.model(fragment);
Note: neither models nor fragments are unique, it's returning simply the first one found
using a fragment
var position = viewPagerPresenterAdapter?.indexOf(fragment);
using a model
var position = viewPagerPresenterAdapter?.indexOf(model);
ViewPager fragments need to inherit form [Updatable]. the #update(t: T) gets called in order to update fragments without the need to recreate them. (which would be the case using #notifyDataSetChanged)
replace model at given position
viewPagerPresenterAdapter?.update(PageModel(text = "updated model at position 0"), 0)
replacing a model at given criteria
viewPagerPresenterAdapter?.update(PageModel(text = "update replaced model by filter"), { it.text == "Page 2" })
modifying model data in place
viewPagerPresenterAdapter?.updateInPlace(filter = { it.text == "Page 3" }, modify = { it.text = "updated model in place by filter" })
PageModel - can be any data model, which can be bound to view pager page and can be accessed inside pages.
var model : PageModel = viewPagerPresenterAdapter?.model(fragment)
// or
var model : PageModel = viewPagerPresenterAdapter?.model(adapterPosition)
ViewPagerModel - meant to be a shared object between all pages and its parent view pager holder
var viewPagerModel : ViewPagerModel = viewPagerPresenterAdapter?.viewPagerModel
Allows view pager pages to control view pager scrolls.
viewPagerPresenterAdapter.scrollHandler
/**
* Skips a given amount of pages.
*/
fun skip(amount: Int, smooth: Boolean = true)
/**
* Scrolls to a given position.
*/
fun scrollTo(position: Int, smooth: Boolean = true)
/**
* Scrolls to next page.
*/
fun scrollToNextPage()
/**
* Scrolls to previous page.
*/
fun scrollToPreviousPage()
/**
* @return true if current page is first.
*/
fun isFirstPage(): Boolean
/**
* @return true if current page is last.
*/
fun isLastPage(): Boolean
net.kibotu.swipedirectionviewpager.SwipeDirectionViewPagerRtl, which uses duolingo's RtlViewPager
implementation "com.android.support:support-core-ui:$support_version"
implementation 'com.duolingo.open:rtl-viewpager:1.0.3'
graldew clean build
gradlew clean assembleRelease test javadoc
- JDK8
- Android Build Tools 27.0.2
- Android SDK 27
Copyright 2018 Jan Rabe 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.