Android 仿京东头部滚动头像动态变化

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代码只是一部门,源代码请看传送门

如果能帮到你的话,可以请作者喝一杯咖啡,谢谢!!!

相关推荐
松仔log10 小时前
Java中级——组合和继承
android·java·开发语言
我命由我1234513 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian23314 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_9557596214 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马14 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone14 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone14 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子18 小时前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker18 小时前
Boolean 变量到底该怎么命名?
android·kotlin
AFinalStone18 小时前
Android 7系统异常问题排查(六)应用异常(上)—ANR机制全解
android·系统异常