UI出了一个新需求,仿京东头部滚动,头像需要动态变化,先来看下京东的是什么效果
我们知道什么效果以后,接下来就想想怎么实现吧,Android常规吸顶折叠布局是由CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout组成的,那么头部固定的布局从外面写一个固定的就行了,通过透明度来控制渐隐渐现,随之滑动放大缩小并且移动的头像需要单独一个图片控件来控制,并且在滑动过程中需要实时的控制头像所处的位置,思路理清楚以后,实现起来就比较简单了
1、先把UI结构画出来
java
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 主布局 -->
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="80dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="@+id/toolbar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layoutUserInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="40dp"
android:paddingBottom="16dp"
app:layout_constraintTop_toTopOf="parent">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imgUserHead"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:src="@mipmap/icon_login_default_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:riv_oval="true" />
<TextView
android:id="@+id/tvHi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="Hi,我是京东PLUS会员"
android:textColor="#333333"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/tvUserPhone"
app:layout_constraintStart_toEndOf="@+id/imgUserHead"
app:layout_constraintTop_toTopOf="@+id/imgUserHead"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tvUserPhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="JD.001"
android:textColor="#666666"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@+id/imgUserHead"
app:layout_constraintStart_toEndOf="@+id/imgUserHead"
app:layout_constraintTop_toBottomOf="@+id/tvHi"
tools:ignore="HardcodedText,SmallSp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:scaleType="fitXY"
android:src="@mipmap/icon_banner"
app:layout_constraintTop_toTopOf="parent"
app:riv_corner_radius="10dp"
app:riv_oval="false" />
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="10dp"
android:background="@drawable/bg_bottom_view"
android:elevation="10dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="标题1"
android:textColor="#FFFFFF"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="标题2"
android:textColor="#FFFFFF"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="标题3"
android:textColor="#FFFFFF"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="标题4"
android:textColor="#FFFFFF"
android:textSize="16sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:text="我是PLUS会员!!!"
android:textColor="#FF0000"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText,RtlSymmetry" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<!-- 滑动到顶部以后出现的吸顶头布局 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layoutUserInfoTop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0"
android:background="#FF0000"
android:paddingTop="42dp"
android:paddingBottom="12dp"
tools:alpha="1">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imgUserHeadTop"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="16dp"
android:src="@mipmap/icon_login_default_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:riv_oval="true" />
<TextView
android:id="@+id/tvHiTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="Hi,我是京东PLUS会员"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/tvUserPhoneTop"
app:layout_constraintStart_toEndOf="@+id/imgUserHeadTop"
app:layout_constraintTop_toTopOf="@+id/imgUserHeadTop"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tvUserPhoneTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="JD.001"
android:textColor="#FFFFFF"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@+id/imgUserHeadTop"
app:layout_constraintStart_toEndOf="@+id/imgUserHeadTop"
app:layout_constraintTop_toBottomOf="@+id/tvHiTop"
tools:ignore="HardcodedText,SmallSp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 滑动过程中的头像 -->
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imgSlide"
android:layout_width="60dp"
android:layout_height="60dp"
android:visibility="invisible"
app:riv_oval="true" />
</FrameLayout>
2、主要代码处理
java
private final HomeAppBarStateChangeListener mAppBarStateChangeListener = new HomeAppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, State state, int slidingDistance) {
switch (state) {
case EXPANDED: //展开
setTitleBackground(1);
mainBinding.imgUserHeadTop.setVisibility(View.INVISIBLE);
mainBinding.imgSlide.setVisibility(View.INVISIBLE);
mainBinding.imgUserHead.setVisibility(View.VISIBLE);
mainBinding.layoutUserInfoTop.setAlpha(0f);
break;
case IDLE: //滚动
mainBinding.imgUserHead.setVisibility(View.INVISIBLE);
break;
case COLLAPSED: //置顶
setTitleBackground(0);
mainBinding.imgUserHeadTop.setVisibility(View.VISIBLE);
mainBinding.imgUserHead.setVisibility(View.INVISIBLE);
mainBinding.imgSlide.setVisibility(View.INVISIBLE);
mainBinding.layoutUserInfoTop.setAlpha(1f);
break;
}
mainBinding.refreshLayout.requestLayout();
}
@Override
public void onStateSliding(AppBarLayout appBarLayout, State state, int slideHeight) {
int slidingHeight = Math.abs(slideHeight);
if (slidingHeight <= top30 && slidingHeight >= 0) {
if (mainBinding.imgSlide.getVisibility() != View.VISIBLE) {
mainBinding.imgSlide.setVisibility(View.VISIBLE);
}
if (mainBinding.imgUserHeadTop.getVisibility() != View.INVISIBLE) {
mainBinding.imgUserHeadTop.setVisibility(View.INVISIBLE);
}
mainBinding.imgSlide.setY(maxTop - slidingHeight);
if (slidingHeight <= top30) {
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mainBinding.imgSlide.getLayoutParams();
layoutParams.width = top60 - slidingHeight;
layoutParams.height = top60 - slidingHeight;
mainBinding.imgSlide.requestLayout();
}
Glide.with(MainActivity.this)
.load(R.mipmap.icon_login_default_header)
.into(mainBinding.imgSlide);
} else {
if (mainBinding.imgUserHeadTop.getVisibility() != View.VISIBLE) {
mainBinding.imgUserHeadTop.setVisibility(View.VISIBLE);
}
if (mainBinding.imgSlide.getVisibility() != View.INVISIBLE) {
mainBinding.imgSlide.setVisibility(View.INVISIBLE);
}
}
if (slidingHeight < 100) {
float alpha = slidingHeight * 1.0f / 100f;
if (alpha < 0.3) {
setTitleBackground(1);
} else {
setTitleBackground(0);
}
mainBinding.layoutUserInfoTop.setAlpha(alpha);
} else {
setTitleBackground(0);
mainBinding.layoutUserInfoTop.setAlpha(1f);
}
}
};
最后来看下Android上实现的效果吧
Java代码只是一部门,源代码请看传送门
如果能帮到你的话,可以请作者喝一杯咖啡,谢谢!!!