软件编程
位置:首页>> 软件编程>> Android编程>> Android中协调滚动布局的实现代码

Android中协调滚动布局的实现代码

作者:newki  发布时间:2023-11-07 20:37:05 

标签:Android,滚动,布局

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

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

这里先上效果图

Android中协调滚动布局的实现代码

Android中协调滚动布局的实现代码

可能大家都比较会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则吸顶。

效果如下:

Android中协调滚动布局的实现代码

二、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>

效果如下:

Android中协调滚动布局的实现代码

三、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>

效果:

Android中协调滚动布局的实现代码

同样的效果我们可以用 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>

效果:

Android中协调滚动布局的实现代码

总结

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

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

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

来源:https://juejin.cn/post/7109661676584042533

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com