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

UI出了一个新需求,仿京东头部滚动,头像需要动态变化,先来看下京东的是什么效果

我们知道什么效果以后,接下来就想想怎么实现吧,Android常规吸顶折叠布局是由CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout组成的,那么头部固定的布局从外面写一个固定的就行了,通过透明度来控制渐隐渐现,随之滑动放大缩小并且移动的头像需要单独一个图片控件来控制,并且在滑动过程中需要实时的控制头像所处的位置,思路理清楚以后,实现起来就比较简单了

1、先把UI结构画出来

<?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、主要代码处理

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

如果能帮到你的话,可以请作者喝一杯咖啡,谢谢!!!
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落魄的Android开发

感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值