Android中協(xié)調(diào)滾動(dòng)布局的實(shí)現(xiàn)代碼
使用 AppbarLayout 和 MotionLayout 實(shí)現(xiàn)常用的布局效果
前文我們講了協(xié)調(diào)滾動(dòng)的一些定義方式,我們?cè)陂_發(fā)中常用的幾種效果都可用 AppbarLayout 或 MotionLayout 來實(shí)現(xiàn)。
這里先上效果圖


可能大家都比較會(huì)AppbarLayout這種實(shí)現(xiàn)方式,這里就直接上代碼和效果圖了。
一、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>很平常的效果了,也是用的比較多的效果,定義起來非常簡(jiǎn)單,在AppbarLayout下面包裹2個(gè)View,圖片View跟隨滾動(dòng),而TabBarLayout則吸頂。
效果如下:

二、AppbarLayout + RecyclerView
和上面一樣的效果,這里我們可以指定下拉的時(shí)候把隱藏的布局顯示出來,設(shè)置一個(gè)核心屬性
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 的位置與狀態(tài)。
頁面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>
<!-- 相冊(cè)布局 -->
<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="相冊(cè)"
android:textColor="@color/white"
android:textSize="@dimen/d_14sp" />
</LinearLayout>
<!-- 固定的狀態(tài)欄 用于定位 -->
<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="武漢斗魚網(wǎng)絡(luò)科技有限公司"
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元/小時(shí)"
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>定義場(chǎng)景xml : 控件多的話,定義的東西也會(huì)比較多
<?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 實(shí)現(xiàn)一些 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">
<!-- 狀態(tài)欄 -->
<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" />
<!-- 內(nèi)部的頭像+姓名等信息 -->
<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="我的簡(jiǎn)歷"
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>
<!-- 內(nèi)部的工作申請(qǐng)統(tǒng)計(jì)相關(guān) -->
<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>定義的場(chǎng)景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>效果:
總結(jié)
類似這樣的協(xié)調(diào)滾動(dòng)布局,當(dāng)?shù)撞苛斜砘瑒?dòng)的時(shí)候,頂部的布局做響應(yīng)的動(dòng)作,我們都可以通過 AppBarLayout 和 MotionLayout 來實(shí)現(xiàn)。區(qū)別只是AppBarLayout實(shí)現(xiàn)起來更簡(jiǎn)單,MotionLayout 的定義可以更細(xì)。
需要注意的是 AppBarLayout 定義的方式 可以定義一些相對(duì)復(fù)雜的頁面,如果非常復(fù)雜的元素使用 MotionLayout 來作為跟視圖,全部的布局一股腦的寫在 MotionLayout 中,那么可能導(dǎo)致性能問題的,最直觀的感受是啟動(dòng)這個(gè)Activity都會(huì)很慢。
其實(shí)在高刷屏流行的今天,留給我們布局上屏的處理時(shí)間越來越少了,如果是特別復(fù)雜或是嵌套較深的布局,一定要慎重使用。常見的優(yōu)化方式是異步加載布局、先展示占位圖、優(yōu)化 MotionLayout 布局,只包裹需要改變的視圖。
到此這篇關(guān)于Android中協(xié)調(diào)滾動(dòng)常用的布局實(shí)現(xiàn)代碼的文章就介紹到這了,更多相關(guān)Android協(xié)調(diào)滾動(dòng)布局內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
PagerSlidingTabStrip制作Android帶標(biāo)簽的多界面滑動(dòng)切換
這篇文章主要介紹了使用PagerSlidingTabStrip制作Android帶標(biāo)簽的多界面滑動(dòng)切換效果的方法,PagerSlidingTabStrip是GitHub上的一個(gè)開源項(xiàng)目,調(diào)用這個(gè)庫可以少寫不少代碼XD 需要的朋友可以參考下2016-04-04
Android調(diào)用系統(tǒng)圖片裁剪限定尺寸及7.0照相問題的解決方法
這篇文章主要介紹了Android調(diào)用系統(tǒng)圖片裁剪限定尺寸,及7.0照相問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Android中使用DownloadManager類來管理數(shù)據(jù)下載的教程
這篇文章主要介紹了Android中使用DownloadManager類來管理數(shù)據(jù)下載的教程,針對(duì)HTTP下文件的下載與保存地址指定等基礎(chǔ)操作作出了詳細(xì)講解,需要的朋友可以參考下2016-04-04
解決android studio 打開java文件 內(nèi)容全變了的問題
這篇文章主要介紹了解決android studio 打開java文件 內(nèi)容全變了的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android中TextView和ImageView實(shí)現(xiàn)傾斜效果
這篇文章主要為大家詳細(xì)介紹了Android中TextView和ImageView實(shí)現(xiàn)傾斜效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù))
這篇文章主要介紹了創(chuàng)建Android守護(hù)進(jìn)程實(shí)例(底層服務(wù)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android實(shí)現(xiàn)邊錄邊播應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)邊錄邊播應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Android MenuItem 自定義長(zhǎng)按事件的實(shí)現(xiàn)
這篇文章主要介紹了Android MenuItem 自定義長(zhǎng)按事件的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
Android中通過訪問本地相冊(cè)或者相機(jī)設(shè)置用戶頭像實(shí)例
本篇文章主要介紹了Android中通過訪問本地相冊(cè)或者相機(jī)設(shè)置用戶頭像,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01

