When I came across this combination, I checked a lot of related information. Everyone encountered different situations. Many of them could not be implemented or did not meet the needs: record them here and used them to solve my problem: Complex layout nesting in Android development ( ScrollView+TabLayout+ViewPager+RecyclerView) causes conflict resolution - Huang Qingqing's World - CSDN Blog
Organize what I use: easy to view
General layout:
<?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">
<com.hq.testscrollview.InterceptScrollView
android:id="@+id/interceptScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/container_normal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/top_info"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="顶部内容模块添加"
android:textSize="18sp" />
</RelativeLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@android:color/white"
app:tabMode ="fixed"
app:tabSelectedTextColor="@android:color/black" />
<!-- The placeholder layout is in the gone state by default. When the TabLayout is removed, its state is changed to visible, reaching "placeholder" Effect -->
<View
android:id="@+id/view_place"
android:layout_width="match_parent"
android:layout_height="50dp"
android:visibility="gone" />
<com.hq.testscrollview.AutofitViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</com.hq.testscrollview.InterceptScrollView>
<!-- Top empty layout suspended above the screen-->
<LinearLayout
android:id="@+id/container_top"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="vertical">
</LinearLayout>
</RelativeLayout>
Two custom control codes:
public class InterceptScrollView extends ScrollView {
private int lastInterceptX;
private int lastInterceptY;
private ScrollChangedListener onScrollChangedListener;
public InterceptScrollView(Context context) {
super(context);
}
public InterceptScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InterceptScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
intercept = false;
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x - lastInterceptX;
int deltaY = y - lastInterceptY;
//如果是垂直滑动,则拦截
if (Math.abs(deltaX) - Math.abs(deltaY) < 0) {
intercept = true;
} else {
intercept = false;
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
lastInterceptX = x;
lastInterceptY = y;
super.onInterceptTouchEvent(ev);//This sentence must not be missed, otherwise the event cannot be intercepted
return intercept;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if(onScrollChangedListener!=null){
onScrollChangedListener.onScrollChanged(l,t,oldl,oldt);
}
}
public void setScrollChangedListener(ScrollChangedListener listener){
onScrollChangedListener = listener;
}
public interface ScrollChangedListener{
void onScrollChanged(int scrollX, int scrollY, int oldScrollX, int oldScrollY);
}
}
Using fillViewport
attributes does not work, then we will rewrite ViewPager
the onmeasure
method to solve the problem that the height is displayed as 0. Rewritten ViewPager
, the code is as follows:
public class AutofitViewPager extends ViewPager {
public AutofitViewPager(@NonNull Context context) {
this(context,null);
}
public AutofitViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) { requestLayout(); // Ensure that each time the current page is selected, the height is calculated to achieve height adaptive effect }
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
//Rewrite onMeasure to solve the problem that the height is displayed as 0, and the height is dynamically displayed as the height of the current child
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = 0; for (int i = 0; i < getChildCount (); i++) { View child = getChildAt(i); child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = child.getMeasuredHeight(); if(i==getCurrentItem()) { height=h; } } heightMeasureSpec = MeasureSpec. makeMeasureSpec(height, MeasureSpec. EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
This is a common solution.
Let’s take a look at the introduction below CoordinatorLayout
, so I won’t spend a lot of space explaining it. Those who are interested in this layout can learn more about it. Of course, before using this layout, remember to add the support:design
dependent libraries. Put the layout code directly below:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
android:background="@android:color/white">
<RelativeLayout
android:id="@+id/title_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_scrollFlags="scroll">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="顶部内容模块"
android:textSize="18sp" />
</RelativeLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@android:color/white"
app:tabMode="fixed"
app:tabSelectedTextColor="@android:color/black" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
This layout can solve many complex viewpager+fragment problems such as various heights and sliding conflicts.