I'm having an issue maybe for misunderstanding how android recyclerview scroll works. I hope this can help the community too, and if you answer please provide information about the causes and fixes in a detailed way. Thanks.
The main problem I'm having is that I have a stack from end true RecyclerView that shows firebase real-time database messages. When a child is added, removed etc I call my method display messages witch sets the adapter with the new messages list and then it scrolls to the last position. The problem is that is not scrolling to the last position as you will see in the video ill show here.
Error video (Click here)
I leave here the ChatFragment Class which is the one used. Also the layout for the ChatFragment.
ChatFragment:
private void setAdapter() {
loadingLayout.setVisibility(View.VISIBLE);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setStackFromEnd(true);
recyclerViewMessageList.setLayoutManager(linearLayoutManager);
}
private void displayMessages(List<Message> messages) {
if (messages.size() > 0) {
MessageAdapter messageAdapter = new MessageAdapter(getActivity(), messages);
recyclerViewMessageList.setAdapter(messageAdapter);
recyclerViewMessageList.scrollToPosition(messages.size() - 1);
}
loadingLayout.setVisibility(View.GONE);
lottieAnimationViewLoading.cancelAnimation();
}
fragment_chat layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.ChatFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewMessageList"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/constraintLayoutChatInput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayoutChatInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:elevation="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recyclerViewMessageList">
<EditText
android:id="#+id/editTextChatSendMessage"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="24dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="10dp"
android:autofillHints="#string/write_message"
android:background="#android:color/transparent"
android:ems="10"
android:hint="#string/write_message"
android:inputType="textMultiLine"
android:maxLines="6"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/imageViewChatSendMessage"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="#+id/imageViewChatSendMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="10dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="8dp"
android:src="#drawable/ic_send_blue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/editTextChatSendMessage"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<include
layout="#layout/loading_messages_layout"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
EDIT:
I have solved it by changing the order of setting the layout manager:
private void setAdapter() {
loadingLayout.setVisibility(View.VISIBLE);
}
private void displayMessages(List<Message> messages) {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setStackFromEnd(true);
recyclerViewMessageList.setLayoutManager(linearLayoutManager);
MessageAdapter messageAdapter = new MessageAdapter(getActivity(), messages);
recyclerViewMessageList.setAdapter(messageAdapter);
recyclerViewMessageList.scrollToPosition(messages.size() - 1);
loadingLayout.setVisibility(View.GONE);
lottieAnimationViewLoading.cancelAnimation();
}
what happens if you do not use (on this line recyclerViewMessageList.scrollToPosition(messages.size() - 2);) the -2 because what i saw on the video it was openning on correct position but after scrolls to -2 position
Related
My issue is: ui freezes when recycler view adapter start listening
my xml Code is as below
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainAdminPackage.AdminDashboardActivity">
<!--Navigation Drawer Setup-->
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/home_background"
app:headerLayout="#layout/menu_header_design"
app:menu="#menu/main_menu" />
<LinearLayout
android:id="#+id/contentViewLl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/home_background"
android:orientation="vertical">
<!--Navigation Menu and Fab Layout Setup-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="68dp"
android:padding="20dp">
<!--Menu Button-->
<ImageView
android:id="#+id/menuIcon"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="4dp"
android:layout_centerVertical="true"
android:focusable="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:src="#drawable/ic_menu_icon_dark_gray"
app:tint="#color/icon_color"
android:contentDescription="#null"/>
<!--FAB Layout System-->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/addQuestionPollCl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="#+id/menuIcon"
android:minHeight="68dp">
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
<!--Nested Scroll View-->
<androidx.core.widget.NestedScrollView
android:id="#+id/dashboardNestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!--Main Container Layout-->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--LAYOUT FOR SEARCH WINDOW AND START DIALOG-->
<RelativeLayout
android:id="#+id/searchAndSloganRl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
</RelativeLayout>
<!--CATEGORIES BUTTON-->
<LinearLayout
android:id="#+id/categoryButtonsLl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:orientation="horizontal"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/searchAndSloganRl"
app:layout_constraintBottom_toBottomOf="parent">
</LinearLayout>
<!--FEATURED COURSE LAYOUT-->
<RelativeLayout
android:id="#+id/featuredCourseRl"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginBottom="10dp"
android:background="#color/banner_background_light"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/categoryButtonsLl"
app:layout_constraintBottom_toBottomOf="parent">
<!--Banner-->
<!--Recycler View for Featured Courses-->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/featuredCoursesRv"
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_toEndOf="#id/featuredBackground"
android:background="#color/home_background"
tools:listitem="#layout/row_featured_courses" />
</RelativeLayout>
<!--NEWS FEED-->
<androidx.appcompat.widget.LinearLayoutCompat
android:visibility="visible"
android:id="#+id/newsFeedMiniLlc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:minHeight="100dp"
android:orientation="vertical"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/featuredCourseRl"
app:layout_constraintBottom_toBottomOf="parent">
<!--News Feed Recycler View-->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/newsFeedRv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="horizontal"
android:background="#color/home_background"
tools:listitem="#layout/row_news_feed_dashboard" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!--NOTES CATEGORIES-->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/notesCategoryLlc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="vertical"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/newsFeedMiniLlc"
app:layout_constraintBottom_toBottomOf="parent">
</androidx.appcompat.widget.LinearLayoutCompat>
<!--ASK QUESTION RECYCLER VIEW LAYOUT-->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/askedQuestionMiniLlc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:orientation="vertical"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/notesCategoryLlc"
app:layout_constraintBottom_toBottomOf="parent">
<!--Recycler View for Asked Questions-->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/askQuestionRv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical"
tools:itemCount="10"
android:nestedScrollingEnabled="false"
tools:listitem="#layout/row_asked_question" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
java code for recycler views
//For hiding the FAB when nest scroll is scrolled
dashboardNestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener(){
#Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){
//For Adapters to Start listening
if(scrollY - oldScrollY != 0) {
if(isVisible(newsFeedMiniLlc)) {
indexOtherPost++;
if(indexOtherPost == 1) {
adapterNewsFeedListFireStoreDashBoard.startListening();
Log.d("NESTED_CHILD", "onScrollChange: indexOtherPost: " + indexOtherPost);
}
}
//Log.d("NESTED_CHILD", "onScrollChange: otherPostMiniLlc: " + isVisible(otherPostMiniLlc));
if(isVisible(askedQuestionMiniLlc)) {
indexAskedQuestion++;
if(indexAskedQuestion == 1) {
adapterAskedQuestionsFireStore.startListening();
Log.d("NESTED_CHILD", "onScrollChange: indexAskedQuestion: " + indexAskedQuestion);
}
}
//Log.d("NESTED_CHILD", "onScrollChange: askedQuestionMiniLlc: " + isVisible(askedQuestionMiniLlc));
}
}
});
//Function for getting Visibility of any View or Layout on the Screen
private static boolean isVisible(final View view) {
if (view == null) {
return false;
}
if (!view.isShown()) {
return false;
}
final Rect actualPosition = new Rect();
view.getGlobalVisibleRect(actualPosition);
int widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
int heightPixels = Resources.getSystem().getDisplayMetrics().heightPixels;
final Rect screen = new Rect(0, 0, widthPixels, heightPixels);
return actualPosition.intersect(screen);
}
//For LOADING ASK QUESTIONS
private void loadAskQuestions(){
//for question Recycler view
LinearLayoutManager askQuestionLayoutManager = new LinearLayoutManager(getApplicationContext());
askQuestionLayoutManager.setReverseLayout(false);
askQuestionLayoutManager.setStackFromEnd(false);
askQuestionLayoutManager.setOrientation(RecyclerView.VERTICAL);
askQuestionRv.setLayoutManager(askQuestionLayoutManager);
//get all Question limited to last 10 questions
Query query = FirebaseFirestore.getInstance()
.collection("Asked Questions")
.orderBy("questionId", Query.Direction.DESCENDING)
.limit(10);
FirestoreRecyclerOptions<ModelAskedQuestion> options = new FirestoreRecyclerOptions.Builder<ModelAskedQuestion>()
.setQuery(query, ModelAskedQuestion.class)
.build();
adapterAskedQuestionsFireStore = new AdapterAskedQuestionsFireStore(this, options);
askQuestionRv.setAdapter(adapterAskedQuestionsFireStore);
}
ui freezes when ask question recycler view adapter start listening and ui only freezes for few seconds until all data is loaded in recycler view.
Any one have any solutions ???
More elaboration of the Issue:
1)I have three recycler view under this layout: Two top most Horizontal and last one Vertical in direction.
2)As this is my main dashboard. I have put nested scroll view listener for adapters to start listening when the particular layout containing that recycler view appears on the screen. Top most two adapters and their corresponding recycler views are working perfectly fine.
But when the last recycler view which is vertical in Direction, appears on the screen, It freezes the entire UI, as its adapter starts listening, for few seconds(aprrox. 1-2 seconds).
In this, adapter loads only last 10 items from the server.
I have tried:
1). Fixing the hieght of recyler view.
2). Fixing the height of Layout containing that recycler view.
3). Changed the Main Container Layout From Linear Layout to Constraint Layout.(As It was suggested in one of the comments under that thread(mentioned at the end of this thread)).
4). Tried android:nestedScrollingEnabled="false".
5). Tried app:layout_behavior="#string/appbar_scrolling_view_behavior".
Nothing has worked for this particular problem.
How to get rid of this this freezing of Ui. It should kept scrolling along the items get recycled in recycler view.
It could be same question asked in this thread.
RecyclerView inside NestedScrollview alternative
I'm trying to display a list in a fixed size scrollview, at first it was the first items who weren't showing and I fixed it but now it's the last ones that aren't reachable.
Here is my xml code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
tools:context=".ui.home.AperoDetailFragment">
<TextView
android:id="#+id/name_apero"
android:layout_width="156dp"
android:layout_height="53dp"
android:textSize="18sp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/date_apero"
android:layout_width="238dp"
android:layout_height="53dp"
android:textSize="18sp"
android:ems="10"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.907"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<ScrollView
android:id="#+id/ingredient_apero"
android:layout_width="410dp"
android:layout_height="607dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/ingredient_title_apero"
app:layout_constraintVertical_bias="0.0">
<LinearLayout
android:id="#+id/vertical_layout_ingredient"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
<TextView
android:id="#+id/ingredient_title_apero"
android:layout_width="115dp"
android:layout_height="28dp"
android:text="Liste d'achat:"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.005"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.125" />
</androidx.constraintlayout.widget.ConstraintLayout>
and here is my java code to populate the list:
public class AperoDetailFragment extends Fragment {
private View root;
private Apero detailApero;
public AperoDetailFragment(Apero apero) {
this.detailApero = apero;
}
#Override
public View onCreateView(#NonNull final LayoutInflater inflater,
final ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_detail_apero, container, false);
TextView name = (TextView)root.findViewById(R.id.name_apero);
name.setText(detailApero.getName());
TextView date = (TextView)root.findViewById(R.id.date_apero);
date.setText(detailApero.getDate());
LinearLayout ll = (LinearLayout)root.findViewById(R.id.vertical_layout_ingredient);
LinearLayout a = new LinearLayout(root.getContext());
a.setOrientation(LinearLayout.VERTICAL);
for(int i = 0; i < 20; i++)
{
Button b = new Button(root.getContext());
b.setText("Button "+i);
a.addView(b);
}
ll.addView(a);
return root;
}
}
When I scroll I can reach the number 16 but not the other, it's like they are under the layout I don't really know how to explain better.
So the question is how can I scroll my list until the last items ?
There are a few issues with your code: first and foremost if you want to display data as a list you should use a RecyclerView instead of a ScrollView. ScrollViews are there to allow the content (or part of it) in your activity/fragment to be scrollable.
Second, it's not a good practice to set specific sizes to your views, especially when using ConstraintLayout.
Third, onCreateView is meant to be a method that will simply inflate your fragment's layout and return it as a View. For handling the UI, use onViewCreated. That way you will guarantee that your UI will never be handled before your fragment is actually attached to the activity.
So answering your question, use a RecyclerView to display your items as a list instead of the ScrollView and you'll be good to go from there
I have a simple layout, which contains a text view, ImageView, and a recycler view, If i set recycler's view width & height to 0dp, and connects its constraint to parent, it does not render the recycler view.
But if i define height in numbers then it works fine, and renders recyclerview
This is my code
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/blue"
tools:context=".activities.MyActivityV2">
<include layout="#layout/content_more_activity" />
</android.support.design.widget.CoordinatorLayout>
Inner Layout
<android.support.constraint.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"
tools:context=".activities.MyActivityV2"
tools:showIn="#layout/activity_more">
<ImageView
android:id="#+id/imageView23"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/logo" />
<TextView
android:id="#+id/tvLabelMore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="10dp"
android:letterSpacing="0.1"
android:text="MORE"
android:textAllCaps="true"
android:textColor="#color/white"
android:textSize="24dp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="#+id/imageView23"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rvMoreItems"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView23" />
Class File
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
generateDataForRecyclerView();
initRecyclerView();
}
private void init() {
rvMoreItems= findViewById(R.id.rvMoreItems);
}
private void generateDataForRecyclerView() {
MoreDataClass moreDataClass= new MoreDataClass();
moreDataClass.setLabel("AAA");
moreDataClass.setHeaderItem(true);
dataList.add(moreDataClass);
dataList.add(moreDataClass);
}
private void initRecyclerView() {
MoreAdapter moreAdapter= new MoreAdapter(this);
moreAdapter.setData(dataList);
rvMoreItems.setLayoutManager(new LinearLayoutManager(this));
rvMoreItems.setAdapter(moreAdapter);
}
Update this function check below.
private void initRecyclerView() {
MoreAdapter moreAdapter= new MoreAdapter(this);
rvMoreItems.setLayoutManager(new LinearLayoutManager(this));
rvMoreItems.setAdapter(moreAdapter);
moreAdapter.setData(dataList);
}
I have tried many solutions found in StackOverflow now and it is not working on what I was expecting. I want to disable the Recycler View Scroll allowing only the Nested scrollView to scroll my content.
Below is my XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:background="#color/backgroundColor">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/clProfileInfoContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/background_divider"
android:paddingStart="#dimen/ps_container_padding_start"
android:paddingTop="#dimen/ps_container_padding_top"
android:paddingEnd="#dimen/ps_container_padding_end"
android:paddingBottom="#dimen/ps_container_padding_bottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/ivPhotoSelector"
android:layout_width="#dimen/ps_photo_selector_max_width"
android:layout_height="#dimen/ps_photo_selector_max_height"
android:contentDescription="#string/cd_photo_selector"
android:maxWidth="#dimen/ps_photo_selector_max_width"
android:maxHeight="#dimen/ps_photo_selector_max_height"
android:src="#drawable/blue_profile_img_placeholder"
app:civ_circle_background_color="#color/colorAccent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/llUsernameContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="#dimen/ps_username_margin_start"
android:layout_marginTop="#dimen/ps_username_margin_top"
app:layout_constraintStart_toEndOf="#+id/ivPhotoSelector"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tvUserName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center_vertical"
android:text="Username"
android:textColor="#color/tvMainTextColor"
android:textSize="#dimen/ps_username_text_size"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="#+id/ivPhotoSelector"
app:layout_constraintTop_toTopOf="#+id/ivPhotoSelector" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="#+id/btnEditProfile"
style="#style/AppTheme.Button.Blue"
android:adjustViewBounds="true"
android:layout_width="wrap_content"
android:layout_height="#dimen/small_button_height"
android:layout_gravity="end"
android:src="#drawable/edit_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/llLocationContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2"
android:layout_marginStart="#dimen/ps_location_margin_start"
android:layout_marginTop="#dimen/ps_location_margin_top"
app:layout_constraintStart_toEndOf="#+id/ivPhotoSelector"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/llUsernameContainer" >
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tvLocation"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Location"
android:textColor="#color/tvSubTextColor"
android:textSize="#dimen/ps_location_text_size"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/btnShare"
style="#style/AppTheme.Button.Blue"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="#dimen/small_button_height"
android:minWidth="#dimen/small_share_button_min_width"
android:text="#string/ps_label_share_profile"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.appcompat.widget.LinearLayoutCompat>
<me.zhanghai.android.materialratingbar.MaterialRatingBar
android:id="#+id/rbRating"
style="#style/Widget.MaterialRatingBar.RatingBar.Indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/ps_star_rating_margin_start"
android:layout_marginTop="#dimen/ps_star_rating_margin_top"
android:layout_marginEnd="#dimen/ps_star_rating_margin_end"
android:maxHeight="#dimen/ps_star_rating_max_height"
android:minHeight="#dimen/ps_star_rating_min_height"
android:numStars="5"
android:rating="4"
app:layout_constraintStart_toEndOf="#+id/ivPhotoSelector"
app:layout_constraintTop_toBottomOf="#+id/llLocationContainer"
app:mrb_fillBackgroundStars="true"
app:mrb_progressBackgroundTint="#color/rbBackgroundColor"
app:mrb_progressTint="#color/rbProgressBackgroundColor" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/clListingContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#android:color/white"
android:paddingStart="#dimen/ps_container_padding_start"
android:paddingTop="#dimen/ps_container_padding_top"
android:paddingEnd="#dimen/ps_container_padding_end"
android:paddingBottom="#dimen/ps_container_padding_bottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/clProfileInfoContainer"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.AppCompatEditText
android:id="#+id/etShortBio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="#dimen/ps_bio_min_height"
android:gravity="top"
android:padding="#dimen/ps_bio_padding"
android:text="Short Bio About Yourself"
android:inputType="textMultiLine"
android:clickable="false"
android:focusable="false"
android:enabled="false"
android:textColor="#color/labelColor"
android:background="#drawable/white_background"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvListing"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="#dimen/ps_listing_margin_top"
android:paddingTop="#dimen/ps_listing_padding_top"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/etShortBio"
tools:listitem="#layout/row_user_listing_item">
</androidx.recyclerview.widget.RecyclerView>
<com.github.ybq.android.spinkit.SpinKitView
android:id="#+id/skUserListingLoading"
style="#style/SpinKitView.Wave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:SpinKit_Color="#color/colorPrimaryDark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/rvListing" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
and in my activity, I set this to disable the scroll of recycler view
private void setupListing() {
// rvMenuList should not be null
assert rvListing != null;
// initialize Recycler View Adapter
userListingAdapter = new UserListingAdapter(getContext());
// initialize GridLayoutManager
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), gridSize);
// initialize custom divider item decorator
SpacesItemDecoration itemDecorator = new SpacesItemDecoration(10, 10, 30);
rvListing.addItemDecoration(itemDecorator);
ViewCompat.setNestedScrollingEnabled(rvListing, false);
// set the adapter to the recycler view
rvListing.setAdapter(userListingAdapter);
// set the layout manager to the recycler view
rvListing.setLayoutManager(gridLayoutManager);
}
Here's how it looks like
Now I can't scroll the recycler view because of using this code ViewCompat.setNestedScrollingEnabled(rvListing, false); and also I can't scroll the whole content to view the other items of my recycler view.
this may work for you, apply layout behavior:
<android.support.v7.widget.RecyclerView
android:id="#+id/conversation"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Instead of using this line:
ViewCompat.setNestedScrollingEnabled(rvListing, false);
Use this line:
rvListing.setNestedScrollingEnabled(false);
after setting the adapter like this:
private void setupListing() {
// rvMenuList should not be null
assert rvListing != null;
// initialize Recycler View Adapter
userListingAdapter = new UserListingAdapter(getContext());
// initialize GridLayoutManager
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), gridSize);
// initialize custom divider item decorator
SpacesItemDecoration itemDecorator = new SpacesItemDecoration(10, 10, 30);
rvListing.addItemDecoration(itemDecorator);
// set the adapter to the recycler view
rvListing.setAdapter(userListingAdapter);
// set the layout manager to the recycler view
rvListing.setLayoutManager(gridLayoutManager);
rvListing.setHasFixedSize(true);
rvListing.setNestedScrollingEnabled(false);
}
use RecyclerView width
android:layout_height="wrap_content"
finally got the solution. the rvListing.setNestedScrollingEnabled(false); actually works. the issue was the parent height i accidentally set it to 0dp which is suppose to be wrap_content. that was the fix of this issue.
Just override the GridLayoutManager as below, and invoke the method setCanScroll(false).
public class CustomLayoutManager extends GridLayoutManager {
private boolean canScroll;
public CustomLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
/**
*
* #param canScroll true--enable scroll, false--disable scroll
*/
public void setCanScroll(boolean canScroll) {
this.canScroll = canScroll;
}
#Override
public boolean canScrollHorizontally() {
return this.canScroll;
}
#Override
public boolean canScrollVertically() {
return false;
}
}
To disable scrolling of RecyclerView, you can do it programmatically:
recyclerView.setNestedScrollingEnabled(false);
Or through xml:
<android.support.v7.widget.RecyclerView
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
But be careful when your RecyclerView contain many items. It will cause lag
Disable RecyclerView scrolling is bad practice, use RecyclerView with multiple item types instead!
I'm noticing that by adding the HorizontalScrollView it's disabling my ability to select items on my ListView. This seems like a pretty basic/common feature to want to add (I want to be able to swipe my item to the left to offer a delete option) but HorizontalScrollView appears to be incompatible with items that you would like to also touch to select. Note that if I change HorizontalScrollView to a LinearLayout or otherwise the items become selectable.
I was suspecting that touch listeners may be ineffective due to the fact that the swiping capability overrides any other kind of touch, but I can't really think of why it doesn't work otherwise. Can anyone help to resolve this issue? I would like to be able to use HorizontalScrollView alongside a click compatibility (unless there is another way to achieve the same functionality).
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.constraint.ConstraintLayout
android:id="#+id/constraintLayout4"
android:layout_width="384dp"
android:layout_height="110dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/task_view_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="17dp"
android:layout_marginTop="28dp"
android:fontFamily="#font/robotolight"
android:text="#string/task_name"
android:textColor="#android:color/black"
android:textSize="24sp"
app:layout_constraintStart_toEndOf="#+id/task_view_icon"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/task_view_icon"
android:layout_width="77dp"
android:layout_height="77dp"
android:layout_marginStart="17dp"
android:layout_marginTop="17dp"
android:contentDescription="#+string/icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/main_page_icon_switch_x4" />
<TextView
android:id="#+id/task_view_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="36dp"
android:fontFamily="#font/robotolight"
android:text="#string/duration"
android:textColor="#android:color/black"
android:textSize="14sp"
app:layout_constraintStart_toEndOf="#+id/task_view_name"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/task_view_detail"
android:layout_width="228dp"
android:layout_height="31dp"
android:layout_marginStart="17dp"
android:fontFamily="#font/robotolight"
android:text="#string/task_view_detail_literal"
android:textColor="#android:color/black"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="#+id/task_view_icon"
app:layout_constraintTop_toBottomOf="#+id/task_view_name" />
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:id="#+id/task_delete"
android:layout_width="116dp"
android:layout_height="110dp"
android:background="#color/colorPrimary"
app:layout_constraintEnd_toEndOf="#id/constraintLayout4"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/task_delete_literal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="13dp"
android:layout_marginTop="39dp"
android:fontFamily="#font/roboto_regular"
android:text="#string/delete"
android:textColor="#android:color/background_light"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</HorizontalScrollView>
For anyone having this problem, I managed to find a way to workaround this. My problem was that I could not click on the ListView item because of the HorizontalScrollView setup in the XML, however in my case I was using an adapter along with my ListView (that allows you link your listView with your actual list row view) and in that adapter I simply defined and linked the container of the view that I want to press and set an onClickListener.
This goes in your custom adapter:
ConstraintLayout myLayout = convertView.findViewById(R.id.constraintLayout1);
ConstraintLayout anotherLayout = convertView.findViewById(R.id.constraintLayout2); //lets' say I'm using this to delete the item when clicked
myLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent exampleIntent = new Intent(viewParent.getContext(), SomeActivity.class);
}
});
anotherLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
android.support.v7.app.AlertDialog.Builder builder = new android.support.v7.app.AlertDialog.Builder(view.getContext());
builder.setMessage("Are You Sure?").setNegativeButton("No", null);
builder.setPositiveButton("yes", new android.support.v7.app.AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Database database = new Database(viewParent.getContext());
database.deleteItem(item);
List<Item> items = database.getItems();
ListView list = (ListView) viewParent.findViewById(R.id.my_linear_list);
//List<Item> items = new Database(viewParent.getContext()).getItems();
TaskAdapter adapterNew = new ItemAdapter(viewParent.getContext(), tasks);
list.setAdapter(adapterNew);
}
});
builder.show();
}
});