I have a vertical custom list and each item of vertical list contains a horizontal list-view. When I scroll horizontally then list also moves little vertically. Which makes it less user friendly. Can I disable vertical scrolling while scrolling horizontally. I am using
<com.devsmart.android.ui.HorizontalListView
android:id="#+id/hlistview"
android:layout_width="match_parent"
android:layout_height="155dp"
android:layout_margin="6dp"
android:background="#fff"
android:fitsSystemWindows="true"
/>
for horizontal list view
The idea is to disable the parent listview to intercept touch event. This might work :
HorizontalListView hv = (HorizontalListView)findViewById(R.id.hlistview);
hv.setOnTouchListener(new ListView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ListView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow ListView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
// Handle HorizontalScrollView touch events.
v.onTouchEvent(event);
return true;
}
});
Reference : https://stackoverflow.com/a/22609646/1239966
Best way to do this.
put given code on your horizontal listview onScroll method it work perfact
ViewParent view_parent = getParent();
if (view_parent != null)
{
view_parent.requestDisallowInterceptTouchEvent(true);
}
Related
listview scroll on some devices Nexus_5x and doesn't scroll on Samsung galaxy tab 7
I try everything on the internet :
this doesn't work !
// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());
// ...
// restore index and position
mList.setSelectionFromTop(index, top);
Link here
Maintain/Save/Restore scroll position when returning to a ListView
also this doesn't work
ListView lv = (ListView)findViewById(R.id.myListView); // your listview inside scrollview
lv.setOnTouchListener(new ListView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
// Handle ListView touch events.
v.onTouchEvent(event);
return true;
}
});
link here
ListView inside ScrollView is not scrolling on Android
My listView xml is
<ListView
android:id="#+id/listview"
style="#style/ListView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginEnd="5dp"
android:layout_marginStart="5dp"
android:layout_marginTop="8dp"
android:visibility="visible"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/buttonClear"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintRight_creator="1"
tools:layout_constraintTop_creator="1" />
landscape doesn't work , but portrait is just fine.
I don't understand why it's ok on some devices and even portrait mode but not the other ?
To start with, its not always a good idea to nest a scrollable view in another especially when they are scrolling in the same direction, although in some cases there are not much alternatives. When I want to implement something like that say a recyclerview in a scrollview, I disable the scrolling behaviour of the recyclerview and make the size expand depending on the size of the contents
http://www.it1me.com/it-answers?id=33330388&ttl=How+to+put+RecyclerView+inside+NestedScrollView%3F
That is a link to where it is implemented. Study it so you'll get the idea.
Goodluck
I am developing an app which it has a vertical ViewPager within ScrollView. The thing is ViewPager only recognize touch events when I scroll horizontally, otherwise ScrollView will get focused and perform the scroll.
I think this could work:
viewPager.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
scrollView.requestDisallowInterceptTouchEvent(true);
int action = event.getActionMasked();
switch(action){
case MotionEvent.ACTION_UP:
scrollView.requestDisallowInterceptTouchEvent(false);
break;
}
return false;
}
});
But because of ViewPager does not recognize touch events when I perform vertical scroll this piece of code does nothing.
What I want to achieve is give focus to ViewPager when I touch it and give focus to ScrollView when I'm not touching the ViewPager. Thanks in advance.
This is some code I use for a scrollview that has problems with textviews focusing. It might help you. It might not.
ScrollView sv = (ScrollView) view.findViewById(R.id.svRecord);
sv.setOnTouchListener(this);
sv.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
sv.setFocusable(true);
sv.setFocusableInTouchMode(true);
Can some one help my with ScrolView in Android Mobile App.My problem- on my vertical ScrollView i have horizontal "hlistview»,and when i moved "hlistview" up/down/right/left play only one. How they can work together? At time,work only one.
hListView.setOnTouchListener(new HorizontalListView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
v.onTouchEvent(event);
return true;
}
});
On nested scrollviews you must intercept the touch events. However if you just requestDisallowInterceptTouchEvent on ACTION_DOWN you are making the it's parent disable touch events the moment your finger touches the screen. That's not the wanted behavior. You need to set a threshold and only disallow the events the moment your scroll distance has hit that threshold.
On the nested scrollview ACTION_DOWN set a field saving the initial X (for horizontal swipe) like this:
mLastX = event.getX();
Next on ACTION_MOVE compare it with your threshold (50 in this example)
if (Math.abs(event.getX() - mLastX) > 50)
requestDisallowInterceptTouchEvent(true);
I am developing an android application which has a scrollview. I have overriden my view from ScrollView and have implemented the onScrollChanged method. As the scrollview scrolls and reaches the bottom, it loads more products and add them to scrollvew. I am having a strange issue. First time when products loads and I try to drag up the scrollview, onScrollChanged never happens. Then I googled and found something:
scrollView.setOnTouchListener(new ListView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
// Handle ListView touch events.
v.onTouchEvent(event);
return true;
}
});
After adding this, when I try to drag the scrollview from empty area of scrollview, it starts to call onScrollChanged and afterwards I start dragging from anywhere else, onScrollChanged is being called. My question is, why it is behaving like that? It should call onScrollChanged from whatever the touch event starts. I hope, I explained my point well. Any solution?
Why don't you use endless adapter with a view like ListView or GridView to achieve the desired behavior instead
I have a ScrollView on top of another view(with Buttons). The ScrollView is taking the whole screen and is obscuring the view that is beneath it.
At some point in my app I need the ScrollView to be disabled (but still visible) and transfer all the touch events to the Buttons that are beneath the ScrollView. How can I do that? Some views like Buttons are automatically doing that when disabled but a ScrollView is not doing that.
Try to implement your own ScrollView which has a flag to indicate the status(disabled/enabled) and also overrides the onTouchEvent and dispatchTouchEvent to let the touch events get pass the ScrollView. Here is an example:
public class DisabledScrollView extends ScrollView {
private boolean mIsDisable = false;
// if status is true, disable the ScrollView
public void setDisableStatus(boolean status) {
mIsDisable = status;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// no more tocuh events for this ScrollView
if (mIsDisable) {
return false;
}
return super.onTouchEvent(ev);
}
public boolean dispatchTouchEvent(MotionEvent ev) {
// although the ScrollView doesn't get touch events , its children will get them so intercept them.
if (mIsDisable) {
return false;
}
return super.dispatchTouchEvent(ev);
}
}
Then all you have to do is change the value of that flag. See if it works.
In my case, I just needed to handle the touch event in View A, which was overlaping View B and then send the event to View B. Both views were child of the same RelativeLayout, but there was no parent-child relation between views A and B. This worked for me:
viewA.setOnTouchListener( new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
// do my stuff here
viewB.dispatchTouchEvent( event );
}
}
In this case I have a recyclerview under a scrollview. The top of scrollview is in vertical scroll, and the recyclerview is in horizontal scroll. The scrollview have top padding, making the recyclerview is visible through the transparency in the scrollview padding. I have to make it this way because when the scrollview is scrolled the recyclerview will scroll vertically to like parallax effect (this effect is in another code). This code below is working for my case, might help
scrollView.setOnTouchListener(new View.OnTouchListener() {
float mDownX,mDownY;
boolean mIsSwiping,isDown;
#Override
public boolean onTouch(View v, MotionEvent event) {
if(mIsSwiping){
recyclerView.dispatchTouchEvent(event);
}
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mIsSwiping = false;
isDown = true;
mDownX = event.getX();
mDownY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
if(isDown){
float deltaX = Math.abs(event.getX() - mDownX);
float deltaY = Math.abs(event.getY() - mDownY);
mDownX = event.getX();
mDownY = event.getY();
if(deltaX!=deltaY){
isDown = false;
if(deltaX>deltaY){
mIsSwiping = true;
}
}
}
}
return mIsSwiping;
}
});
This is the layout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/gray0"
android:clipToPadding="false"
android:clipChildren="false"
android:paddingBottom="70dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="320dp"
android:orientation="horizontal"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
<ScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="301.75dp"
android:paddingBottom="23.5dp"
android:clipChildren="false"
android:clipToPadding="false">
.
.
.