recyclerview problem when scrooling right half screen - android

When scrolling from left half screen of the mobile scrolling is happening but when i scroll from right half screen scroling is not happening.
This is my xml clode.
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/postRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_margin="2dp"
android:nestedScrollingEnabled="false">
</androidx.recyclerview.widget.RecyclerView>
My Java code is
val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.VERTICAL
binding.postRecyclerView.layoutManager = layoutManager
binding.postRecyclerView.setHasFixedSize(false)
enter code here

Finally after so much search i found the solution. Actually i have used Floating button in that page due to that hieght from right side scrolling was not happend in Recyclerview.

Related

Android Recyclerview not remeasuring its height

My application has a lot of nested recycler views , In one of those I have a layout which holds an image and a textview like this.
The text view is an indicator which would disappear when the user opens that specific course.
And it would become something like this :
Since the indicator is present only on some of the courses , the indicator might disappear (view.gone) and appear (view.visible) on certain conditions.
This is the recyclerview code that holds these courses.
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_video_packs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_16dp"
android:clipToPadding="false"
android:paddingEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/rv_continue_watching" />
Notice that the recycler view is a wrap content.
When there is a case of multiple courses , some courses might not contain the new video indicator. And if those courses with no indicator is present on the screen then the recyclerview would wrap its height to only hold on to the course image , something like this.
but the issue is , when we scroll horizontally , some courses might contain the indicator , meaning that the recyclerview should increase its height accordingly to accommodate the indicator as well .
Instead recyclerview fails to update its height to wrap around both the view hence resulting in this incomplete view.
This is happening because the recyclerview was unable to update its height when scrolling hence making the view cut in half.
I have tried multiple ways to fix this like ,
Setting setHasFixedSize to false etc . But didnt seem to work
This is happening only sometimes.
The only viable solution now is to fix the recycler view height to a specific height so that it holds both the views.
But I want a more scalable and optimum solution if possible for this .
Is there any way to make recyclerview recalculate its height ?
Recyclerview Item view code.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:clickable="true"
android:orientation="vertical"
>
<ImageView
android:id="#+id/iv_learn_item"
android:visibility="invisible"
android:layout_width="134dp"
android:layout_height="200dp"
android:adjustViewBounds="true"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:foreground="?attr/selectableItemBackground"
/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/video_update_tv_guideline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintGuide_begin="195dp"
android:orientation="horizontal"
/>
<TextView
android:id="#+id/video_update_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="#id/iv_learn_item"
app:layout_constraintEnd_toEndOf="#id/iv_learn_item"
app:layout_constraintTop_toBottomOf="#+id/video_update_tv_guideline"
android:layout_marginStart="#dimen/dimen_11dp"
android:layout_marginEnd="#dimen/dimen_11dp"
style="#style/content_update_pill"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Adapter code
rvVideoPacks.layoutManager =
LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false)
rvVideoPacks.setHasFixedSize(false)
rvVideoPacks.itemAnimator = null
rvVideoPacks.isNestedScrollingEnabled = true
rvVideoPacks.adapter = videoPackAdapter
EDIT :
I have also tried to make the indicator invisible , but that just creates an extra space at the bottom , making it look bad.
I want the recyclerview to adjust its height accordingly.
One way to fix this issue is give fix height to main ConstraintLayout if possible for your layout.

Viewpager2 swipe gesture only horizontally Android

How can I prevent diagonal swipe on Viewpager2, only allow to swipe if gesture is strictly horizontally.
I dot not want this
I want this
This how make it work
source from Medium
fun ViewPager2.reduceDragSensitivity() {
val recyclerViewField = ViewPager2::class.java.getDeclaredField("mRecyclerView")
recyclerViewField.isAccessible = true
val recyclerView = recyclerViewField.get(this) as RecyclerView
val touchSlopField = RecyclerView::class.java.getDeclaredField("mTouchSlop")
touchSlopField.isAccessible = true
val touchSlop = touchSlopField.get(recyclerView) as Int
touchSlopField.set(recyclerView, touchSlop*3)
}
Also you must have Recyclerview like this
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layerType="hardware"
android:orientation="vertical"
android:overScrollMode="never"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerArtist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:clipToPadding="false"
android:layerType="hardware"
android:orientation="vertical"
android:overScrollMode="never" />
</androidx.core.widget.NestedScrollView>
also
ViewCompat.setNestedScrollingEnabled(recyclerView,false)
I found this awesome article that addresses this issue in depth. The problem is actually with the recyclerview which is the backbone of the new viewpager2.
Many times, even though an horizontal gesture is performed on a child RecyclerView, the parent RecyclerView kicks in and intercepts the touch event instead of the child RecyclerView, resulting in a small vertical scroll instead of an horizontal scroll. This actually happens when the scroll gesture is not perfectly horizontal. It’s actually diagonal, even if you can see that the vertical distance of the gesture is small compared to its horizontal distance and its intent was clearly horizontal
Further, the author of the article explains the cause of this behavior by digging into the recyclerview code
In summary, the problem is that when the RecyclerView is configured to scroll in a single direction as it’s usually the case, it doesn’t test if the global shape of the gesture is more horizontal (abs(dx) > abs(dy)) or vertical ( abs(dy) > abs(dx)) before deciding to intercept it, potentially conflicting with a child view scrolling in the opposite direction.
Here's the article link. Scroll to the bottom, you'll find the solution. I think this solution is better than modifying the touch slop value to reduce the drag sensitivity.

Loading items into a RecyclerView with stackFromEnd = true doesn't scroll to bottom

I have a chat app and i'm trying to ensure that when the user opens the screen the items display from the bottom with the most recent right above the input area. I've used a custom view for the input area and both the recycler and the custom view are within a ConstraintLayout.
My problem is that when I load items into the list, if the number of items is greater than the size of the recycler, it will not fully show the last item. When I make the input area visibility = Gone then the items display properly at the bottom. It's almost like the recyclers LinearLayoutManager thinks that the height of the Recycler is of the screen without the input field. I've manually printed out the size of the views and used layout inspector to ensure that the recycler is indeed drawn in the correct location (above the input and below the navigation bar).
What could be causing such an issue? I should note that whenever you click on a Linkified text in a chat bubble that the list scrolls a small amount equal to the offset that's incorrect when you open the screen. Clearly something is not measuring right here and not sure where to begin.
I should also note that if I try to add a post with smoothScroll it will go to the end of the list but then whenever a new item appears in the list from sending a message the items above the most recently added one seem to jump up a little with an unnecessary animation. It's like the last item in the list is in some special state?
if you're curious this is my scrolling function:
private fun scrollToFirstItem(dueToKeyboard: Boolean = false) {
val stackingFromEnd = (recyclerView.layoutManager as LinearLayoutManager).stackFromEnd
if (stackingFromEnd) {
val firstPosition = recyclerView.adapter?.itemCount?: 0 - 1
if (dueToKeyboard ) {
recyclerView.scrollBy(0, Integer.MAX_VALUE)
} else {
recyclerView.scrollToPosition(firstPosition)
}
recyclerView.post { recyclerView.smoothScrollToPosition(firstPosition) }
} else {
recyclerView.scrollToPosition(0)
}
}
And my xml for my fragment:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/searchView"
layout="#layout/compose_new_message_include"/>
<com.airbnb.epoxy.EpoxyRecyclerView
android:id="#+id/conversationEpoxyRV"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scrollbars="vertical"
app:layout_constraintTop_toBottomOf="#id/searchView"
app:layout_constraintBottom_toTopOf="#id/composeView"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
tools:listitem="#layout/conversation_item_inbound"/>
<include layout="#layout/conversation_pip_view"
android:id="#+id/selectedMediaContainer"/>
<****.ComposeView
android:id="#+id/composeView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Any help is appreciated, I'm so lost..
To me this feels like more of an issue in the layout rather than in the scrolling function. I hope that this can be resolved easily if you use a Relative Layout instead of a Linear Layout. So in case if it may be helpful, i'll add my solution below using a Relative Layout.
<RelativeLayout
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/input_field">
</androidx.recyclerview.widget.RecyclerView>
<EditText
android:id="#+id/input_field"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
So in case if it is not clear what i have done, an EditText element is set to align to the bottom of parent which is a Relative Layout. Then a RecyclerView is added so that RecylerView will be always constraint above the EditText but not overlapped.
Everything looks fine, except the restrictions you added to recycleview design, I see that you are setting the recycleview to top of searchView app:layout_constraintTop_toBottomOf="#id/searchView" while the searchView view is not restricted as should it be.
It's better when using ConstraintLayout to restrict every view inorder avoid unexpected behaviors, because every view has a relation with other view will be effected with other view (x, y), therefore your searchView should be look like:
<include
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
layout="#layout/compose_new_message_include"/>
Give the size of arraylist of your data to smoothScrollToPosition
var linearLayoutManager = LinearLayoutManager(context)
recyclerView.layoutManager=linearLayoutManager
recyclerView.adapter=adapter
linearLayoutManager.setStackFromEnd(true)
adapter.notifyDataSetChanged()
recyclerView.smoothScrollToPosition(dataMsgs.size())
I had a similar problem some years back and I solved it with scrollToPositionWithOffset (support library). Of course this was before constraint was used....
I kept my newer items at the bottom, too. The code I used for scrolling after inserting an item was:
((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(getItemCount() - 1, 0);
To scroll and adjust the awkward positioning after removing an item, I used:
View vTopCard = layoutManager.getChildAt(0);
// Get its adapter position
final int topCardPos = layoutManager.getPosition(vTopCard);
// Get top of card position
int topOffset = layoutManager.getDecoratedTop(vTopCard);
int cardMargin = (int) getResources().getDimension(R.dimen.card_vertical_margin);
((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(topCardPos, topOffset - cardMargin);
The getDecoratedTop helps with the "bounce" and final positioning, as does factoring the vertical margin.
I hope this helps (at least part of your issue)! Like I said, this is old code (when I was learning to program Android and Java at the same time), so if I left something out, let me know and I'll reexamine the app's code in more detail (though, I'll have to find the time).
Good luck!

Immediately snap Recyclerview

My app uses a RecyclerView with a LinearLayoutManager and a LinearSnapHelper.
At the start of my app I want my RecyclerView to immediately scroll to a snap position without any animation.
I know of RecyclerView.smoothScrollToPosition() but that animates the scroll. Any ideas how to achieve this? Thanks! :)
Code
Set up the RecyclerView:
mRecyclerRooms = (RecyclerView) mView.findViewById(R.id.recyclerRooms);
mRoomsLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
mRecyclerRooms.setLayoutManager(mRoomsLayoutManager);
mSnapHelperRooms = new LinearSnapHelper();
mSnapHelperRooms.attachToRecyclerView(mRecyclerRooms);
mRecyclerRooms.addOnScrollListener(mRoomScrollListener);
XML for RecyclerView:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerRooms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
mRoomScrollListener() is used to calculate the distance to snap via float distanceFromSnap = abs(mSnapHelperRooms.calculateDistanceToFinalSnap(mRecyclerRooms.getLayoutManager(), view)[0]); and then scale the item accordingly. The idea is to make items get bigger and have more alpha when they are near the snap position which should be the center of the RecyclerView.
Use this
recyclerViewList.scrollToPosition(position);
http://www.devexchanges.info/2016/09/android-tip-recyclerview-snapping-with.html?m=1
This might help. But I am worried that Linear snap helper is enough for snapping at center.

RecyclerView inside HorizontalScrollView Android

I am using a Recycler view inside a Horizontal Scroll View to display threaded comments like below:
Comment1
Comment1Child1
Comment1Child2
Comment1Child2Child1
Comment1Child3 Comment2
etc.
I have done this with the following XML:
<HorizontalScrollView
android:id="#+id/horizontalScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbarSize="2dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/commentRV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginLeft="47dp"
android:minWidth="200dp" />
</HorizontalScrollView>
You'll see I set a min width of 200dp so that the comments never get too small and the deeper down the thread they go the further off screen it will be pushed.
It is displaying perfectly but I am unable to scroll horizontally. I can see the scroll bars but I cannot scroll horizontally.
I have fiddled with disabling Touch and nestedScrollingEnabled in the RV but not sure what the real solution is. Nothing seems to work?
Any help would be much appreciated! Thank you
Remove HorizontalScrollView you can give LinearLayoutManager with horizontal orientation like this
LinearLayoutManager layoutManager= new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
reclyclerView.setLayoutManager(layoutManager);
//recyclerView.setMinimumWidth(200); optional for width if u need

Categories

Resources