簡體   English   中英

Android NestedScrollView 不適用於 viewpager 布局

[英]Android NestedScrollView doesn't work in layout with viewpager

這是我的布局: 在此處輸入圖片說明

當我在 viewPager 中滾動 recyclerView 時,我希望能夠滾動布局的上半部分(帶有名稱、圖像、跟隨者的文本視圖...),所以我讀到我可以使用 NestedScrollView 來實現它,所以我把 NestedScrollView作為我的根布局:

NestedScrollView:
-----------------ConstraintLayout:
---------------------------------rest of the views as in picture above

我還在 NEstedScrollView 中添加了 android:fillViewport="true" 因為這解決了缺少視圖尋呼機的問題。 所以問題是滾動視圖不起作用,一切都與使用 nestedScrollView 之前相同,當我滾動 recyclerView 時,布局的底部不會滾動屏幕。 有誰知道為什么,我使用嵌套的滾動視圖是否錯誤,我還沒有找到任何可以解決我的問題的示例,而且文檔非常糟糕。 我的布局的 XML 代碼:

<androidx.core.widget.NestedScrollView
        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"
        android:fillViewport="true">

    <androidx.constraintlayout.widget.ConstraintLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        <androidx.appcompat.widget.Toolbar
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:theme="?attr/actionBarTheme"
                android:minHeight="?attr/actionBarSize"
                android:elevation="4dp"
                android:id="@+id/title"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:title="UserName"
                app:layout_constraintEnd_toEndOf="parent"/>

        <de.hdodenhof.circleimageview.CircleImageView
                android:id="@+id/profile_image"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_margin="8dp"
                app:srcCompat="@drawable/ic_profile_24dp"
                tools:src="@drawable/ic_profile_24dp"
                app:civ_border_color="@color/primaryLightColor"
                app:civ_border_width="1dp" android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/title" android:layout_marginStart="8dp"
                app:layout_constraintStart_toStartOf="parent" android:layout_marginLeft="8dp"/>
        <TextView
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:id="@+id/textView"
                app:layout_constraintEnd_toEndOf="parent"
                android:layout_marginEnd="8dp" android:layout_marginRight="8dp"
                app:layout_constraintStart_toEndOf="@+id/profile_image" android:layout_marginLeft="8dp"
                android:layout_marginStart="8dp"
                app:layout_constraintBottom_toBottomOf="@+id/profile_image"
                app:layout_constraintTop_toTopOf="@+id/profile_image"
                tools:text="Short description "/>

        <TextView
                android:id="@+id/questions_label"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="@string/questions"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/profile_image" app:layout_constraintStart_toStartOf="parent"
                android:layout_marginLeft="8dp" android:layout_marginStart="8dp"
                app:layout_constraintHorizontal_bias="0.5" app:layout_constraintEnd_toStartOf="@+id/followers_label"/>
        <TextView
                android:id="@+id/questions_number"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:textSize="18sp"
                android:textStyle="bold"
                tools:text="0"
                app:layout_constraintTop_toBottomOf="@+id/questions_label"
                app:layout_constraintEnd_toEndOf="@+id/questions_label"
                app:layout_constraintStart_toStartOf="@+id/questions_label"/>

        <TextView
                android:id="@+id/followers_label"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="@string/followers"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/profile_image"
                app:layout_constraintStart_toEndOf="@+id/questions_label" android:layout_marginStart="8dp"
                android:layout_marginLeft="8dp" android:layout_marginEnd="8dp"
                app:layout_constraintEnd_toStartOf="@+id/following_label" android:layout_marginRight="8dp"
                app:layout_constraintHorizontal_bias="0.5"/>

        <TextView
                android:id="@+id/following_label"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="@string/following"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/profile_image" android:layout_marginEnd="8dp"
                app:layout_constraintEnd_toEndOf="parent" android:layout_marginRight="8dp"
                app:layout_constraintStart_toEndOf="@+id/followers_label" app:layout_constraintHorizontal_bias="0.5"/>
        <TextView
                android:id="@+id/followers_number"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:textSize="18sp"
                android:textStyle="bold"
                tools:text="0"
                app:layout_constraintEnd_toEndOf="@+id/followers_label"
                app:layout_constraintStart_toStartOf="@+id/followers_label"
                app:layout_constraintTop_toBottomOf="@+id/followers_label"/>
        <TextView
                android:id="@+id/following_number"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:textSize="18sp"
                android:textStyle="bold"
                tools:text="0"
                app:layout_constraintEnd_toEndOf="@+id/following_label"
                app:layout_constraintStart_toStartOf="@+id/following_label"
                app:layout_constraintTop_toBottomOf="@+id/following_label"/>

        <com.google.android.material.tabs.TabLayout
                android:id="@+id/sliding_tabs"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:background="@color/primaryLightColor"
                app:tabMode="fixed" app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/followers_number"/>

        <androidx.viewpager.widget.ViewPager
                android:id="@+id/view_pager"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:background="@android:color/white"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

編輯:建議后的代碼:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        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">

    <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:theme="?attr/actionBarTheme"
                android:minHeight="?attr/actionBarSize"
                android:id="@+id/title"
                tools:title="UserName"/>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.constraintlayout.widget.ConstraintLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            <de.hdodenhof.circleimageview.CircleImageView
                    android:id="@+id/profile_image"
                    android:layout_width="80dp"
                    android:layout_height="80dp"
                    android:layout_marginStart="@dimen/spacing_normal"
                    android:layout_marginLeft="@dimen/spacing_normal"
                    android:layout_marginTop="@dimen/spacing_normal"
                    app:civ_border_color="@color/secondaryDarkColor"
                    app:civ_border_width="1dp"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    app:srcCompat="@drawable/ic_profile_24dp"
                    tools:src="@drawable/ic_profile_24dp" />

            <com.google.android.material.textview.MaterialTextView
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:id="@+id/description"
                    android:layout_marginEnd="@dimen/spacing_normal"
                    android:layout_marginRight="@dimen/spacing_normal"
                    android:layout_marginLeft="@dimen/spacing_normal"
                    android:layout_marginStart="@dimen/spacing_normal"
                    app:layout_constraintStart_toEndOf="@+id/profile_image"
                    app:layout_constraintEnd_toEndOf="parent"                    app:layout_constraintBottom_toBottomOf="@+id/profile_image"
                    app:layout_constraintTop_toTopOf="@+id/profile_image"
                    tools:text="Short description "/>

            <include
                    layout="@layout/qff_layout"
                    android:id="@+id/qff_layout"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/spacing_small"
                    app:layout_constraintTop_toBottomOf="@+id/profile_image"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"/>

            <com.google.android.material.tabs.TabLayout
                    android:id="@+id/sliding_tabs"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:background="@color/primaryLightColor"
                    app:tabMode="fixed"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/qff_layout"/>

            <androidx.viewpager.widget.ViewPager
                    android:id="@+id/view_pager"
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:background="@android:color/white"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

這里有什么問題,沒有任何意義,除了 ViewPager 沒有任何滾動

如您所知,NestedScrollView有一個孩子,如果您想要布局的滾動行為,則其孩子的身高必須為wrap_content

在第一個布局中,必須將ConstraintLayout的高度設置為wrap_content但是如果出於某種原因(例如,要將ViewPager綁定到布局的底部)希望使布局成為match_parent ,則必須使用建議的答案(表示您必須使用CoordinatorLayout ),但要考慮以下因素:

1-您應該將要滾動的所有內容放入AppbarLayout 。此布局是從LinearLayout擴展而來的,因此您可以輕松地將其放入其中。 從您的問題來看,我認為您想將所有內容滾動到ViewPager但是您可以根據需要進行更改。

(注意:實際上,我建議將CollapsingToolbar用作AppbarLAyout的子AppbarLAyout ,然后將其放入其中,但是對於您的問題,這也很好用)

2-在AppbarLayout內容根目錄中添加app:layout_scrollFlags="scroll"屬性

3-添加app:layout_behavior="@string/appbar_scrolling_view_behavior"屬性到你的兄弟姐妹AppbarLayout 在您的問題中,可以在NestedScrollView使用此屬性。

這是我的代碼:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    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">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            app:layout_scrollFlags="scroll"//I forget too add this, so I edit my answer
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            android:theme="?attr/actionBarTheme" />

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll"
            android:orientation="vertical">

            <View
                android:id="@+id/profile_image"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_marginStart="10dp"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="10dp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/description"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_marginStart="@dimen/spacing_normal"
                android:layout_marginLeft="@dimen/spacing_normal"
                android:layout_marginEnd="@dimen/spacing_normal"
                android:layout_marginRight="@dimen/spacing_normal"
                app:layout_constraintBottom_toBottomOf="@+id/profile_image"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/profile_image"
                app:layout_constraintTop_toTopOf="@+id/profile_image"
                tools:text="Short description " />

            <include
                layout="@layout/qff_layout"
                android:id="@+id/qff_layout"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/profile_image" />

            <com.google.android.material.tabs.TabLayout
                android:id="@+id/sliding_tabs"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:background="#559735"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/qff_layout"
                app:tabMode="fixed" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.viewpager.widget.ViewPager
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />
    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

我沒有嘗試過這段代碼,但是我很確定這對您有用:)

在NestedScrollView中放

app:layout_behavior="@string/appbar_scrolling_view_behavior"

您是否嘗試過這個:

<CoordinatorLayout>
...<AppbarLayout>
......<Toolbar/>
...</AppbarLayout>
...<NestedScrollView> (set height and weight to match parent, then set fillViewPort="true" and for the last give layout_behavior="@string/appbar_scrolling_view_behavior")
......<ConstraintLayout> (change height to wrap_content because you don't need to set match parent, its already handled by nestedscrollview as a parent)
.........(All Child Components)
......</ConstraintLayout>
...</NestedScrollView>
</CoordinatorLayout>

根據官方文檔,FillViewPort作為NestedScrollView的屬性是將內容的高度擴展到視口邊界。 請檢查官方文檔以獲取更好的解釋: NestedScrollView-FillViewPort

更新:根據您當前的代碼,我進行了一些更改,請檢查一下。

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        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">

    <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:theme="?attr/actionBarTheme"
                android:minHeight="?attr/actionBarSize"
                android:id="@+id/title"
                tools:title="UserName"/>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            <de.hdodenhof.circleimageview.CircleImageView
                    android:id="@+id/profile_image"
                    android:layout_width="80dp"
                    android:layout_height="80dp"
                    android:layout_marginStart="@dimen/spacing_normal"
                    android:layout_marginLeft="@dimen/spacing_normal"
                    android:layout_marginTop="@dimen/spacing_normal"
                    app:civ_border_color="@color/secondaryDarkColor"
                    app:civ_border_width="1dp"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    app:srcCompat="@drawable/ic_profile_24dp"
                    tools:src="@drawable/ic_profile_24dp" />

            <com.google.android.material.textview.MaterialTextView
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:id="@+id/description"
                    android:layout_marginEnd="@dimen/spacing_normal"
                    android:layout_marginRight="@dimen/spacing_normal"
                    android:layout_marginLeft="@dimen/spacing_normal"
                    android:layout_marginStart="@dimen/spacing_normal"
                    app:layout_constraintStart_toEndOf="@+id/profile_image"
                    app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/profile_image"
                    app:layout_constraintTop_toTopOf="@+id/profile_image"
                    tools:text="Short description "/>

            <include
                    layout="@layout/qff_layout"
                    android:id="@+id/qff_layout"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/spacing_small"
                    app:layout_constraintTop_toBottomOf="@+id/profile_image"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"/>

            <com.google.android.material.tabs.TabLayout
                    android:id="@+id/sliding_tabs"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:background="@color/primaryLightColor"
                    app:tabMode="fixed"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/qff_layout"/>

            <androidx.viewpager.widget.ViewPager
                    android:id="@+id/view_pager"
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:background="@android:color/white"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/sliding_tabs" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

您的內容適合您的顯示區域。 這就是它發生的原因。 為此,您必須設置ViewPager的固定高度。 之后,整個布局滾動。 但這不是一個適當的解決方案。

設置ViewPager高度500dp並檢查。

我將HorizontalScrollView用作上部布局的容器:

<ConstraintLayout>

    <Toolbar/>

    <HorizontalScrollView>
        <ConstraintLayout android:id="@+id/top_container">

                <!-- your upper widgets here -->

        </ConstraintLayout>
    </HorizontalScrollView>

    <TabLayout/>
    <ViewPager/>

</ConstraintLayout>

當用戶滾動ViewPager ,它將回調ViewPager.OnPageChangeListener.onPageScrolled() 您可以重寫它,以通過Horizo​​ntalScrollView.setScrollX()方法以編程方式滾動上部布局,該方法繼承自基本View類:

class ScrollListener implements ViewPager.OnPageChangeListener {
    private ViewGroup scrollView;

    ScrollListener(ViewGroup scrollView) {
        this.scrollView = scrollView;
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        scrollView.setScrollX(scrollView.getWidth() * position + positionOffsetPixels);
    }

// the interface requires to override 2 more methods:
    @Override
    public void onPageSelected(int position) {}

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

然后在MainActivity ,必須通過ViewPager.addOnPageChangeListener()將此偵聽器設置為ViewPager

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewGroup scrollView = findViewById(R.id.top_scroll);

        ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.addOnPageChangeListener(new ScrollListener(scrollView));
        viewPager.setAdapter(new MyAdapter(getApplicationContext(), 3));
}

注意:此代碼將壓縮上部布局,因為HorizontalScrollView不使用屏幕邊界進行度量和布局。 因此,它允許您將小部件置於屏幕之外( 屏幕截圖 ),並具有滾動功能。

在您的情況下,屏幕上沒有小部件,因此您不會看到結果,因為沒有任何可滾動的內容。 為了進行測試,我在MainActivity添加了幾行以拉伸上部布局:

        Point size = new Point();
        getWindowManager().getDefaultDisplay().getSize(size);

        ConstraintLayout upperLayout = findViewById(R.id.top_container);
        upperLayout .setMinWidth(size.x + 400);

我的git源代碼示例鏈接 (我通過觸摸移除了滾動的上部布局)

希望這有幫助,祝你好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM