I am trying to create a horizontal scroll view inside horizontal scroll view in android. First horizontal scrolling views are working fine. When i am trying to scroll second horizontal scrolling views are not working.
my layout file
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="100dp"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:layout_width="250dp"
android:layout_height="100dp"
app:cardCornerRadius="20dp"
app:cardBackgroundColor="#color/colorPrimary"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:scrollbars="horizontal"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp">
<LinearLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1"></Button>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2"></Button>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="3"></Button>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="4"></Button>
</LinearLayout>
</HorizontalScrollView>
</androidx.cardview.widget.CardView>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</RelativeLayout>
can anybody share your knowledge how to achieve this one?
You can create Custom class for nested scroll view for support horizontal smooth scroll.
public class HorizontalNestedScrollView extends NestedScrollView {
private int slop;
private float mInitialMotionX;
private float mInitialMotionY;
public HorizontalNestedScrollView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
ViewConfiguration config = ViewConfiguration.get(context);
slop = config.getScaledEdgeSlop();
}
public HorizontalNestedScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public HorizontalNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private float xDistance, yDistance, lastX, lastY;
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
lastX = ev.getX();
lastY = ev.getY();
// This is very important line that fixes
computeScroll();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - lastX);
yDistance += Math.abs(curY - lastY);
lastX = curX;
lastY = curY;
if (xDistance > yDistance) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
}
You can read about the issue and the simple fix here: https://code.google.com/p/android/issues/detail?id=194398
Use this class in place of your nestedscrollview in the xml file, and the child lists should intercept and handle the touch events properly.
Hope this will help you.
Related
I have a horizontal recycler-view within motion layout. Sometimes when I do a horizontal swipe, the page starts scrolling in the vertical direction. This happens when we do a diagonal fling.
I want something like Google Play where horizontal recycler-views can defend slightly diagonal vertical swipes. BTW setting nestedscrollEnabled doesn't work.
There is quite a nice article regarding all the RecycleView scroll behavior and the issue itself. Checkout RĂºben Sousa article. Solution is quite easy, try to use adopted RecyclerView:
/**
* A RecyclerView that only handles scroll events with the same orientation of its LayoutManager.
* Avoids situations where nested recyclerviews don't receive touch events properly:
*/
public class OrientationAwareRecyclerView extends RecyclerView {
private float lastX = 0.0f;
private float lastY = 0.0f;
private boolean scrolling = false;
public OrientationAwareRecyclerView(#NonNull Context context) {
this(context, null);
}
public OrientationAwareRecyclerView(#NonNull Context context, #Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public OrientationAwareRecyclerView(#NonNull Context context, #Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
addOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
scrolling = newState != RecyclerView.SCROLL_STATE_IDLE;
}
});
}
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
final LayoutManager lm = getLayoutManager();
if (lm == null) {
return super.onInterceptTouchEvent(e);
}
boolean allowScroll = true;
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
lastX = e.getX();
lastY = e.getY();
// If we were scrolling, stop now by faking a touch release
if (scrolling) {
MotionEvent newEvent = MotionEvent.obtain(e);
newEvent.setAction(MotionEvent.ACTION_UP);
return super.onInterceptTouchEvent(newEvent);
}
break;
}
case MotionEvent.ACTION_MOVE: {
// We're moving, so check if we're trying
// to scroll vertically or horizontally so we don't intercept the wrong event.
float currentX = e.getX();
float currentY = e.getY();
float dx = Math.abs(currentX - lastX);
float dy = Math.abs(currentY - lastY);
allowScroll = dy > dx ? lm.canScrollVertically() : lm.canScrollHorizontally();
break;
}
}
if (!allowScroll) {
return false;
}
return super.onInterceptTouchEvent(e);
}
}
This Work perfect for me.
activity_main.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:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
</LinearLayout>
list_item.xml
<?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="wrap_content"
android:background="?android:selectableItemBackground"
android:orientation="vertical"
android:padding="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp">
<TextView
android:id="#+id/itemTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:layout_toLeftOf="#+id/btnMore"
android:text="Sample title"
android:textColor="#android:color/black"
android:textSize="18sp" />
<Button
android:id="#+id/btnMore"
android:layout_width="wrap_content"
android:layout_height="42dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:theme="#style/MyButton"
android:text="more"
android:textColor="#FFF" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_list"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_gravity="center_vertical"
android:orientation="horizontal" />
</LinearLayout>
list_single_card.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 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="wrap_content"
android:orientation="horizontal"
app:cardCornerRadius="5dp"
app:cardUseCompatPadding="true"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="0dp"
android:background="?android:selectableItemBackground"
android:orientation="vertical">
<ImageView
android:id="#+id/itemImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:scaleType="fitCenter"
android:src="#drawable/android" />
<TextView
android:id="#+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/itemImage"
android:gravity="center"
android:padding="5dp"
android:text="Sample title"
android:textColor="#android:color/black"
android:textSize="18sp" />
</LinearLayout>
</android.support.v7.widget.CardView>
Try this:
RecyclerView rv = findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, true);
rv.setLayoutManager(layoutManager);
rv.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow RecyclerView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow RecyclerView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
v.onTouchEvent(event);
return true;
}
});
That code prevent scroll vertically when you scroll with your horizontal recyclerview.
xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frame_living_root_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<SurfaceView
android:id="#+id/player_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
<android.opengl.GLSurfaceView
android:id="#+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:visibility="gone" />
<com.netease.nimlib.sdk.avchat.model.AVChatSurfaceViewRenderer
android:id="#+id/video_render"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<com.netease.nimlib.sdk.avchat.model.AVChatSurfaceViewRenderer
android:id="#+id/bypass_video_render"
android:layout_width="110dip"
android:layout_height="150dip"
android:layout_gravity="right|end|bottom"
android:layout_marginBottom="70dip"
android:layout_marginEnd="10dip"
android:layout_marginRight="10dip"
android:visibility="gone" />
<!--root view is FrameLayout with 40dip layout_margin and is a little complex-->
<include layout="#layout/layout_live_top" />
<!-- the content of this view will be scroll by touch event-->
<com.example.SimpleSlideView
android:id="#+id/slide_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- yellow background-->
<ImageView
android:id="#+id/yellow_child_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0" />
</com.example.SimpleSlideView>
</FrameLayout>
SimpleSlideView:
public class SimpleSlideView extends FrameLayout {
public int screenWidth;
public int screenHeight;
private float lastY;
public SimpleSlideView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
initScreenSize(context);
scrollTo(0, screenHeight);
}
private void initScreenSize(#NonNull Context context) {
DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
float rawY = ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
final int delta = (int) (rawY - lastY);
scrollTo(0, getScrollY() - (delta));
lastY = rawY;
break;
case MotionEvent.ACTION_UP:
scrollTo(0, screenHeight);
break;
}
return true;
}
}
I want to write a SimpleSlideView that can scroll it content down by pull down on it SimpleSlideView works as expected in lightweight XML but a little weird in complex XML.
#layout/layout_live_top contain a FrameLayout root view with 40dip layout_margin and layout_live_top is a little complex.
SimpleSlideView is a MatchParent view without padding and margin, same with it child #+id/yellow_child_view which has a yellow background.
Something weird is happen when quickly pulldown:
The yellow area has 40dip margin left and right at the beginning of the pull and then it become match parent.SimpleSlideView seems to be affected by the margin(40dip) of other view, it should be matched parent while pulling down.I don't know why this happened.It is because of my complex XML?
I recently implemented the Dragging and Scaling code that was offered on the Android Developer website FOUND HERE
The problem I am running into is in regards to the ability to move the view once it has been added to a layout. The image is scalable through the gesture but not movable.
This view is being added to a FrameLayout that is within a Fragment if that helps at all.
Has anyone ran into a similar problem implementing this Android example in a custom view? or can someone tell me what I am missing that I cannot move the views that I am adding.
public class CustomImageView extends View {
private static final int INVALID_POINTER_ID = 0;
Drawable _drawable;
// private static readonly int InvalidPointerId = -1;
// private int _activePointerId = InvalidPointerId;
private float _posX;
private float _posY;
private float mScaleFactor = 1.0f;
private int mActivePointerId = INVALID_POINTER_ID;
// gesture listeners
private ScaleGestureDetector mScaleDetector;
private float mLastTouchX;
private float mLastTouchY;
private float mPosY;
private float mPosX;
public CustomImageView(Context context, int resourceId) {
super(context, null, 0);
_drawable = getResources().getDrawable(resourceId);
_drawable.setBounds(0, 0, 200, 200);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
// TODO Auto-generated constructor stub
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(_posX, _posY);
canvas.scale(mScaleFactor, mScaleFactor);
_drawable.draw(canvas);
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = MotionEventCompat.getActionMasked(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
// Remember where we started (for dragging)
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer (for dragging)
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex = MotionEventCompat.findPointerIndex(ev,
mActivePointerId);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev,
pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(ev,
newPointerIndex);
}
break;
}
}
return true;
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}
Here is the XML, the root_layout that I am adding the views to is a FrameLayout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="#dimen/ab_height"
android:background="#color/red" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageButton
android:id="#+id/btn_Back"
android:layout_width="#dimen/width"
android:layout_height="fill_parent"
android:background="#color/red"
android:contentDescription="#string/desc"
android:src="#drawable/ic_navigation_back" />
<LinearLayout
android:layout_width="#dimen/dim_1"
android:layout_height="fill_parent"
android:background="#color/red" >
</LinearLayout>
<TextView
android:id="#+id/text_name"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:tag="bold"
android:text="Pixagram"
android:textColor="#color/white"
android:textSize="#dimen/tex_size_xxxlarge"
android:textStyle="bold" />
<LinearLayout
android:layout_width="#dimen/dim_1"
android:layout_height="fill_parent"
android:background="#color/red" >
</LinearLayout>
<ImageButton
android:id="#+id/btn_Accept"
android:layout_width="#dimen/width"
android:layout_height="fill_parent"
android:background="#color/red"
android:contentDescription="#string/desc"
android:src="#drawable/ic_navigation_accept" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="#dimen/dim_1"
android:background="#color/red" >
</LinearLayout>
<FrameLayout
android:id="#+id/root_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<ImageView
android:id="#+id/imageViewEdit"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/abc_ab_solid_dark_holo" />
</FrameLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="50dp"
android:background="#color/red"
android:orientation="horizontal" >
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="bottom"
android:gravity="bottom"
android:background="#color/transparent" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:background="#color/transparent" >
<ImageButton
android:id="#+id/imageButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ic_clear" />
<ImageButton
android:id="#+id/imageButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_tab_selected_pressed_holo" />
<ImageButton
android:id="#+id/imageButton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ic_clear" />
<ImageButton
android:id="#+id/imageButton4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_tab_selected_pressed_holo" />
<ImageButton
android:id="#+id/imageButton5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ic_clear" />
<ImageButton
android:id="#+id/imageButton6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_tab_selected_pressed_holo" />
<ImageButton
android:id="#+id/imageButton7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ic_clear" />
<ImageButton
android:id="#+id/imageButton8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_tab_selected_pressed_holo" />
<ImageButton
android:id="#+id/imageButton9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ic_clear" />
<ImageButton
android:id="#+id/imageButton10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_tab_selected_pressed_holo" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</LinearLayout>
This seems to show that ACTION_MOVE is not getting called
09-23 23:14:46.310: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch Down
09-23 23:14:46.350: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch UP
09-23 23:14:47.300: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch Down
09-23 23:14:47.790: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch UP
09-23 23:14:48.000: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch Down
09-23 23:14:48.030: I/ViewRootImpl(24235): ViewRoot's Touch Event :261
09-23 23:14:48.670: I/ViewRootImpl(24235): ViewRoot's Touch Event :6
09-23 23:14:48.710: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch UP
09-23 23:14:48.980: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch Down
09-23 23:14:49.320: I/ViewRootImpl(24235): ViewRoot's Touch Event : Touch UP
Although I haven't dug carefully through all of your code, it looks like that in your onDraw() method, you are translating by _posX and _posY, but you don't change these anywhere in your gesture handling. Try using mPosX and mPosY in onDraw() instead.
I'm using gallery view inside scoll view but gallery view not working properly.
My custom GalleryView
<com.divum.Adapter.CustomGallery
android:id="#+id/gallery"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fadingEdge="none"
android:spacing="10dp" />
Adapter Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/top_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="2dp"
android:orientation="vertical"
android:weightSum="100">
<TextView
android:id="#+id/txt_title1"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:padding="5dp"
android:textColor="#color/black"
android:textSize="14dp" />
<ImageView
android:id="#+id/image1"
android:layout_width="fill_parent"
android:layout_height="65dp"
android:layout_marginTop="2dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:layout_marginLeft="2dp" />
<ScrollView
android:scrollHorizontally="false"
android:fadingEdge="none"
android:scrollbars="none"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txt_details"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:padding="5dp"
android:textColor="#color/black"
android:textSize="14dp" />
</ScrollView>
</LinearLayout>
My problem is scrollview(vertically) working fine. The galleryview(horizontally) swiping is not working...
This is well known bug: ScrollView intercept both horizontal and vertical touch events. You can use this custom scroll view instead of standard one. This intercept only vertical touches:
public class VerticalScrollView extends ScrollView {
private float xDistance, yDistance, lastX, lastY;
public VerticalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
lastX = ev.getX();
lastY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - lastX);
yDistance += Math.abs(curY - lastY);
lastX = curX;
lastY = curY;
if (xDistance > yDistance)
return false;
}
return super.onInterceptTouchEvent(ev);
}
}
I have a layout where I have a ScrollView and some stuffs. It looks like:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/welcome_scrol_lay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="#drawable/bg">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/bg"
android:weightSum="100" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:orientation="vertical"
android:weightSum="100"
android:background="#drawable/specialmapholder">
<android.support.v4.view.ViewPager
android:id="#+id/welcomeViewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_weight="90"
android:clickable="true" />
<LinearLayout
android:id="#+id/welcome_indicatorLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:gravity="center" >
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="50"
android:orientation="vertical">
<TextView
android:id="#+id/welcome_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="Large Text"
android:textColor="#color/white"
android:textStyle="bold"
android:textSize="26dp"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/welcome_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="Medium Text"
android:textColor="#color/white"
android:textSize="14dp"
android:textStyle="bold"
android:layout_marginTop="20dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
</LinearLayout>
</ScrollView>
As you can see I have a Viewpager in the ScrollView. I want to disable scroll when I touch ViewPager, because when I want to change picture page is scrolled. How can I disable the scroll function when I touch the ViewPager?
In Android, parents can consume child's TouchEvents. In this case, the ScrollView consumes the TouchEvents of your ViewPager component. To avoid this behaviour, Android framework provides the onInterceptTouchEvent(MotionEvent).
In your case, you have to subclass ScrollView and change the onInterceptTouchEvent(MotionEvent) method. You should change the onInterceptTouchEvent(MotionEvent), so that the ScrollView consumes the child's event only when the user scrolls the ScrollView vertically.
example implementation for ListView:
public class VerticalListView extends ListView {
private float mLastX;
private float mLastY;
private float mDiffX;
private float mDiffY;
public VerticalListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticalListView(Context context) {
super(context);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// reset difference values
mDiffX = 0;
mDiffY = 0;
mLastX = ev.getX();
mLastY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
mDiffX += Math.abs(curX - mLastX);
mDiffY += Math.abs(curY - mLastY);
mLastX = curX;
mLastY = curY;
// don't intercept event, when user tries to scroll horizontally
if (mDiffX > mDiffY) {
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
}