Android Question Scrollview inside Scrollview

Kevin Beckett

Member
Licensed User
Although B4i works nicely with a ScrollView inside a Scrollview, B4A does not.
Is there a way to make it happen for Android?
I have a large Scrollview for the bulk of the screen, then inside that large Scrollview I have some labels and two smaller Scrollviews. Each of the smaller Scrollviews contains a label that is many lines long.
 

walterf25

Expert
Licensed User
Although B4i works nicely with a ScrollView inside a Scrollview, B4A does not.
Is there a way to make it happen for Android?
I have a large Scrollview for the bulk of the screen, then inside that large Scrollview I have some labels and two smaller Scrollviews. Each of the smaller Scrollviews contains a label that is many lines long.
It is totally possible to make this work, i have done it in the past, although it is not recommended to use nested scrollviews, the way i've made this work described here in this post:
https://stackoverflow.com/questions/4490821/scrollview-inside-scrollview#13634181

Good luck!
Walter
 
Upvote 0

Kevin Beckett

Member
Licensed User
It is totally possible to make this work, i have done it in the past, although it is not recommended to use nested scrollviews, the way i've made this work described here in this post:
https://stackoverflow.com/questions/4490821/scrollview-inside-scrollview#13634181

Good luck!
Walter
Thanks Walter. Please could you let me know where I should put that code? I've tried putting it into the Main module surrounded by #IF JAVA ... #END IF but the compiler says
javac 1.8.0_171
main.java:2445: error: <identifier> expected
Private void makeMyScrollSmart() {
^
1 error
 
Upvote 0

JordiCP

Well-Known Member
Licensed User
javac 1.8.0_171
main.java:2445: error: <identifier> expected
Private void makeMyScrollSmart() {
^
1 error
Java is case-sensitive, and it seems that you pasted the text before enclosing it between "#IF JAVA" and "#END IF", so the IDE capitalized the recognized words thinking that it was a B4A statement --> change it to "private" (lower-cased) and make sure that it hasn't happened the same with the other pasted lines.

I haven't tested the above code, but if it works (I assume so), there is still a part missing: it will need a slight modification to accept the child scrollview as a parameter, and then it will have to be called from B4A through JavaObject
 
Upvote 0

Kevin Beckett

Member
Licensed User
Java is case-sensitive, and it seems that you pasted the text before enclosing it between "#IF JAVA" and "#END IF", so the IDE capitalized the recognized words thinking that it was a B4A statement --> change it to "private" (lower-cased) and make sure that it hasn't happened the same with the other pasted lines.

I haven't tested the above code, but if it works (I assume so), there is still a part missing: it will need a slight modification to accept the child scrollview as a parameter, and then it will have to be called from B4A through JavaObject

Thanks JordiCP, I've re-pasted the code but still need some help.

I have got a basic JavaObject to work OK in the Main module:
#If JAVA
public String FirstMethod() {
return "Hello from Java!";
}
#End If
Sub Process_Globals
Private java_testing As JavaObject
End Sub
Sub Activity_Create(FirstTime As Boolean)
If FirstTime Then
java_testing.InitializeContext
End If
Dim s As String = java_testing.RunMethod("FirstMethod", Null)
Log(s) ' prints Hello from Java!
End Sub

But when I add the code for ScrollViews I get a compiler error saying that the View symbol/package is not recognised:

Compiling generated Java code. Error
javac 1.8.0_171
main.java:2701: error: cannot find symbol
private void requestDisallowParentInterceptTouchEvent(View __v, Boolean __disallowIntercept) {
^
symbol: class View
location: class main
1 error

I'm guessing that View is some kind of foundation class from which ScrollView is descended.

This is the code I have pasted in:

#If JAVA
private void makeMyScrollSmart() {
myScroll.setOnTouchListener(new View.OnTouchListener() {
@override
public boolean onTouch(View __v, MotionEvent __event) {
if (__event.getAction() == MotionEvent.ACTION_DOWN) {
// Disallow the touch request for parent scroll on touch of child view
requestDisallowParentInterceptTouchEvent(__v, true);
} else if (__event.getAction() == MotionEvent.ACTION_UP || __event.getAction() == MotionEvent.ACTION_CANCEL) {
// Re-allows parent events
requestDisallowParentInterceptTouchEvent(__v, false);
}
return false;
}
});
}

private void requestDisallowParentInterceptTouchEvent(View __v, Boolean __disallowIntercept) {
while (__v.getParent() != null && __v.getParent() instanceof View) {
if (__v.getParent() instanceof ScrollView) {
__v.getParent().requestDisallowInterceptTouchEvent(__disallowIntercept);
}
__v = (View) __v.getParent();
}
}
#End If
 
Upvote 0

JordiCP

Well-Known Member
Licensed User
For better readability, you can add [CODE ] (here the code ) [/CODE ] tags (without the spaces after the 'E' !!) before and after it

For the current error, add a line after the "#IF JAVA"
B4X:
#IF JAVA
   import android.view.View;            // This will prevent the current error from appearing
   import android.view.MotionEvent; // This will prevent the next error from appearing
    
   // here the rest of the Java code. We change function declaration, since current code doesn't know where myScroll is (the StackOverflow code was just an example)
  private void makeMyScrollSmart( View myScroll ) {
     //..
  }
Call this function with the child scrollView as a parameter.

Can't tell if it will work, but these changes will at least remove the current errors
 
Upvote 0

Kevin Beckett

Member
Licensed User
Thanks, it now compiles after a third import:
B4X:
    import android.widget.ScrollView;
Declaration:
B4X:
    private void makeMyScrollSmart(View myScroll) {

In B4A I've got a ScrollView called sclSfComments.
When B4A displays that ScrollView, it now calls this:
B4X:
    Dim java_view As View
    java_view = sclSfComments
    java_testing.RunMethod("makeMyScrollSmart", Array(java_view))
but B4A crashes at runtime with:
B4X:
    Error occurred on line: 783 (Main)
    java.lang.RuntimeException: Method: makeMyScrollSmart not found in: b4a.RDR_Support.main

Don't worry about responding quickly to this, you've helped a lot already, thanks.
 
Upvote 0

Kevin Beckett

Member
Licensed User
For the benefit of anyone else who wants to do this, and is as inexperienced with Java as I am, this is what I ended up doing, with help from JordiCP and walterf25:
B4X:
Sub Process_Globals
    Private java_object As JavaObject
End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        java_object.InitializeContext
    End If
End Sub

#If JAVA
import android.view.View;
import android.view.MotionEvent;
import android.widget.ScrollView;

public void makeMyScrollSmart(View myScroll) {
    myScroll.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View __v, MotionEvent __event) {
            if (__event.getAction() == MotionEvent.ACTION_DOWN) {
                //  Disallow the touch request for parent scroll on touch of child view
                requestDisallowParentInterceptTouchEvent(__v, true);
            } else if (__event.getAction() == MotionEvent.ACTION_UP || __event.getAction() == MotionEvent.ACTION_CANCEL) {
                // Re-allows parent events
                requestDisallowParentInterceptTouchEvent(__v, false);
            }
            return false;
        }
    });
}

private void requestDisallowParentInterceptTouchEvent(View __v, Boolean __disallowIntercept) {
    while (__v.getParent() != null && __v.getParent() instanceof View) {
        if (__v.getParent() instanceof ScrollView) {
            __v.getParent().requestDisallowInterceptTouchEvent(__disallowIntercept);
        }
        __v = (View) __v.getParent();
    }
}
#End If

Sub displayMyScroll
    Dim java_view As View
    java_view = sclSfDetails ' the name of my ScrollView object
    java_object.RunMethod("makeMyScrollSmart", Array(java_view))
End Sub
 
Upvote 0

walterf25

Expert
Licensed User
For the benefit of anyone else who wants to do this, and is as inexperienced with Java as I am, this is what I ended up doing, with help from JordiCP and walterf25:
B4X:
Sub Process_Globals
    Private java_object As JavaObject
End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        java_object.InitializeContext
    End If
End Sub

#If JAVA
import android.view.View;
import android.view.MotionEvent;
import android.widget.ScrollView;

public void makeMyScrollSmart(View myScroll) {
    myScroll.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View __v, MotionEvent __event) {
            if (__event.getAction() == MotionEvent.ACTION_DOWN) {
                //  Disallow the touch request for parent scroll on touch of child view
                requestDisallowParentInterceptTouchEvent(__v, true);
            } else if (__event.getAction() == MotionEvent.ACTION_UP || __event.getAction() == MotionEvent.ACTION_CANCEL) {
                // Re-allows parent events
                requestDisallowParentInterceptTouchEvent(__v, false);
            }
            return false;
        }
    });
}

private void requestDisallowParentInterceptTouchEvent(View __v, Boolean __disallowIntercept) {
    while (__v.getParent() != null && __v.getParent() instanceof View) {
        if (__v.getParent() instanceof ScrollView) {
            __v.getParent().requestDisallowInterceptTouchEvent(__disallowIntercept);
        }
        __v = (View) __v.getParent();
    }
}
#End If

Sub displayMyScroll
    Dim java_view As View
    java_view = sclSfDetails ' the name of my ScrollView object
    java_object.RunMethod("makeMyScrollSmart", Array(java_view))
End Sub
Awesome you got it to work, i could have saved you a lot of trouble but it was midnight here when i replied to your post, anyhow i'm glad to see you got it working.

Walter
 
Upvote 0
Top