Android Nested RecyclerView Change Angle Of Scroll
I have horizontal recyclerViews in vertical RecyclerView. To scroll horizontally I should swipe from 45 degrees to -45 degree. To scroll vertically from 90 degrees to 45 degrees. Is any possibility to override this?
For example, vertical scroll works only with the swipe from 105 to 75 degrees. Else, horizontal scroll.
android android-recyclerview recycler-adapter
add a comment |
I have horizontal recyclerViews in vertical RecyclerView. To scroll horizontally I should swipe from 45 degrees to -45 degree. To scroll vertically from 90 degrees to 45 degrees. Is any possibility to override this?
For example, vertical scroll works only with the swipe from 105 to 75 degrees. Else, horizontal scroll.
android android-recyclerview recycler-adapter
add a comment |
I have horizontal recyclerViews in vertical RecyclerView. To scroll horizontally I should swipe from 45 degrees to -45 degree. To scroll vertically from 90 degrees to 45 degrees. Is any possibility to override this?
For example, vertical scroll works only with the swipe from 105 to 75 degrees. Else, horizontal scroll.
android android-recyclerview recycler-adapter
I have horizontal recyclerViews in vertical RecyclerView. To scroll horizontally I should swipe from 45 degrees to -45 degree. To scroll vertically from 90 degrees to 45 degrees. Is any possibility to override this?
For example, vertical scroll works only with the swipe from 105 to 75 degrees. Else, horizontal scroll.
android android-recyclerview recycler-adapter
android android-recyclerview recycler-adapter
edited Nov 27 '18 at 14:13
Jayson Minard
40.4k17114174
40.4k17114174
asked Nov 27 '18 at 8:59
Тигран ЧилингарянТигран Чилингарян
84
84
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You need to create MainVerticalRecyclerView
like this:
open class MainVerticalRecyclerView : RecyclerView {
private var scrollPointerId = -1
private var pointTouchX = 0
private var pointTouchY = 0
private var touchSlopType = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
val vc = ViewConfiguration.get(context)
touchSlopType = vc.scaledTouchSlop
}
override fun setScrollingTouchSlop(slopConstant: Int) {
super.setScrollingTouchSlop(slopConstant)
val vc = ViewConfiguration.get(context)
when (slopConstant) {
TOUCH_SLOP_DEFAULT -> touchSlopType = vc.scaledTouchSlop
TOUCH_SLOP_PAGING -> touchSlopType = vc.scaledPagingTouchSlop
}
}
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (e == null) {
return false
}
val action = e.actionMasked
val actionIndex = e.actionIndex
when (action) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
pointTouchX = Math.round(e.x + 0.5f)
pointTouchY = Math.round(e.y + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_POINTER_DOWN -> {
scrollPointerId = e.getPointerId(actionIndex)
pointTouchX = Math.round(e.getX(actionIndex) + 0.5f)
pointTouchY = Math.round(e.getY(actionIndex) + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index < 0) {
return false
}
val x = Math.round(e.getX(index) + 0.5f)
val y = Math.round(e.getY(index) + 0.5f)
if (scrollState != SCROLL_STATE_DRAGGING) {
val dx = x - pointTouchX
val dy = y - pointTouchY
var startScroll = false
if (layoutManager?.canScrollHorizontally() == true && Math.abs(dx) > touchSlopType && (layoutManager?.canScrollVertically() == true || Math.abs(dx) > Math.abs(dy))) {
startScroll = true
}
if (layoutManager?.canScrollVertically() == true && Math.abs(dy) > touchSlopType && (layoutManager?.canScrollHorizontally() == true || Math.abs(dy) > Math.abs(dx))) {
startScroll = true
}
return startScroll && super.onInterceptTouchEvent(e)
}
return super.onInterceptTouchEvent(e)
}
else -> {
return super.onInterceptTouchEvent(e)
}
}
}
}
and create ChildHorizontalRecyclerView
for other nested RecyclerView
inside main RecyclerView
like this:
class ChildHorizontalRecyclerView : MainVerticalRecyclerView {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
if you want scroll like in PlayStore
when you touch HorizontalChildRecyclerView
need write:
recyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_DOWN && rv.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
rv.stopScroll()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53495948%2fandroid-nested-recyclerview-change-angle-of-scroll%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You need to create MainVerticalRecyclerView
like this:
open class MainVerticalRecyclerView : RecyclerView {
private var scrollPointerId = -1
private var pointTouchX = 0
private var pointTouchY = 0
private var touchSlopType = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
val vc = ViewConfiguration.get(context)
touchSlopType = vc.scaledTouchSlop
}
override fun setScrollingTouchSlop(slopConstant: Int) {
super.setScrollingTouchSlop(slopConstant)
val vc = ViewConfiguration.get(context)
when (slopConstant) {
TOUCH_SLOP_DEFAULT -> touchSlopType = vc.scaledTouchSlop
TOUCH_SLOP_PAGING -> touchSlopType = vc.scaledPagingTouchSlop
}
}
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (e == null) {
return false
}
val action = e.actionMasked
val actionIndex = e.actionIndex
when (action) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
pointTouchX = Math.round(e.x + 0.5f)
pointTouchY = Math.round(e.y + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_POINTER_DOWN -> {
scrollPointerId = e.getPointerId(actionIndex)
pointTouchX = Math.round(e.getX(actionIndex) + 0.5f)
pointTouchY = Math.round(e.getY(actionIndex) + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index < 0) {
return false
}
val x = Math.round(e.getX(index) + 0.5f)
val y = Math.round(e.getY(index) + 0.5f)
if (scrollState != SCROLL_STATE_DRAGGING) {
val dx = x - pointTouchX
val dy = y - pointTouchY
var startScroll = false
if (layoutManager?.canScrollHorizontally() == true && Math.abs(dx) > touchSlopType && (layoutManager?.canScrollVertically() == true || Math.abs(dx) > Math.abs(dy))) {
startScroll = true
}
if (layoutManager?.canScrollVertically() == true && Math.abs(dy) > touchSlopType && (layoutManager?.canScrollHorizontally() == true || Math.abs(dy) > Math.abs(dx))) {
startScroll = true
}
return startScroll && super.onInterceptTouchEvent(e)
}
return super.onInterceptTouchEvent(e)
}
else -> {
return super.onInterceptTouchEvent(e)
}
}
}
}
and create ChildHorizontalRecyclerView
for other nested RecyclerView
inside main RecyclerView
like this:
class ChildHorizontalRecyclerView : MainVerticalRecyclerView {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
if you want scroll like in PlayStore
when you touch HorizontalChildRecyclerView
need write:
recyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_DOWN && rv.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
rv.stopScroll()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
add a comment |
You need to create MainVerticalRecyclerView
like this:
open class MainVerticalRecyclerView : RecyclerView {
private var scrollPointerId = -1
private var pointTouchX = 0
private var pointTouchY = 0
private var touchSlopType = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
val vc = ViewConfiguration.get(context)
touchSlopType = vc.scaledTouchSlop
}
override fun setScrollingTouchSlop(slopConstant: Int) {
super.setScrollingTouchSlop(slopConstant)
val vc = ViewConfiguration.get(context)
when (slopConstant) {
TOUCH_SLOP_DEFAULT -> touchSlopType = vc.scaledTouchSlop
TOUCH_SLOP_PAGING -> touchSlopType = vc.scaledPagingTouchSlop
}
}
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (e == null) {
return false
}
val action = e.actionMasked
val actionIndex = e.actionIndex
when (action) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
pointTouchX = Math.round(e.x + 0.5f)
pointTouchY = Math.round(e.y + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_POINTER_DOWN -> {
scrollPointerId = e.getPointerId(actionIndex)
pointTouchX = Math.round(e.getX(actionIndex) + 0.5f)
pointTouchY = Math.round(e.getY(actionIndex) + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index < 0) {
return false
}
val x = Math.round(e.getX(index) + 0.5f)
val y = Math.round(e.getY(index) + 0.5f)
if (scrollState != SCROLL_STATE_DRAGGING) {
val dx = x - pointTouchX
val dy = y - pointTouchY
var startScroll = false
if (layoutManager?.canScrollHorizontally() == true && Math.abs(dx) > touchSlopType && (layoutManager?.canScrollVertically() == true || Math.abs(dx) > Math.abs(dy))) {
startScroll = true
}
if (layoutManager?.canScrollVertically() == true && Math.abs(dy) > touchSlopType && (layoutManager?.canScrollHorizontally() == true || Math.abs(dy) > Math.abs(dx))) {
startScroll = true
}
return startScroll && super.onInterceptTouchEvent(e)
}
return super.onInterceptTouchEvent(e)
}
else -> {
return super.onInterceptTouchEvent(e)
}
}
}
}
and create ChildHorizontalRecyclerView
for other nested RecyclerView
inside main RecyclerView
like this:
class ChildHorizontalRecyclerView : MainVerticalRecyclerView {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
if you want scroll like in PlayStore
when you touch HorizontalChildRecyclerView
need write:
recyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_DOWN && rv.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
rv.stopScroll()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
add a comment |
You need to create MainVerticalRecyclerView
like this:
open class MainVerticalRecyclerView : RecyclerView {
private var scrollPointerId = -1
private var pointTouchX = 0
private var pointTouchY = 0
private var touchSlopType = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
val vc = ViewConfiguration.get(context)
touchSlopType = vc.scaledTouchSlop
}
override fun setScrollingTouchSlop(slopConstant: Int) {
super.setScrollingTouchSlop(slopConstant)
val vc = ViewConfiguration.get(context)
when (slopConstant) {
TOUCH_SLOP_DEFAULT -> touchSlopType = vc.scaledTouchSlop
TOUCH_SLOP_PAGING -> touchSlopType = vc.scaledPagingTouchSlop
}
}
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (e == null) {
return false
}
val action = e.actionMasked
val actionIndex = e.actionIndex
when (action) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
pointTouchX = Math.round(e.x + 0.5f)
pointTouchY = Math.round(e.y + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_POINTER_DOWN -> {
scrollPointerId = e.getPointerId(actionIndex)
pointTouchX = Math.round(e.getX(actionIndex) + 0.5f)
pointTouchY = Math.round(e.getY(actionIndex) + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index < 0) {
return false
}
val x = Math.round(e.getX(index) + 0.5f)
val y = Math.round(e.getY(index) + 0.5f)
if (scrollState != SCROLL_STATE_DRAGGING) {
val dx = x - pointTouchX
val dy = y - pointTouchY
var startScroll = false
if (layoutManager?.canScrollHorizontally() == true && Math.abs(dx) > touchSlopType && (layoutManager?.canScrollVertically() == true || Math.abs(dx) > Math.abs(dy))) {
startScroll = true
}
if (layoutManager?.canScrollVertically() == true && Math.abs(dy) > touchSlopType && (layoutManager?.canScrollHorizontally() == true || Math.abs(dy) > Math.abs(dx))) {
startScroll = true
}
return startScroll && super.onInterceptTouchEvent(e)
}
return super.onInterceptTouchEvent(e)
}
else -> {
return super.onInterceptTouchEvent(e)
}
}
}
}
and create ChildHorizontalRecyclerView
for other nested RecyclerView
inside main RecyclerView
like this:
class ChildHorizontalRecyclerView : MainVerticalRecyclerView {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
if you want scroll like in PlayStore
when you touch HorizontalChildRecyclerView
need write:
recyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_DOWN && rv.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
rv.stopScroll()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
You need to create MainVerticalRecyclerView
like this:
open class MainVerticalRecyclerView : RecyclerView {
private var scrollPointerId = -1
private var pointTouchX = 0
private var pointTouchY = 0
private var touchSlopType = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
val vc = ViewConfiguration.get(context)
touchSlopType = vc.scaledTouchSlop
}
override fun setScrollingTouchSlop(slopConstant: Int) {
super.setScrollingTouchSlop(slopConstant)
val vc = ViewConfiguration.get(context)
when (slopConstant) {
TOUCH_SLOP_DEFAULT -> touchSlopType = vc.scaledTouchSlop
TOUCH_SLOP_PAGING -> touchSlopType = vc.scaledPagingTouchSlop
}
}
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (e == null) {
return false
}
val action = e.actionMasked
val actionIndex = e.actionIndex
when (action) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
pointTouchX = Math.round(e.x + 0.5f)
pointTouchY = Math.round(e.y + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_POINTER_DOWN -> {
scrollPointerId = e.getPointerId(actionIndex)
pointTouchX = Math.round(e.getX(actionIndex) + 0.5f)
pointTouchY = Math.round(e.getY(actionIndex) + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index < 0) {
return false
}
val x = Math.round(e.getX(index) + 0.5f)
val y = Math.round(e.getY(index) + 0.5f)
if (scrollState != SCROLL_STATE_DRAGGING) {
val dx = x - pointTouchX
val dy = y - pointTouchY
var startScroll = false
if (layoutManager?.canScrollHorizontally() == true && Math.abs(dx) > touchSlopType && (layoutManager?.canScrollVertically() == true || Math.abs(dx) > Math.abs(dy))) {
startScroll = true
}
if (layoutManager?.canScrollVertically() == true && Math.abs(dy) > touchSlopType && (layoutManager?.canScrollHorizontally() == true || Math.abs(dy) > Math.abs(dx))) {
startScroll = true
}
return startScroll && super.onInterceptTouchEvent(e)
}
return super.onInterceptTouchEvent(e)
}
else -> {
return super.onInterceptTouchEvent(e)
}
}
}
}
and create ChildHorizontalRecyclerView
for other nested RecyclerView
inside main RecyclerView
like this:
class ChildHorizontalRecyclerView : MainVerticalRecyclerView {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
if you want scroll like in PlayStore
when you touch HorizontalChildRecyclerView
need write:
recyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_DOWN && rv.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
rv.stopScroll()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
answered Jan 31 at 11:34
DedmarazmDedmarazm
1212
1212
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53495948%2fandroid-nested-recyclerview-change-angle-of-scroll%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown