This question already has answers here:
RecyclerView inside ScrollView is not working
(26 answers)
Closed 6 years ago.
I'm using the latest support design (compile 'com.android.support:design:+') which from 23.2 should have fixed the issue with RecyclerView inside ScrollView.
The RecyclerView and the ExpandableListView scrolling both work perfectly.
But when the ExpandableListView is too long and I want to be able to scroll the layout upwards so I could see the rest of it, the scrollview just doesn't work.
fragment :
myRecyclerView = (RecyclerView) view.findViewById(R.id.myRecyclerView);
myRecyclerView.setNestedScrollingEnabled(false);
LinearLayoutManager layoutManager = new LinearLayoutManager( mContext, LinearLayoutManager.HORIZONTAL, false );
layoutManager.setAutoMeasureEnabled(true);
myRecyclerView.setLayoutManager(layoutManager);
MyListAdapter myListAdapter = new MyListAdapter(recyclerDataList, getActivity());
myRecyclerView.setAdapter(myListAdapter);
xml:
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<TextView
android:id="#+id/headerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="header text"
android:layout_marginRight="10dp"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/myRecyclerView"
android:layout_below="#id/headerText"
android:scrollbars="none"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ExpandableListView
android:id="#+id/expandableList"
android:layout_below="#id/myRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="1dp"
android:dividerHeight="0dp"
android:groupIndicator="#null"
android:listSelector="#android:color/transparent"
android:showDividers="middle" >
</ExpandableListView>
</RelativeLayout>
</ScrollView>
You need to calculate listview height at run time, can not use listview or expendable listview inside scroll view like this.
Android list view inside a scroll view
You should do this way:
Implement OnItemTouchListener of RecyclerView and disallow parent touch event on ACTION_MOVE.
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
int action = e.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
recyclerView.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
recyclerView.getParent().requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_MOVE:
recyclerView.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
Hope this will help you.
Related
I have a horizontal recyclerview that takes up the entire screen. Within that recyclerview is a textview and an imageslider than holds three images.
I used this for the imageslider:
https://github.com/denzcoskun/ImageSlideshow
Recyclerview XML
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/bonus_detail_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/bonus_detail_item"/>
Bonus Detail XML
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/bonus_detail_title"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.07"
android:background="#color/myOrange"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textAlignment="center"
android:autoSizeMaxTextSize="100sp"
android:autoSizeMinTextSize="10sp"
android:autoSizeTextType="uniform"
android:layout_gravity="center_horizontal"
android:textColor="#android:color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#id/bonus_image_slider"/>
<com.denzcoskun.imageslider.ImageSlider
android:id="#+id/bonus_image_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:iss_auto_cycle="false"
app:iss_period="1000"
app:iss_delay="0"
app:iss_placeholder="#drawable/placeholder"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The problem is that when I try to swipe on the imageslider the entire recyclerview scrolls. I have searched here trying to find a solution, but the option suggested on many other posts does not work for me.
holder.imageSlider.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
I am not restricted to using the imageSlider, but I do have to maintain the horizontal recyclerview and a horizontal swipe between images. I also tried adding the images in a horizontalscrollview, but I have been unable to set the images to be the full screen width.
You have to request disallow intercepting touch events on your RecyclerView not the direct parent of your ImageSlider which is ConstraintLayout:
holder.imageSlider.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent() // ConstraintLayout
.getParent() // RecyclerView
.requestDisallowInterceptTouchEvent(true);
return false;
}
});
I want to have a pagination for the recyclerview but , In my case , the recyclerView is inside a ScrollView. So the onscrollListener not working as expected. So I am planning to find the scroll end for the ScrollView and will fire the next page request.
Is this a good solution or Do somebody have a better idea?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent" android:fillViewport="false">
<LinearLayout android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<FrameLayout android:id="#+id/headerContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
You can use the following code for intercepting the RecyclerView scrolls and can fine tune your scroll events on basis of that, I hope it help
mList.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
float rawX;
int mSlop = ViewConfiguration.get(getActivity()).getScaledTouchSlop();
#Override
public boolean onInterceptTouchEvent(RecyclerView v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
v.getParent().requestDisallowInterceptTouchEvent(true);
rawX = event.getRawX();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
v.getParent().requestDisallowInterceptTouchEvent(false);
rawX = 0f;
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(rawX - event.getRawX()) > mSlop)
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
I have searched a lot regarding my query and none of them was useful. I have a recyclerview and some static data inside a scroll view which is inside a root parentlayout as show below.
I have set -
scrollview.scrollto(0,0);
because everytime i open the activity it jumps to the recyclerview firstitem and it skips out the static data above the recyclerview.
recyclerview.setNestedScrollingEnabled(false);
recyclerview.setfocusable(false);
for smoothscroll.
the problem is with-
layoutmanager.scrollToPositionWithOffset(pos,0);
it is not working. I have set the aboveline after setting adapter to recyclerview. Also tried with NestedScrollView but in vain.
although I have used
layoutmanager.scrollToPosition(pos);
For those who skip the code, i have set match_parent to ScrollView and
fillviewport to true.
Here is my layout.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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/bottomsheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.inkdrops.khaalijeb.BrandCouponActivity">
<RelativeLayout
android:id="#+id/inclusionviewgroup"
android:layout_width="match_parent"
android:layout_height="match_parent">
<static data/>
<ScrollView
android:id="#+id/scrollviewmain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/one"
android:fillViewport="true"
android:scrollbars="none"
android:layout_above="#+id/donelayout">
<staticdata/>
<TextView
android:id="#+id/dealstext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/card1"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:textSize="16sp"
android:text="Deals & Coupons"
android:textColor="#444444" />
<RelativeLayout
android:id="#+id/recyclerlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/dealstext"
android:layout_marginTop="5dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:background="#color/colorbackground">
<android.support.v7.widget.RecyclerView
android:id="#+id/coupon_rec_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorbackground"
android:visibility="visible"/>
</RelativeLayout>
<statisdata>
</RelativeLayout>
</ScrollView>
include layout="#layout/activity_coupons"
android:visibility="gone"
/>
</RelativeLayout>
</RelativeLayout>
Need to scroll ScrollView by getting top position of RecyclerView's child :
float y = recyclerView.getY() + recyclerView.getChildAt(selectedPosition).getY();
scrollView.smoothScrollTo(0, (int) y);
you can use scroll view method to reach your desired locations as:
scrollView.smoothScrollTo(int x, int y);
Step 1: Add this line for selecting that position in the recyclerview
adaptercat.setSelectedItem(Integer.parseInt(dealtypeid));
Step 2: Once check below constructor by getting current position
public CatgerotyAdapter(Context context, ArrayList<HashMap<String, String>> arraylist,String selectedPosition) {
this.context = context;
this.data = arraylist;
resultp = new HashMap<>();
currentItemPos=Integer.parseInt(selectedPosition)-1;
}
Step 3: And this function also in adapter
public void setCurrentItem(int item)
{
this.currentItemPos = item;
}
Last step 4. Add this function outside adapter in your class
private void onPagerItemClick2(Integer tag)
{
adaptercat.setCurrentItem(tag);
catsp.setAdapter(adaptercat);
}
Pust this line in your listview item click listner
((ClassName) context).onPagerItemClick2(position);
That position will be selected when will you open listview ..
Use this method scrollToPosition (int position) this is work for me. hope this will help you.
mMessagesRecyclerView = (RecyclerView) findViewById(R.id.messagesRecyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setStackFromEnd(true);
mMessagesRecyclerView.setLayoutManager(layoutManager);
mMessagesAdapter = new MessagesAdapter();
mMessagesRecyclerView.setAdapter(mMessagesAdapter);
mMessagesRecyclerView.scrollToPosition(your position);
this is my layoutstructer
I have a ScrollView and a nested TextView. When I set setOnTouchListener to it,the gestures are recognized but the scrolling not working. And If I set setOnTouchListener to nested TextView,its working fine. I have tried by googling but could not solve the problem.
But my need is to set the setOnTouchListener to ScrollView.
Please help.
layout.xml
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:id="#+id/scrollView">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#000000"
android:background="#00FF00"
android:padding="15dp"
android:textSize="18sp" />
</LinearLayout>
</ScrollView>
MainActivity.java
mGestureDetector = new GestureDetectorCompat(this,this);
findViewById(R.id.scrollView).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, final MotionEvent event) {
Log.e("Stark", "setOnTouchListener");
mGestureDetector.onTouchEvent(event);
return true;
}
});
Why you need to set onTouch. If only scroll up and down. Try below
ScrollView sv;
sv.post(new Runnable() {
#Override
public void run() {
sv.fullScroll(View.FOCUS_DOWN);
}
});
make sure you have this in scrollview xml. hope it helps.
android:fillViewport="true"
I have a ScrollView. One of its children is a ListView. Both scrolling in the same direction. How do I get both of them to respond to scroll events? And then when the end of the ListView is reached for the event to go to the parent ScrollView so the ScrollView may scroll?
xml layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
...
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
...
android:orientation="vertical"
>
<LinearLayout
android:id="#+id/..."
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="horizontal">
...
</LinearLayout>
<android.support.v4.view.ViewPager
.../>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/pad_half"
>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
>
</LinearLayout>
</LinearLayout>
</ScrollView>
My ListView actually goes inside the ViewPager. The design is such that about three items in the ListView is visible, and user is able to scroll to see other items. In the meantime, the views above and below the ViewPager are visible. Again, it's a ViewPager: it has other pages than the ListView in question.
You Should not have a listview within a ScrollView.
But you can have a custom class and use that to accomplish A Listview with in a ScrollView.
Try the following code
first make a custom ScrollView Class.
public class VerticalScrollview extends ScrollView{
public VerticalScrollview(Context context) {
super(context);
}
public VerticalScrollview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticalScrollview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
return false; // redirect MotionEvents to ourself
case MotionEvent.ACTION_CANCEL:
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
return false;
default: break;
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
return true;
}
}
Then use this class for you layout
<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:background="#android:color/white"
android:orientation="vertical" >
<com.gui.today.VerticalScrollview
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ProgressBar
android:id="#+id/progressBar3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal" />
<TextView
android:id="#+id/empty_calender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:text="#string/empty_calender"
android:textColor="#ffffff"
android:visibility="gone" />
<ListView
android:id="#+id/listView2"
android:layout_width="fill_parent"
android:layout_height="150dp" >
</ListView>
</FrameLayout>
</LinearLayout>
</com.gui.today.VerticalScrollview>
I have a ScrollView
Get rid of it.
One of its children is a ListView
Put everything in the ListView, either using addHeaderView()/addFooterView(), my MergeAdapter, or something else along those lines.
You cant scroll a listview same direction as the scrollview. But if you have a horizontal scrollview you can scroll vertical with a listview.
you cannot add a ListView in a scroll View ,as list view also scolls and there would be a synchonization problem between listview scroll and scroll view scoll. You can make a CustomList View and add this method into it.
#Override public boolean onInterceptTouchEvent(MotionEvent ev)
{
/*
* Prevent parent controls from stealing our events once we've gotten a touch down
*/
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
ViewParent p = getParent();
if (p != null) {
p.requestDisallowInterceptTouchEvent(true);
}
}
return false;
}