I have the following layout
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
//some views here
</LinearLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="*" >
</TableLayout>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
The problem is when I scrolldown the table, I can't scrollUp again because the swipelayout is being triggered. How can I trigger the swiperefresh only when the first view of the table is visible?
I found that if you replace your ScrollView with a android.support.v4.widget.NestedScrollView the scrolling behavior will work as you expect it to.
Make your own implementation of SwipeRefreshLayout and override the canChildScrollUp in this way:
#Override
public boolean canChildScrollUp() {
if (scrollView != null)
return scrollView.canScrollVertically(-1);
return false;
}
just replace with any subclass of ScrollView.
If you have layout like this:
<SwipeRefreshLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/your_scroll_view_id">
<LinearLayout>
...
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</SwipeRefreshLayout>
You need to create your own class and override the function in this way:
class SwipeRefreshLayoutCustom extends SwipeRefreshLayout {
public SwipeRefreshLayoutCustom(Context context, AttributeSet attributes) {
super(context, attributes)
}
#override
boolean canChildScrollUp() {
return your_scroll_view_id.scrollY != 0
}
}
Use NestedScrollView with:
app:layout_behavior="#string/appbar_scrolling_view_behavior"
Related
I need behavior similar to this implementation But NestedScrollView would be the parent and RecyclerView would be the child of would NestedScrollView .
Eg: https://medium.com/widgetlabs-engineering/scrollable-nestedscrollviews-inside-recyclerview-ca65050d828a
I am not sure whether it can be achieved.Tried disabling the of parent(NSV) while child(RV)is scrolling But scroll on child scrolls the entire view including parent.
I'v implemented Marc Knaup solution and all works correct event if NestedScrollView would be the parent and the result was shown below
btw, i put what i'v done
CustomRecycleView
package com.example.nested_scroll_test;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.core.view.NestedScrollingParent;
import androidx.recyclerview.widget.RecyclerView;
public class CustomRecycleView extends RecyclerView implements NestedScrollingParent {
private View nestedScrollTarget = null;
private boolean nestedScrollTargetIsBeingDragged = false;
private boolean nestedScrollTargetWasUnableToScroll = false;
private boolean skipsTouchInterception = false;
public CustomRecycleView(Context context) {
super(context);
}
public CustomRecycleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRecycleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean temporarilySkipsInterception = nestedScrollTarget != null;
if (temporarilySkipsInterception) {
// If a descendent view is scrolling we set a flag to temporarily skip our onInterceptTouchEvent implementation
skipsTouchInterception = true;
}
// First dispatch, potentially skipping our onInterceptTouchEvent
boolean handled = super.dispatchTouchEvent(ev);
if (temporarilySkipsInterception) {
skipsTouchInterception = false;
// If the first dispatch yielded no result or we noticed that the descendent view is unable to scroll in the
// direction the user is scrolling, we dispatch once more but without skipping our onInterceptTouchEvent.
// Note that RecyclerView automatically cancels active touches of all its descendents once it starts scrolling
// so we don't have to do that.
if (!handled || nestedScrollTargetWasUnableToScroll) {
handled = super.dispatchTouchEvent(ev);
}
}
return handled;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
return !skipsTouchInterception && super.onInterceptTouchEvent(e);
}
#Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
if (dyConsumed != 0) {
// The descendent was actually scrolled, so we won't bother it any longer.
// It will receive all future events until it finished scrolling.
nestedScrollTargetIsBeingDragged = true;
nestedScrollTargetWasUnableToScroll = false;
} else if (dyConsumed == 0 && dyUnconsumed != 0) {
// The descendent tried scrolling in response to touch movements but was not able to do so.
// We remember that in order to allow RecyclerView to take over scrolling.
nestedScrollTargetWasUnableToScroll = true;
if (target.getParent() != null)
target.getParent().requestDisallowInterceptTouchEvent(false);
}
}
#Override
public void onNestedScrollAccepted(View child, View target, int axes) {
if (axes != 0 && View.SCROLL_AXIS_VERTICAL != 0) {
// A descendent started scrolling, so we'll observe it.
nestedScrollTarget = target;
nestedScrollTargetIsBeingDragged = false;
nestedScrollTargetWasUnableToScroll = false;
}
super.onNestedScrollAccepted(child, target, axes);
}
#Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return nestedScrollAxes != 0 && View.SCROLL_AXIS_VERTICAL != 0;
}
#Override
public void onStopNestedScroll(View child) {
nestedScrollTarget = null;
nestedScrollTargetIsBeingDragged = false;
nestedScrollTargetWasUnableToScroll = false;
}
}
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorAccent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#FFFFFF"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAlignment="center"
android:text="Top Section"/>
</LinearLayout>
<com.example.nested_scroll_test.CustomRecycleView
android:id="#+id/rw"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#color/colorPrimary"
android:nestedScrollingEnabled="true"
android:orientation="vertical">
</com.example.nested_scroll_test.CustomRecycleView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#FFFFFF"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAlignment="center"
android:text="Bottom Section"/>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
RecycleViewItem.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/nsw"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="vertical">
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="#CCCC"
android:gravity="center"
android:nestedScrollingEnabled="false"
android:orientation="vertical"
android:padding="2dp"
android:textColor="#FFFFFF" />
</androidx.core.widget.NestedScrollView>
#Rockin use overscrollmode bro:)
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:fillViewport="true"
android:overScrollMode="always"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/color_white"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/activity_insight_recyclerview_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/_20sdp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="#layout/raw_insight" />
post entire thing what you have tried so far.
your xml should be ,
<android.support.v4.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View > <!-- upper content -->
<!-- set recycler view with with wrap_content -->
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
set scrolling behaviour inside onCreateView() / onCreate() method.
requires Api 21+ .
RecyclerView v = (RecyclerView) findViewById(...);
v.setNestedScrollingEnabled(false);
or
android:nestedScrollingEnabled="false" // inside recycler view in xml file
This is demo for what you want look, In MainActivity.xml file :
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
tools:context="MainActivity">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<ImageView
android:id="#+id/top_seller"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
<ImageView
android:id="#+id/top_seller1"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/product_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="none" />
<ImageView
android:id="#+id/top_seller2"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
<ImageView
android:id="#+id/top_seller3"
android:layout_width="match_parent"
android:layout_height="200sp"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"
android:adjustViewBounds="true"
android:src="#drawable/background"
android:scaleType="fitXY"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
In your MainActivity.java class onCreate method:
RecyclerView bestRecyclerView = findViewById(R.id.product_list);
GridLayoutManager mGrid = new GridLayoutManager(this, 2);
bestRecyclerView.setLayoutManager(mGrid);
bestRecyclerView.setHasFixedSize(true);
bestRecyclerView.setNestedScrollingEnabled(false);
// Create ProductAdapter for RecyclerView data
ProductAdapter mAdapter = new ProductAdapter(MainActivity4.this,getProductTestData());
bestRecyclerView.setAdapter(mAdapter);
I hope It'll help you...!
In general simple trick works for me. When attaching OnTouchListener to child View, in onTouch() just disable touch interrupts. Something like this:
RecyclerView rv = findViewById(...);
rv.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
...
v.getParent().requestDisallowInterceptTouchEvent(true);
Have you try subclass the RV and override onInterceptTouchEvent?
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
when (event!!.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_DOWN -> {
// WE INTERACT WITH THIS RV. PREVENT PARENT TO INTERCEPT
parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
// THIS SEEMS LIKE IT WILL HAVE "DEFAULT" BEHAVIOUR BUT SINCE WE CURRENTLY DRAGGING THE RV THEN IT WONT SCROLL THE PARENT
parent.requestDisallowInterceptTouchEvent(false)
}
}
return false
}
I have a group horizontal RecycleViews inside a SwipeRefreshLayout and I am having trouble with swiping the Recycleviews on the start of the page as it keeps stopping it and detecting a refresh swipe.
How to stop this from happening?
Or is there a way to trigger refresh only if not swiping?
Also, is this the best way to implement my desired layout?
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/activity_main_swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="70dp"
android:isScrollContainer="false"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/block_border"
android:orientation="vertical">
<TextView
android:id="#+id/trending_episodes_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!--This is the first affected recycle -->
<android.support.v7.widget.RecyclerView
android:id="#+id/trendingEpisodesRecycle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal" />
</LinearLayout>
<!--This is the Second affected recycle -->
<android.support.v7.widget.RecyclerView
android:id="#+id/allNewsRecycle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/title_top"
android:clipToPadding="false"
android:orientation="horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/block_border"
android:orientation="vertical">
<TextView
android:id="#+id/moods_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/title_top"
android:textColor="#color/colorBlack"
android:textSize="20sp"
android:textStyle="bold" />
<android.support.v7.widget.RecyclerView
android:id="#+id/moodsRecycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="horizontal" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
Ok so I solved this problem by disabling the SwipeRefreshLayout when the RecycleView is being touched, and re-enabling it again once the user let go of the RecycleView.
Bellow are the code for that from my program:
MyRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(final RecyclerView recyclerView, int newState)
{
super.onScrollStateChanged(recyclerView,newState);
if (newState != RecyclerView.SCROLL_STATE_IDLE) { // on scroll stop
mSwipeRefreshLayout.setEnabled(false);
}
else
{
mSwipeRefreshLayout.setEnabled(true);
}
}
}
Zaid answer works fine. But in my case I had horizontal recycle views inside adapter, so for me it would be hard to connect adapter with activity recycler.
Easier approach is to create custom VerticalRefreshLayout and use it instead of SwipeRefreshLayout.
Kotlin solution:
class VerticalRefreshLayout(context: Context?, attrs: AttributeSet?) : SwipeRefreshLayout(context!!, attrs) {
private val mTouchSlop: Int = ViewConfiguration.get(context).scaledTouchSlop
private var mPrevX = 0f
#SuppressLint("Recycle")
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> mPrevX = MotionEvent.obtain(event).x
MotionEvent.ACTION_MOVE -> {
val eventX = event.x
val xDiff = abs(eventX - mPrevX)
if (xDiff > mTouchSlop) {
return false
}
}
}
return super.onInterceptTouchEvent(event)
}
I've inflated a fragment from view pager which uses the listview. And list view does not support setNestedScrollingEnabled in pre lollipop devices. So I've added the listview inside a NestedScrollView but when scrolling the list it does not scrolling.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:id="#+id/fragment_item_view"
android:background="#color/white"
android:isScrollContainer="true">
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/progressBar"
android:layout_centerInParent="true" />
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fillViewport="true">
<ListView
android:id="#+id/list_item_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:clipToPadding="false"
android:divider="#color/gray_stroke_color"
android:dividerHeight="0.5dp"
android:paddingBottom="#dimen/padding_64dp" >
</ListView>
</android.support.v4.widget.NestedScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
Can anyone suggest me any solution. Thanks in advance.
Try using
setNestedScrollingEnabled(true);
yourtListViewName.setNestedScrollingEnabled(true);
Use ViewCompat.setNestedScrollingEnabled() and your problem will be solved.
I am not sure why you would want to use a ListView inside a ScrollView if it will take up the entire height/width of it's parent.
I would suggest just using the ListView in the root layout of your fragment and eliminate the ScrollView.
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<ListView
android:id="#+id/list_item_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:clipToPadding="false"
android:divider="#color/gray_stroke_color"
android:dividerHeight="0.5dp"
android:paddingBottom="#dimen/padding_64dp"/>
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>
Also, I would suggest using RecyclerView instead of ListView as it implements NestedScrollingChild.
But if you are set on having nested scroll views in your layout you need to understand that NestedScrollView is intended to work as parent or a child scroll view while list. Here is a good example of a scrollview containing 2 other scrollviews:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</android.support.v4.widget.NestedScrollView>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
</ScrollView>
Also, I noticed that you are maybe using CoordinatorLayout because you are setting the layout behavior of your child views. If so, you only need to specify the 'app:layout_behavior="#string/appbar_scrolling_view_behavior"' for your main and only ScrollView: A ListView, RecyclerView or NestedScrollView.
You have to intercept the touch event for smooth scrolling
outerScrollView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
findViewById(R.id.inner_scroll).getParent()
.requestDisallowInterceptTouchEvent(false);
return false;
}
});
innerScrollView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
its work if add this code
android:nestedScrollingEnabled="true"
<ExpandableListView
android:id="#+id/lvExp"
android:nestedScrollingEnabled="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="right"
/>
Inside the XML file, while defining the ListView, kindly write,
android:nestedScrollingEnabled="true"
It will solve the issue
Create a Custom NonScrollListView
NonScrollListView.java
public class NonScrollListView extends ListView {
public NonScrollListView(Context context) {
super(context);
}
public NonScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
customListView
<?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"
android:fadingEdgeLength="0dp"
android:fillViewport="true"
android:overScrollMode="never"
android:scrollbars="none" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- com.Example Changed with your Package name -->
<com.Example.NonScrollListView
android:id="#+id/lv_nonscroll_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.Example.NonScrollListView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/lv_nonscroll_list" >
</RelativeLayout>
</RelativeLayout></ScrollView>
In Java File
Create a object of your customListview instead of ListView like :
NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);
I working with SwipeRefreshLayout. Here what my need is...
Im using one Linearlayout inside SwipeRefreshLayout which is in "RED COLOR".
when im trying to pull down that layout, that layout is not moving. Only its showing that refresh circular arrow, But i want to pull down that whole "Red color" layout. How to achieve this?
Please find my sources for reference.
Suggestion please....
mylayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefreshLayout_emptyView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#ff0000"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample SwipeRefreshLayout"
android:layout_marginTop="50dp"
android:textColor="#ffffff" />
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
MyClass.java
public class MyClass extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private SwipeRefreshLayout swipeLayout;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.mylayout,null);
swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout_emptyView);
onCreateSwipeToRefresh(swipeLayout);
return view;
}
private void onCreateSwipeToRefresh(SwipeRefreshLayout swipeLayout) {
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorSchemeColors(android.R.color.holo_green_dark, android.R.color.holo_red_dark,
android.R.color.holo_blue_dark, android.R.color.holo_orange_dark);
}
#Override
public void onRefresh() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Used PullRefreshLayout instead SwipeRefreshLayout from this sample
Instead for using a ScrollView as child of SwipeRefreshLayout, try using a RelativeLayout / LinearLayout and make the ScrollView a child of it.
something like this:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefreshLayout_emptyView"
android:layout_width="match_parent"
android:layout_height="300dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0000">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
//Leave the interior the same
</ScrollView>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
Also apply the red color to your LinearLayout. You currently have it in your SwipeRefreshLayout
Your ScrollView should not wrap_content on its height but match_parent
I have RecyclerView inside ScrollView which is inside SwipeRefresh layout. I have few layouts on top of RecyclerView, but my RecyclerView is not visible, even if i remove other layouts from ScrollView. What do you suggest? I need to put list below some layouts in ScrollView somehow.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<include layout="#layout/toolbar"></include>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
....
<android.support.v7.widget.RecyclerView
android:id="#+id/simpleList"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
Tried to give specific height but still not visible o.O
If i replace RecyclerView with ListView, then list is visible.
If you want to have all the items of the list always visible then replace RecyclerView with LinearLayout and add your items to it.
An example:
your_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<include layout="#layout/toolbar"></include>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
....
<LinearLayout
android:id="#+id/simpleList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/item_text"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ic_ab_back_mtrl_am_alpha"/>
</LinearLayout>
And in your Java code:
first declare the list
mSimpleList = (LinearLayout) findViewById(R.id.simpleList);
then method for adding the items
public void addListItems(ArrayList<String> strings) {
LayoutInflater inflater = LayoutInflater.from(this);
for(String s : strings) {
View item = inflater.inflate(R.layout.item_layout, mSimpleList, false);
TextView text = (TextView) item.findViewById(R.id.item_text);
text.setText(s);
mSimpleList.addView(item);//you can add layout params if you want
}
}
I just had to put android:fillViewport="true" to SwipeRefreshLayout. And now RecyclerView is visible.
My earlier answer is blocking the down scroll. So, a good work around will be add your Stuff as the first element of the RecyclerView. That can be easily implemented using the adapter. That way you can still scroll your stuff as well as your actual list elements.
<?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">
<include layout="#layout/toolbar"></include>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/simpleList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#+id/your_stuff" />
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
And using something like the following for your adapter implimentation,
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
class YourStuffViewHolder extends RecyclerView.ViewHolder {
//
}
class ViewHolderListItem extends RecyclerView.ViewHolder {
//
}
#Override
public int getItemViewType(int position) {
if(position>0){
return 1;
}
return 0;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 0: return new YourStuffViewHolder();
case 1: return new ViewHolderListItem ();
}
}
}