使用 AppbarLayout 和 MotionLayout 实现常用的布局效果

前文我们讲了协调滚动的一些定义方式,我们在开发中常用的几种效果都可用 AppbarLayout 或 MotionLayout 来实现。

这里先上效果图

可能大家都比较会AppbarLayout这种实现方式,这里就直接上代码和效果图了。

一、AppbarLayout ViewPager

核心代码都在 CoordinatorLayout 闭包中

        <androidx.coordinatorlayout.widget.CoordinatorLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">
                <com.google.android.material.appbar.AppBarLayout
                    android:id="@ id/app_bar_layout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/white"
                    android:orientation="vertical"
                    app:elevation="0dp">
                    <!--   顶部的图片    -->
                    <androidx.constraintlayout.widget.ConstraintLayout
                        android:id="@ id/cl_img_box"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        app:layout_scrollFlags="scroll|snap">
                        <ImageView
                            android:id="@ id/image_view_photo_cover"
                            android:layout_width="0dp"
                            android:layout_height="0dp"
                            android:contentDescription="@string/part_time_jobs"
                            android:scaleType="centerCrop"
                            app:layout_constraintDimensionRatio="W,94:129"
                            app:layout_constraintLeft_toLeftOf="parent"
                            app:layout_constraintRight_toRightOf="parent"
                            app:layout_constraintTop_toTopOf="parent" />
                        <ProgressBar
                            android:id="@ id/progress_bar_job_detail"
                            android:layout_width="25dp"
                            android:layout_height="25dp"
                            android:layout_gravity="center"
                            android:indeterminate="true"
                            android:indeterminateTint="@color/colorAccent"
                            android:indeterminateTintMode="src_atop"
                            app:layout_constraintBottom_toBottomOf="parent"
                            app:layout_constraintLeft_toLeftOf="parent"
                            app:layout_constraintRight_toRightOf="parent"
                            app:layout_constraintTop_toTopOf="parent" />
                        <com.youth.banner.Banner
                            android:id="@ id/banner_employer_imgs"
                            android:layout_width="match_parent"
                            android:layout_height="0dp"
                            android:background="@drawable/iv_promotion_merchant_detail_placehold_bg"
                            app:banner_auto_loop="false"
                            app:banner_indicator_height="@dimen/d_5dp"
                            app:banner_indicator_marginBottom="@dimen/d_15dp"
                            app:banner_indicator_normal_color="#66ffffff"
                            app:banner_indicator_normal_width="@dimen/d_4dp"
                            app:banner_indicator_selected_color="#ffffff"
                            app:banner_indicator_selected_width="@dimen/d_6dp"
                            app:banner_indicator_space="@dimen/d_4dp"
                            app:banner_infinite_loop="true"
                            app:layout_constraintDimensionRatio="W,94:129"
                            app:layout_constraintLeft_toLeftOf="parent"
                            app:layout_constraintRight_toRightOf="parent"
                            app:layout_constraintTop_toTopOf="parent" />
                        <LinearLayout
                            android:id="@ id/ll_gallery_box"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_marginRight="@dimen/d_15dp"
                            android:layout_marginBottom="@dimen/d_10dp"
                            android:background="@drawable/shape_job_detail_gallery_box"
                            android:gravity="center"
                            android:orientation="horizontal"
                            app:layout_constraintBottom_toBottomOf="parent"
                            app:layout_constraintRight_toRightOf="parent">
                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:drawableLeft="@drawable/job_detail_gallery_icon"
                                android:drawablePadding="@dimen/d_7dp"
                                android:paddingLeft="@dimen/d_10dp"
                                android:paddingTop="@dimen/d_6dp"
                                android:paddingRight="@dimen/d_10dp"
                                android:paddingBottom="@dimen/d_6dp"
                                android:text="@string/gallery"
                                android:textColor="@color/white"
                                android:textSize="@dimen/d_14sp" />
                        </LinearLayout>
                    </androidx.constraintlayout.widget.ConstraintLayout>
                    <!--   Tab布局         -->
                    <FrameLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content">
                        <com.google.android.material.tabs.TabLayout
                            android:id="@ id/tabLayout"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:background="@color/white"
                            app:tabIndicator="@drawable/shape_blue_bottom_line_3conner"
                            app:tabIndicatorColor="@color/app_blue"
                            app:tabIndicatorFullWidth="false"
                            app:tabIndicatorHeight="@dimen/d_2dp"
                            app:tabMode="scrollable"
                            app:tabRippleColor="@color/transparent"
                            app:tabSelectedTextColor="@color/app_blue"
                            app:tabTextColor="@color/black" />
                        <ImageView
                            android:id="@ id/iv_tab_right"
                            android:layout_width="wrap_content"
                            android:layout_height="match_parent"
                            android:layout_gravity="right"
                            android:src="@drawable/job_detail_tab_right_arrow" />
                    </FrameLayout>
                    <View
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/d_6dp"
                        android:background="@color/page_background" />
                </com.google.android.material.appbar.AppBarLayout>
                <androidx.viewpager.widget.ViewPager
                    android:id="@ id/view_pager"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
            </androidx.coordinatorlayout.widget.CoordinatorLayout>

很平常的效果了,也是用的比较多的效果,定义起来非常简单,在AppbarLayout下面包裹2个View,图片View跟随滚动,而TabBarLayout则吸顶。

效果如下:

二、AppbarLayout RecyclerView

和上面一样的效果,这里我们可以指定下拉的时候把隐藏的布局显示出来,设置一个核心属性

app:layout_scrollFlags="scroll|snap|enterAlways

定义的布局如下:

        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <!--    顶部的筛选     -->
            <com.google.android.material.appbar.AppBarLayout
                android:id="@ id/app_bar_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@color/white"
                    android:orientation="vertical"
                    app:layout_scrollFlags="scroll|snap|enterAlways">
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="@dimen/d_12dp"
                        android:layout_marginTop="@dimen/d_12dp"
                        android:layout_marginRight="@dimen/d_12dp"
                        android:gravity="center_vertical"
                        android:orientation="horizontal">
                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="兼职推荐"
                            android:textColor="@color/black_33"
                            android:textSize="@{viewModel.mSortTypeLD == 1?@dimen/d_17sp:@dimen/d_15sp}"
                            binding:clicks="@{click.switchReCommend}"
                            binding:typefaceMediumOrBold="@{viewModel.mSortTypeLD == 1}"
                            tools:textSize="@dimen/d_17sp" />
                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_marginLeft="@dimen/d_15dp"
                            android:text="最新"
                            android:textColor="@color/black_33"
                            android:textSize="@{viewModel.mSortTypeLD == 2?@dimen/d_17sp:@dimen/d_15sp}"
                            binding:clicks="@{click.switchlatested}"
                            binding:typefaceMediumOrBold="@{viewModel.mSortTypeLD == 2}" />
                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_marginLeft="@dimen/d_15dp"
                            android:text="附近"
                            android:textColor="@color/black_33"
                            android:textSize="@{viewModel.mSortTypeLD == 3?@dimen/d_17sp:@dimen/d_15sp}"
                            binding:clicks="@{click.switchNearby}"
                            binding:typefaceMediumOrBold="@{viewModel.mSortTypeLD == 3}" />
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="@dimen/d_8dp"
                        android:orientation="horizontal"
                        android:paddingLeft="@dimen/d_15dp"
                        android:paddingRight="@dimen/d_15dp">
                        <TextView
                            android:layout_width="0dp"
                            android:layout_height="@dimen/d_27dp"
                            android:layout_weight="1"
                            android:background="@{viewModel.MPopupPositionTypeLD==1?@drawable/shape_blue_round2_border:@drawable/shape_white_gray_round2}"
                            android:drawableRight="@{viewModel.MPopupPositionTypeLD==1?@drawable/ic_drop_up_blue:@drawable/ic_drop_down_gray}"
                            android:gravity="center"
                            android:paddingLeft="@dimen/d_8dp"
                            android:paddingRight="@dimen/d_8dp"
                            android:text="全武汉"
                            android:textColor="@{viewModel.MPopupPositionTypeLD==1?@color/app_blue:@color/gray_66}"
                            android:textSize="@dimen/d_12sp"
                            binding:clicks="@{click.searchByLocationPopup}"
                            tools:drawableRight="@drawable/ic_drop_down_gray" />
                        <TextView
                            android:layout_width="0dp"
                            android:layout_height="@dimen/d_27dp"
                            android:layout_marginLeft="@dimen/d_5dp"
                            android:layout_weight="1"
                            android:background="@{viewModel.MPopupPositionTypeLD==2?@drawable/shape_blue_round2_border:@drawable/shape_white_gray_round2}"
                            android:drawableRight="@{viewModel.MPopupPositionTypeLD==2?@drawable/ic_drop_up_blue:@drawable/ic_drop_down_gray}"
                            android:gravity="center"
                            android:paddingLeft="@dimen/d_8dp"
                            android:paddingRight="@dimen/d_8dp"
                            android:text="职位类型"
                            android:textColor="@{viewModel.MPopupPositionTypeLD==2?@color/app_blue:@color/gray_66}"
                            android:textSize="@dimen/d_12sp"
                            binding:clicks="@{click.searchByPositionPopup}"
                            tools:drawableRight="@drawable/ic_drop_down_gray" />
                        <TextView
                            android:layout_width="0dp"
                            android:layout_height="@dimen/d_27dp"
                            android:layout_marginLeft="@dimen/d_5dp"
                            android:layout_weight="1"
                            android:background="@{viewModel.MPopupPositionTypeLD==3?@drawable/shape_blue_round2_border:@drawable/shape_white_gray_round2}"
                            android:drawableRight="@{viewModel.MPopupPositionTypeLD==3?@drawable/ic_drop_up_blue:@drawable/ic_drop_down_gray}"
                            android:gravity="center"
                            android:paddingLeft="@dimen/d_8dp"
                            android:paddingRight="@dimen/d_8dp"
                            android:text="日期"
                            android:textColor="@{viewModel.MPopupPositionTypeLD==3?@color/app_blue:@color/gray_66}"
                            android:textSize="@dimen/d_12sp"
                            binding:clicks="@{click.searchByDatePopup}"
                            tools:drawableRight="@drawable/ic_drop_down_gray" />
                        <TextView
                            android:layout_width="0dp"
                            android:layout_height="@dimen/d_27dp"
                            android:layout_marginLeft="@dimen/d_5dp"
                            android:layout_weight="1"
                            android:background="@{viewModel.MPopupPositionTypeLD==4?@drawable/shape_blue_round2_border:@drawable/shape_white_gray_round2}"
                            android:drawableRight="@{viewModel.MPopupPositionTypeLD==4?@drawable/ic_drop_up_blue:@drawable/ic_drop_down_gray}"
                            android:gravity="center"
                            android:paddingLeft="@dimen/d_8dp"
                            android:paddingRight="@dimen/d_8dp"
                            android:text="筛选"
                            android:textColor="@{viewModel.MPopupPositionTypeLD==4?@color/app_blue:@color/gray_66}"
                            android:textSize="@dimen/d_12sp"
                            binding:clicks="@{click.searchByFilterPopup}"
                            tools:drawableRight="@drawable/ic_drop_down_gray" />
                    </LinearLayout>
                    <View
                        android:id="@ id/view_popup_divider"
                        android:layout_width="match_parent"
                        android:layout_height="@dimen/d_1dp"
                        android:layout_marginTop="@dimen/d_10dp"
                        android:background="@color/main_divider" />
                </LinearLayout>
            </com.google.android.material.appbar.AppBarLayout>
            <!--   刷新 列表   -->
            <com.scwang.smart.refresh.layout.SmartRefreshLayout
                android:id="@ id/refresh_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:focusable="true"
                android:focusableInTouchMode="true"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"
                app:srlEnablePreviewInEditMode="true"
                app:srlPrimaryColor="@color/white"
                tools:visibility="gone">
                <com.scwang.smart.refresh.header.ClassicsHeader
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
                <androidx.recyclerview.widget.RecyclerView
                    android:id="@ id/recycler_view"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:overScrollMode="never"
                    android:scrollbars="vertical">
                </androidx.recyclerview.widget.RecyclerView>
            </com.scwang.smart.refresh.layout.SmartRefreshLayout>
        </androidx.coordinatorlayout.widget.CoordinatorLayout>

效果如下:

三、MotionLayout

MotionLayout的定义主要看xml中控件的start end 的位置与状态。

页面xml:

  <androidx.constraintlayout.motion.widget.MotionLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            app:layoutDescription="@xml/scene_part_job_detail">
            <!--   顶部的图片    -->
            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@ id/cl_top_img_box"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
                <ImageView
                    android:id="@ id/iv_job_image"
                    android:layout_width="0dp"
                    android:layout_height="0dp"
                    android:background="@color/gray"
                    android:scaleType="centerCrop"
                    app:layout_constraintDimensionRatio="W,219:375"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toRightOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
            </androidx.constraintlayout.widget.ConstraintLayout>
            <!-- 相册布局 -->
            <LinearLayout
                android:id="@ id/ll_gallery_box"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="@dimen/d_15dp"
                android:layout_marginBottom="@dimen/d_10dp"
                android:background="@drawable/shape_job_detail_gallery_box"
                android:gravity="center"
                android:orientation="horizontal"
                app:layout_constraintBottom_toBottomOf="@id/cl_top_img_box"
                app:layout_constraintRight_toRightOf="@id/cl_top_img_box"
                binding:clicks="@{click.gotoGalleryPage}">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:drawableLeft="@drawable/job_detail_gallery_icon"
                    android:drawablePadding="@dimen/d_7dp"
                    android:paddingLeft="@dimen/d_10dp"
                    android:paddingTop="@dimen/d_6dp"
                    android:paddingRight="@dimen/d_10dp"
                    android:paddingBottom="@dimen/d_6dp"
                    android:text="相册"
                    android:textColor="@color/white"
                    android:textSize="@dimen/d_14sp" />
            </LinearLayout>
            <!--   固定的状态栏 用于定位     -->
            <com.guadou.lib_baselib.view.titlebar.StatusbarGrayView
                android:id="@ id/status_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
            <!--   返回栏    -->
            <FrameLayout
                android:id="@ id/back_layout"
                android:layout_width="match_parent"
                android:layout_height="@dimen/d_40dp"
                android:background="@color/transparent"
                tools:layout_editor_absoluteY="24dp">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_marginLeft="@dimen/d_14dp"
                    android:layout_marginTop="@dimen/d_2dp"
                    android:src="@mipmap/back_white_icon" />
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical|right"
                    android:layout_marginRight="@dimen/d_15dp"
                    android:src="@drawable/part_detail_job_collect_icon" />
            </FrameLayout>
            <!--  工作信息等TextView    -->
            <TextView
                android:id="@ id/tv_job_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/d_15dp"
                android:layout_marginTop="@dimen/d_5dp"
                android:ellipsize="end"
                android:gravity="center"
                android:lines="1"
                android:singleLine="true"
                android:text="斗鱼主播招聘"
                android:textColor="@color/white"
                android:textSize="@dimen/d_20sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@id/back_layout" />
            <TextView
                android:id="@ id/tv_job_employer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/d_15dp"
                android:layout_marginTop="@dimen/d_10dp"
                android:text="武汉斗鱼网络科技有限公司"
                android:textColor="@color/white"
                android:textSize="@dimen/d_14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_job_title" />
            <TextView
                android:id="@ id/tv_job_hour"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/d_15dp"
                android:layout_marginTop="@dimen/d_10dp"
                android:text="100元/小时"
                android:textColor="@color/text_orange"
                android:textSize="@dimen/d_16sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_job_employer" />
            <TextView
                android:id="@ id/tv_job_industry"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/d_15dp"
                android:layout_marginTop="@dimen/d_8dp"
                android:text="江岸 | 主播"
                android:textColor="@color/white"
                android:textSize="@dimen/d_14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_job_hour" />
            <!--   Tab布局     -->
            <FrameLayout
                android:id="@ id/tab_layout_box"
                android:layout_width="match_parent"
                android:layout_height="@dimen/d_40dp">
                <com.google.android.material.tabs.TabLayout
                    android:id="@ id/tabLayout"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/d_40dp"
                    android:background="@color/white"
                    app:tabIndicator="@drawable/shape_blue_bottom_line_3conner"
                    app:tabIndicatorColor="@color/app_blue"
                    app:tabIndicatorFullWidth="false"
                    app:tabIndicatorHeight="@dimen/d_2dp"
                    app:tabMode="scrollable"
                    app:tabRippleColor="@color/transparent"
                    app:tabSelectedTextColor="@color/app_blue"
                    app:tabTextColor="@color/black" />
                <ImageView
                    android:id="@ id/iv_tab_right"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_gravity="right"
                    android:src="@drawable/job_detail_tab_right_arrow"
                    binding:clicks="@{click.tabNext}" />
            </FrameLayout>
            <!--   Fragment容器     -->
            <androidx.viewpager.widget.ViewPager
                android:id="@ id/view_pager"
                android:layout_width="match_parent"
                android:layout_height="0dp" />
        </androidx.constraintlayout.motion.widget.MotionLayout>

定义场景xml : 控件多的话,定义的东西也会比较多

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">
    <Transition
        motion:constraintSetEnd="@ id/end"
        motion:constraintSetStart="@ id/start"
        motion:duration="350">
        <OnClick
            motion:clickAction="toggle"
            motion:targetId="@id/cl_top_img_box" />
        <OnSwipe
            motion:dragDirection="dragUp"
            motion:touchAnchorId="@id/view_pager" />
    </Transition>
    <ConstraintSet android:id="@ id/start">
        <Constraint
            android:id="@id/cl_top_img_box"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/ll_gallery_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="@dimen/d_15dp"
            android:layout_marginBottom="@dimen/d_10dp"
            android:alpha="1"
            motion:layout_constraintBottom_toBottomOf="@id/cl_top_img_box"
            motion:layout_constraintRight_toRightOf="@id/cl_top_img_box" />
        <Constraint
            android:id="@id/status_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="0"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/back_layout"
            android:layout_width="match_parent"
            android:layout_height="@dimen/d_40dp"
            motion:layout_constraintTop_toBottomOf="@id/status_view" />
        <Constraint
            android:id="@id/tv_job_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="@dimen/d_5dp"
            android:layout_marginRight="@dimen/d_15dp"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/back_layout">
            <CustomAttribute
                motion:attributeName="textSize"
                motion:customFloatValue="20" />
        </Constraint>
        <Constraint
            android:id="@id/tv_job_employer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="@dimen/d_10dp"
            android:alpha="1"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/tv_job_title" />
        <Constraint
            android:id="@id/tv_job_hour"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="@dimen/d_10dp"
            android:alpha="1"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/tv_job_employer" />
        <Constraint
            android:id="@id/tv_job_industry"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="@dimen/d_8dp"
            android:alpha="1"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/tv_job_hour" />
        <Constraint
            android:id="@id/tab_layout_box"
            android:layout_width="match_parent"
            android:layout_height="@dimen/d_40dp"
            motion:layout_constraintTop_toBottomOf="@id/cl_top_img_box" />
        <Constraint
            android:id="@id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/tab_layout_box" />
    </ConstraintSet>
    <ConstraintSet android:id="@ id/end">
        <Constraint
            android:id="@id/cl_top_img_box"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="@id/back_layout"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/ll_gallery_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="@dimen/d_15dp"
            android:layout_marginBottom="@dimen/d_10dp"
            android:alpha="0"
            motion:layout_constraintBottom_toBottomOf="@id/cl_top_img_box"
            motion:layout_constraintRight_toRightOf="@id/cl_top_img_box" />
        <Constraint
            android:id="@id/status_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="0"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/back_layout"
            android:layout_width="match_parent"
            android:layout_height="@dimen/d_40dp"
            motion:layout_constraintTop_toBottomOf="@id/status_view" />
        <Constraint
            android:id="@id/tv_job_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_50dp"
            android:layout_marginTop="0dp"
            android:layout_marginRight="@dimen/d_50dp"
            motion:layout_constraintBottom_toBottomOf="@id/back_layout"
            motion:layout_constraintLeft_toLeftOf="@id/back_layout"
            motion:layout_constraintRight_toRightOf="@id/back_layout"
            motion:layout_constraintTop_toTopOf="@id/back_layout">
            <CustomAttribute
                motion:attributeName="textSize"
                motion:customFloatValue="20" />
        </Constraint>
        <Constraint
            android:id="@id/tv_job_employer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="@dimen/d_11dp"
            android:alpha="0"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/back_layout" />
        <Constraint
            android:id="@id/tv_job_hour"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="@dimen/d_11dp"
            android:alpha="0"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/tv_job_employer" />
        <Constraint
            android:id="@id/tv_job_industry"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="@dimen/d_8dp"
            android:alpha="0"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/tv_job_hour" />
        <Constraint
            android:id="@id/tab_layout_box"
            android:layout_width="match_parent"
            android:layout_height="@dimen/d_40dp"
            motion:layout_constraintTop_toBottomOf="@id/back_layout" />
        <Constraint
            android:id="@id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/tab_layout_box" />
    </ConstraintSet>
</MotionScene>

效果:

同样的效果我们可以用 MotionLayout 实现一些 Behavior 的效果:

   <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@ id/motion_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/page_bg"
        app:layoutDescription="@xml/scene_profile_page">
        <!--   状态栏   -->
        <com.guadou.lib_baselib.view.titlebar.StatusbarGrayView
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <!--  Profile顶部    -->
        <ImageView
            android:id="@ id/iv_top_bg"
            android:layout_width="0dp"
            android:layout_height="245dp"
            android:scaleType="fitXY"
            android:src="@drawable/profile_top_img_bg"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <!--    内部的头像 姓名等信息    -->
        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@ id/cl_name_info"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="30dp"
            android:layout_marginTop="50dp"
            android:layout_marginRight="15dp"
            android:orientation="horizontal"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent">
            <com.guadou.lib_baselib.view.CircleImageView
                android:id="@ id/iv_user_avatar"
                android:layout_width="74dp"
                android:layout_height="74dp"
                android:src="@color/gray"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
            <TextView
                android:id="@ id/iv_user_name"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/d_10dp"
                android:text="邓悠然"
                android:textColor="@color/black_33"
                android:textSize="@dimen/d_20sp"
                app:layout_constraintBottom_toTopOf="@id/tv_user_mobile"
                app:layout_constraintLeft_toRightOf="@id/iv_user_avatar"
                app:layout_constraintRight_toLeftOf="@id/tv_user_resume"
                app:layout_constraintTop_toTopOf="@id/iv_user_avatar" />
            <TextView
                android:id="@ id/tv_user_mobile"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_profile_mobile_bg"
                android:drawableLeft="@drawable/profile_mobile_icon"
                android:drawablePadding="4.5dp"
                android:paddingLeft="@dimen/d_10dp"
                android:paddingTop="@dimen/d_5dp"
                android:paddingRight="@dimen/d_10dp"
                android:paddingBottom="@dimen/d_5dp"
                android:text="18961023119"
                android:textColor="@color/black_33"
                android:textSize="@dimen/d_14sp"
                app:layout_constraintBottom_toBottomOf="@id/iv_user_avatar"
                app:layout_constraintLeft_toLeftOf="@id/iv_user_name"
                app:layout_constraintTop_toBottomOf="@id/iv_user_name" />
            <TextView
                android:id="@ id/tv_user_resume"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/shape_profile_resume_bg"
                android:drawableLeft="@drawable/profile_resume_icon"
                android:drawablePadding="@dimen/d_7dp"
                android:paddingLeft="@dimen/d_15dp"
                android:paddingTop="@dimen/d_8dp"
                android:paddingRight="@dimen/d_13dp"
                android:paddingBottom="@dimen/d_8dp"
                android:text="我的简历"
                android:textColor="@color/black_33"
                android:textSize="@dimen/d_14sp"
                app:layout_constraintBottom_toBottomOf="@id/iv_user_avatar"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="@id/iv_user_avatar"
                binding:clicks="@{click.gotoMyResume}" />
        </androidx.constraintlayout.widget.ConstraintLayout>
        <!--    内部的工作申请统计相关     -->
        <LinearLayout
            android:id="@ id/ll_job_info"
            android:layout_width="match_parent"
            android:layout_height="117dp"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="180dp"
            android:layout_marginRight="@dimen/d_15dp"
            android:background="@drawable/shape_white_round10"
            android:orientation="vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/d_20dp"
                android:layout_marginTop="14.5dp"
                android:text="我的投递"
                android:textColor="@color/black_33"
                android:textSize="@dimen/d_16sp" />
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal"
                android:paddingLeft="@dimen/d_5dp"
                android:paddingRight="@dimen/d_5dp">
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/selector_btn_white_gray_bg"
                    binding:clicks="@{click.gotoJobAll}">
                   ...
                </androidx.constraintlayout.widget.ConstraintLayout>
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/selector_btn_white_gray_bg"
                    binding:clicks="@{click.gotoJobPending}">
                   ...
                </androidx.constraintlayout.widget.ConstraintLayout>
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/selector_btn_white_gray_bg"
                    binding:clicks="@{click.gotoJobApplied}">
                    ...
                </androidx.constraintlayout.widget.ConstraintLayout>
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/selector_btn_white_gray_bg"
                    binding:clicks="@{click.gotoJobArrived}">
                   ...
                </androidx.constraintlayout.widget.ConstraintLayout>
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@drawable/selector_btn_white_gray_bg"
                    binding:clicks="@{click.gotoJobComplete}">
                    ...
                </androidx.constraintlayout.widget.ConstraintLayout>
            </LinearLayout>
        </LinearLayout>
        <!--    Profile底部列表     -->
        <androidx.core.widget.NestedScrollView
            android:id="@ id/scrollView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="@color/page_bg"
            android:fillViewport="true"
            android:overScrollMode="never"
            android:scrollbars="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@id/ll_job_info">
        ...
       </androidx.core.widget.NestedScrollView>
    </androidx.constraintlayout.motion.widget.MotionLayout>

定义的场景xml:

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">
    <Transition
        motion:constraintSetEnd="@ id/end"
        motion:constraintSetStart="@ id/start"
        motion:duration="350">
        <OnSwipe
            motion:dragDirection="dragUp"
            motion:touchAnchorId="@id/scrollView" />
        <KeyFrameSet>
            <KeyPosition
                motion:alpha="0"
                motion:framePosition="25"
                motion:keyPositionType="parentRelative"
                motion:motionTarget="@ id/cl_name_info" />
        </KeyFrameSet>
    </Transition>
    <ConstraintSet android:id="@ id/start">
        <Constraint
            android:id="@id/status_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="0"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/iv_top_bg"
            android:layout_width="0dp"
            android:layout_height="245dp"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/cl_name_info"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="30dp"
            android:layout_marginTop="50dp"
            android:layout_marginRight="15dp"
            android:alpha="1"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/ll_job_info"
            android:layout_width="match_parent"
            android:layout_height="117dp"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="180dp"
            android:layout_marginRight="@dimen/d_15dp"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/scrollView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/ll_job_info" />
    </ConstraintSet>
    <ConstraintSet android:id="@ id/end">
        <Constraint
            android:id="@id/status_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="1"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/iv_top_bg"
            android:layout_width="0dp"
            android:layout_height="0dp"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/cl_name_info"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginLeft="30dp"
            android:layout_marginTop="50dp"
            android:layout_marginRight="15dp"
            android:alpha="0"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@id/ll_job_info"
            android:layout_width="match_parent"
            android:layout_height="117dp"
            android:layout_marginLeft="@dimen/d_15dp"
            android:layout_marginTop="10dp"
            android:layout_marginRight="@dimen/d_15dp"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/status_view" />
        <Constraint
            android:id="@id/scrollView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/ll_job_info" />
    </ConstraintSet>
</MotionScene>

效果:

总结

类似这样的协调滚动布局,当底部列表滑动的时候,顶部的布局做响应的动作,我们都可以通过 AppBarLayout 和 MotionLayout 来实现。区别只是AppBarLayout实现起来更简单,MotionLayout 的定义可以更细。

需要注意的是 AppBarLayout 定义的方式 可以定义一些相对复杂的页面,如果非常复杂的元素使用 MotionLayout 来作为跟视图,全部的布局一股脑的写在 MotionLayout 中,那么可能导致性能问题的,最直观的感受是启动这个Activity都会很慢。

其实在高刷屏流行的今天,留给我们布局上屏的处理时间越来越少了,如果是特别复杂或是嵌套较深的布局,一定要慎重使用。常见的优化方式是异步加载布局、先展示占位图、优化 MotionLayout 布局,只包裹需要改变的视图。

到此这篇关于Android中协调滚动常用的布局实现代码的文章就介绍到这了,更多相关Android协调滚动布局内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Android中协调滚动布局的实现代码的更多相关文章

  1. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  7. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  8. 在iOS上向后播放HTML5视频

    我试图在iPad上反向播放HTML5视频.HTML5元素包括一个名为playbackRate的属性,它允许以更快或更慢的速率或相反的方式播放视频.根据Apple’sdocumentation,iOS不支持此属性.通过每秒多次设置currentTime属性,可以反复播放,而无需使用playbackRate.这种方法适用于桌面Safari,但似乎在iOS设备上的搜索限制为每秒1次更新–在我的情况下太慢了.有没有办法在iOS设备上向后播放HTML5视频?解决方法iOS6Safari现在支持playbackRat

  9. 使用 Swift 语言编写 Android 应用入门

    Swift标准库可以编译安卓armv7的内核,这使得可以在安卓移动设备上执行Swift语句代码。做梦,虽然Swift编译器可以胜任在安卓设备上编译Swift代码并运行。这需要的不仅仅是用Swift标准库编写一个APP,更多的是你需要一些框架来搭建你的应用用户界面,以上这些Swift标准库不能提供。简单来说,构建在安卓设备上使用的Swiftstdlib需要libiconv和libicu。通过命令行执行以下命令:gitclonegit@github.com:SwiftAndroid/libiconv-libi

  10. Android – 调用GONE然后VISIBLE使视图显示在错误的位置

    我有两个视图,A和B,视图A在视图B上方.当我以编程方式将视图A设置为GONE时,它将消失,并且它正下方的视图将转到视图A的位置.但是,当我再次将相同的视图设置为VISIBLE时,它会在视图B上显示.我不希望这样.我希望视图B回到原来的位置,这是我认为会发生的事情.我怎样才能做到这一点?编辑–代码}这里是XML:解决方法您可以尝试将两个视图放在RelativeLayout中并相对于彼此设置它们的位置.

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部