ListView in Fragment in ViewPager in ScrollView for android> = 2.3
to directly answer the question:
Is it possible to do this?
Yes it is. You can see this example here under "Albums and Profiles". But this is not easy, not straightforward.
There are two problems with adding a ListView inside a ScrollView (you can look into it yourself), which TouchEvents is confusing because it doesn't know which View
touch will consume, and the system won't know how to expand the infinite size. View inside another endless sidez view.
Because it is not easy or easy to implement, there are several possible implementations, and they are all LOT of code and LOT of testing. I'll point you to an open source example and you can go from there:
source to share
The problem here is including the ListView inside the ScrollView. The steps below describe how to wrap any vertically scrolling view in another vertically scrolling view.
Step 1
Write a method that determines that the view can be scrolled vertically and put the method in the general utility class as follows. This method is taken from ViewPager.java and modified to determine if the view can be vertically scrolled.
public static boolean canScroll(View v, boolean checkV, int dy, int x, int y) {
if (v instanceof ViewGroup) {
final ViewGroup group = (ViewGroup) v;
final int scrollX = v.getScrollX();
final int scrollY = v.getScrollY();
final int count = group.getChildCount();
for (int i = count - 1; i >= 0; i--) {
final View child = group.getChildAt(i);
if (x + scrollX >= child.getLeft()
&& x + scrollX < child.getRight()
&& y + scrollY >= child.getTop()
&& y + scrollY < child.getBottom()
&& canScroll(child, true, dy,
x + scrollX - child.getLeft(), y + scrollY
- child.getTop())) {
return true;
}
}
}
return checkV && ViewCompat.canScrollVertically(v, -dy);
}
Step 2
The subclass covering the vertically scrolling view could be ScrollView or ListView (in your case it is ScrollView
) or the like, and override the onInterceptTouchEvent () method as follows.
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
float x = event.getX();
float y = event.getY();
float dy = y - mLastMotionY;
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
if (Util.canScroll(this, false, (int) dy, (int) x, (int) y)) {
mLastMotionY = y;
return false;
}
break;
}
return super.onInterceptTouchEvent(event);
}
Step 3
The subclass enclosed in the vertically scrolling view could be a GridView or ListView or the like (in your case ListView
) and override the onMeasure () method as follows. You don't need to override this method in the ScrollView. Its default implementation behaves correctly.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int mode = MeasureSpec.getMode(widthMeasureSpec);
if (mode == MeasureSpec.UNSPECIFIED) {
int height = getLayoutParams().height;
if (height > 0)
setMeasuredDimension(getMeasuredWidth(), height);
}
}
Step 4
Finally, create a layout xml file and subclass ScrollView and ListView and you have to hard codelayout_height
. If you are creating a view hierarchy with java code then hardcoded the height to LayoutParams
. This hard-coding is not required if you are using your own measurement strategy instead of the one shown in step 3.
For more information, please view this ScrollInsideScroll post , download the project and study the code.
source to share