I have a vertical ViewPager. Each page contains some elements which a NestedScrollView. If I swipe outside of the NestedScrollView it works perfectly, but if I swipe inside the NestedScrollView the vertical scroll of ViewPager doesn't work.
My Nested:
<android.support.v4.widget.NestedScrollView
android:id="#+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:clipToPadding="false"
android:overScrollMode="never">
And I set the setup like that too:
scrollView.setNestedScrollingEnabled(false);
Could you help me guys? Thank you very much!
Use requestDisallowInterceptTouchEvent so it will not allow child to intercept touch events.
yourViewPager.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
yourViewPager.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
For more reference this requestDisallowInterceptTouchEvent
Related
I have a VerticalViewPager whose Fragment content I want to scroll horizontally. The vertical paging works fine until the horizontal content is big enough to scroll. After that the touch events are not passed on to the ViewPager and so paging no longer works.
MVCE
This can be reproduced by setting up a simple project as given in this answer that I just posted.
Replace the fragment_one.xml file with
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" >
<TextView
android:id="#+id/textview"
android:textSize="30sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</HorizontalScrollView>
</RelativeLayout>
and set the text to anything long enough to scroll horizontally.
Things I've tried
NestedScrollView: That quickly turned out to be a dead end since it is apparently not available for horizontal scrolling. I thought about converting the source code to a HorizontalNextedScrollView but that would not be a trivial project.
Custom HorizontalScrollView: I tried converting answers like this and this for horizontal scrolling, but was unsuccessful. I'm going to continue experimenting in this area.
This is not a DoubleViewPager but I feel like the solution should be similar.
In order to answer this and other similar questions, it is very helpful to understand how the Android Framework handles touch events. My fuller answer on that is here, but I will include the summary diagram below.
The HorizontalScrollView (ViewGroup B in the diagram) is handling all touch events before the VerticalViewPager (ViewGroup A) has a chance to. So the solution is to use onInterceptTouchEvent() in the VerticalViewPager to selectively filter out vertical scrolls. For that it is easiest to just use a GestureDetector.SimpleOnGestureListener.onScroll().
Here are the relevant changes you need to make to the VerticalViewPager class to accomplish that:
public class VerticalViewPager extends ViewPager {
GestureDetector mDetector;
private void init() {
// ...
mDetector = new GestureDetector(getContext(), new VerticalScrollListener());
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(flipXY(ev));
flipXY(ev);
return mDetector.onTouchEvent(ev);
}
class VerticalScrollListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return Math.abs(distanceY) > Math.abs(distanceX);
}
}
}
I am using RecyclerView inside NestedScrollView and it works. But when I use RecyclerView inside LinearLayout or something, it scroll in various speed depending on gesture. The scroll listen to gesture and if I slide up only a bit, then it scroll a little bit while if I slide up really fast, then it scroll really fast. Now my problem is that RecyclerView inside NestedScrollView certainly scroll but fast scroll does not work. However I slide up fast or slow, RecyclerView or NestedScrollView only scroll a little bit.
How can I make my NestedScrollView or RecyclerView inside that scroll view scroll in various speed?
try
recyclerView.setNestedScrollingEnabled(false);
By default setNestedScrollingEnabled works only after API-21.
You can use ViewCompat.setNestedScrollingEnabled(recyclerView, false); to disable nested scrolling for before and after API-21(Lollipop). Link to documentation.
I was working on android 16 where this was not possible to use setNestedSCrollEnabled method,
What I end up doing to stop RecyclerView from handling Scrolls.
Like in LinerLayoutManager i made canScrollHorizontally, canScrollVertically to return false by default.
myRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false){
#Override
public boolean canScrollHorizontally() {
return false;
}
#Override
public boolean canScrollVertically() {
return false;
}
});
After several iterations, I came up with a solution.
If you are using RecyclerView, then:
recyclerView.setNestedScrollingEnabled(false);
If you are using LinearLayout inside NestedScrollingView, take the LinearLayout inside a normal ScrollView and then set its scrolling to
scrollView.setNestedScrollingEnabled(false);
android:overScrollMode="never
<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">
<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>
You can use ScrollView with ExtendRecyclerView class that overrides the onMeasure method. That works for me!
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthSpec, expandSpec);
}
recyclerView.setNestedScrollingEnabled(false);
Will be useful sometimes.But it is not advisable for all the times.because it disables view recycling feature in recylcer view.
Alternatives:
Try CollapsiveToolbarLayout with Recycler view.
put other views in collapsiveTollbar layout.
I also met this problem.
And upgrade to 26.1.0 fix it.
In My Case i placed all images in drawable folder insted of drawable-xxxhdpi folder thats why my screen UI is lagging.
This is WAI. The NestedScrollView measures its children with the Spec "Unspecified". The child can grow as much as it wants too.
This essentially equates the height of NSV and RV. So as far as the RV is concerned, it believes that it is completely displayed.
Wrap your RV with an LL and give your RV a height. The LL would not set the measure spec to be UNSPECIFIED so the RV would correctly scroll within its set height of whatever DPs you provide.
The only downside of this method is that you will not be able to do a match parent on your RV.
You should wrap recycler view in any layout like LinearLayout and set RecyclerView size to constant, like 800dp. This will enable smooth scroll and recycler view will still recycler views during scroll.
<android.support.v4.widget.NestedScrollView 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:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="800dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</LinearLayout>
I have two listViews in the same LinearLayout. Each listView looks like this:
<ListView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:id="#+id/listViewReceived"
android:layout_weight="1"
>
</ListView>
<ListView ><!--same as above-->
The issue is that the two listViews have a scrollbar but I want show all the items without a scrollbar.
if I make scrolling in anyone the listviews the movement is generated internally. but I want show scrollbar in entire the screen. how the green bar. https://drive.google.com/file/d/0B_Z2NZi-dbUMc3FCOTQ1UDNWRnM/view
issue is that the two listView have your scrollbar but I want show all the items without scrollbar.
Add this to all of the listview
android:scrollbars="none"
android:scrollbars=none will define which scrollbars to display or show any at all. This won’t disable scrolling as such (you’ll be able to scroll in the appropriate direction) but just hide the scrollbars from the user interface. Try Following Code
listView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
return true; // Indicates that this has been handled by you and will not be forwarded further.
}
return false;
}
});
I have to add pull-to-refresh functionality to refresh info on main screen. Here`s a scheme of my screen UI (red area should handle pulling):
I use ready solution for pull-to-refresh. Due to documentation, my red layout should be one of these classes:
ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager
But I have ListView on my screen, so I am not able to use ScrollView as red layout. And I`m stuck with this problem. It is possible to use UITableView into UIScrollView in iOS, but in Android one I have no idea what to do in such cases.
Any help will be appreciated. Thanks!
Why not replace the listview by a LinearLayout and then you can use the ScrollView?
You just need to create a layout for the items in the linearlayout and then adding them using something like this:
LinearLayout layout = (LinearLayout)findViewById(R.id.MyListLayout);
for (int i=0; i<list.size(); i++) {
Item item = list.get(i);
View view = inflater.inflate(R.layout.MyRowLayout, null);
Textview myTextView = view.findViewById(R.id.MyTextView);
myTextView.setText(item.getString());
list.addView(vi);
}
Is the pull-to-refresh horizontal or vertical?
In case it's horizontal, use a HorizontalScrollView (a ViewPager would do, too), and then place a Table?Layout inside it.
In case it's horizontal, well, I don't think I like that design (the pull-to-refresh area should just be the ListView), but I believe there is some way to use the ListView without its internal scrolling so that you can rely on a parent ScrollView to do the scrolling, but I'd need to check the code of an old problem to "remember" how to do that.
I've solved this issue, but forgot to write about it :)
My layout.xml file looks like this:
<com.handmark.pulltorefresh.library.PullToRefreshScrollView
android:id="#+id/home_info_pulltorefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:id="#+id/home_info_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white_background"
android:baselineAligned="false"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/charts_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="vertical"
android:paddingRight="5dp" >
<FrameLayout
android:id="#+id/frame_container_chart_top"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/frame_container_chart_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<FrameLayout
android:id="#+id/frame_container_right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
</com.handmark.pulltorefresh.library.PullToRefreshScrollView>
android:fillViewport="true" is used to stretch its content to fill the viewport (make height of scroll match_parent)
I add Fragment containing ListView programmatically (R.layout.frame_container_right Fragment resource ID)
Everything worked fine, but when I tried to scroll ListView down, my ScrollView began to scroll. Scrolling ListView up worked fine. Also I noticed that if I tap ListView, move finger left or right and then try to scroll down, touch events are not transmitted from ListView to ScrollView and I get expected behavior. So I've decided to emulate this situation programmatically:
mListViewReviews.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
long startTime = SystemClock.uptimeMillis();
long duration = 1;
MotionEvent e = MotionEvent.obtain(startTime, startTime + duration, MotionEvent.ACTION_MOVE, event
.getX(), event.getY() + 10, 0);
MotionEvent ev = MotionEvent.obtain(startTime + duration, startTime + duration * 2,
MotionEvent.ACTION_MOVE, event.getX(), event.getY() + 20, 0);
v.dispatchTouchEvent(e);
v.dispatchTouchEvent(ev);
}
return false;
}
});
As a result, I've got working ListView with proper cell reuse and working pull-to-refresh logic. Thanks!
I'd like to create a layout width GridView that takes the whole screen (fill_parent for both width and height).
Number of columns is X, number of rows is Y (filled with own adapter, extending BaseAdapter).
What I don't want is scrolling. I'd like to have all items visible, no vertical scroll bar.
Thanks in advance.
Try to set the following OnTouchListener:
gridView.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
return event.getAction() == MotionEvent.ACTION_MOVE);
}
});
set attribute android:scrollingCache="false" in your GridView
<ListView android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollingCache="false"
android:layout_weight="1" />
..maybe:
mKeypadGrid.setEnabled(false);
will solve your problem. It disabled scroll but other functionality I need was working. Not sure if it will fit to your needs.. Cheers