Scrollview+Viewpager+フラグメントスライドの競合と高さの問題の修復

この組み合わせに遭遇したとき、私は多くの関連情報を確認しました。誰もが異なる状況に遭遇しましたが、それらの多くは実現できなかったり、要件を満たしていませんでした。ここに記録して、問題の解決に使用してください: Android 開発の複雑さレイアウトのネスト(ScrollView+TabLayout+ViewPager+RecyclerView) による競合の解決策_Huang Qingqing の World-CSDN ブログ

使用するものを整理: 見やすく

一般的なレイアウト:

<?xml version="1.0"coding="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:方向 = "垂直">

            <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" />
            <!-- プレースホルダー レイアウト、デフォルトは消えた状態です。TabLayout が削除されると、その状態は表示され、「プレースホルダー」効果に達します。 -->
            <ビュー
                android:id="@+id/view_place"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:可視性 = "なくなった" />

            <com.hq.testscrollview.AutofitViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </LinearLayout>
    </com.hq.testscrollview.InterceptScrollView>

    <!-- 画面上に浮いている一番上の空のレイアウト -->
    <LinearLayout
        android:id="@+id/container_top"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="vertical">

    </LinearLayout>
</RelativeLayout>
2 つのカスタム コントロール コード:

public class InterceptScrollView extends ScrollView {

    プライベート int lastInterceptX;
    private int lastInterceptY;

    プライベート 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:                 インターセプト = false;                 壊す;             case MotionEvent.ACTION_MOVE:                 int deltaX = x - lastInterceptX;                 int deltaY = y - lastInterceptY;                 //結果が垂直滑動である場合、その                 場合 if (Math.abs(deltaX) - Math.abs(deltaY) < 0) {                     intercept = true;                 } それ以外 {














                    切片 = false;
                }

                Break;
            case MotionEvent.ACTION_UP:
                intercept = false;
                Break;
        }
        lastInterceptX = x;
        lastInterceptY = y;
        super.onInterceptTouchEvent(ev);//このセンテンスを見逃してはなりません、そうしないとイベントをインターセプトできません
        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 リスナー){         onScrollChangedListener = リスナー;     }

    public Interface ScrollChangedListener{         void onScrollChanged(intscrollX, intscrollY, int oldScrollX, int oldScrollY);     } }


属性を使うとfillViewportうまくいかないので、高さが0と表示される問題を解決するメソッドをViewPager書き換えます。onmeasure書き換えるとViewPager、コードは次のようになります。

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(intposition) {                 requestLayout();//高さ適応効果を実現するために、現在のページが選択されるたびに高さを計算することが保証されます             }

            @Override
            public void onPageScrollStateChanged(int state) {             }         });     }


    //高さが0と表示される問題を解決するためにonMeasureを書き換え、高さが現在の子の高さとして動的に表示される @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(幅測定仕様, 高さ測定仕様);
    }

これ
は一般的な解決策です。

はじめに を見てみましょうCoordinatorLayout。そのため、多くのスペースを費やして説明するつもりはありません。このレイアウトに興味がある場合は、さらに詳しく学ぶことができます。もちろん、このレイアウトを使用する前に、依存関係を追加することを忘れないでくださいsupport:design。ライブラリを作成し、レイアウト コードをその直下に置きます。

<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 ="修正"
            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" />

このレイアウト
は、さまざまな高さ、スライドの競合、その他の問題を処理するさまざまなビューページャーとフラグメントの多くを解決できます。

おすすめ

転載: blog.csdn.net/qq_25462179/article/details/121116720