Android中如何使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能
发表于:2025-11-20 作者:千家信息网编辑
千家信息网最后更新 2025年11月20日,这篇文章主要介绍了Android中如何使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获
千家信息网最后更新 2025年11月20日Android中如何使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能
这篇文章主要介绍了Android中如何使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
直接上布局文件代码
上java代码
package com.ce.myscrollimg;import androidx.appcompat.app.AppCompatActivity;import androidx.fragment.app.Fragment;import androidx.viewpager.widget.ViewPager;import android.graphics.Typeface;import android.os.Bundle;import android.util.TypedValue;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;import com.google.android.material.tabs.TabLayout;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity { private TabLayout toolbar_tab; private NoScrollViewPager vp_content; private ViewPagerAdapter vpAdapter; private List listFragment = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } //初始化view private void initView(){ //tab toolbar_tab = findViewById(R.id.toolbar_tab); // vp_content = findViewById(R.id.vp_content); vpAdapter = new ViewPagerAdapter(getSupportFragmentManager(),listFragment); vp_content.setAdapter(vpAdapter); vp_content.setOffscreenPageLimit(2); toolbar_tab.setupWithViewPager(vp_content); for(int i=0;i<12;i++){ listFragment.add(CeshiFragment.newInstance("第"+i+"页")); } vpAdapter.notifyDataSetChanged(); for(int i=0;i重点在于设置AppBarLayout的Behavior这里自定义AppBarLayoutOverScrollViewBehavior,下面贴出代码
package com.ce.myscrollimg;import android.animation.Animator;import android.animation.ValueAnimator;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import androidx.appcompat.widget.Toolbar;import androidx.coordinatorlayout.widget.CoordinatorLayout;import androidx.core.view.ViewCompat;import com.google.android.material.appbar.AppBarLayout;/** * Created by gjm on 2017/5/24. * 目前包括的事件: * 图片放大回弹 * 个人信息布局的top和botoom跟随图片位移 * toolbar背景变色 */public class AppBarLayoutOverScrollViewBehavior extends AppBarLayout.Behavior { private static final String TAG = "overScroll"; private static final String TAG_TOOLBAR = "toolbar"; private static final String TAG_MIDDLE = "middle"; private static final float TARGET_HEIGHT = 1500; private View mTargetView; private int mParentHeight; private int mTargetViewHeight; private float mTotalDy; private float mLastScale; private int mLastBottom; private boolean isAnimate; private Toolbar mToolBar; private ViewGroup middleLayout;//个人信息布局 private int mMiddleHeight; private boolean isRecovering = false;//是否正在自动回弹中 private final float MAX_REFRESH_LIMIT = 0.3f;//达到这个下拉临界值就开始刷新动画 public AppBarLayoutOverScrollViewBehavior() { } public AppBarLayoutOverScrollViewBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onLayoutChild(CoordinatorLayout parent, AppBarLayout abl, int layoutDirection) { boolean handled = super.onLayoutChild(parent, abl, layoutDirection); if (mToolBar == null) { mToolBar = parent.findViewWithTag(TAG_TOOLBAR); } if (middleLayout == null) { middleLayout = (ViewGroup) parent.findViewWithTag(TAG_MIDDLE); } // 需要在调用过super.onLayoutChild()方法之后获取 if (mTargetView == null) { mTargetView = parent.findViewById(R.id.iv_bg); if (mTargetView != null) { initial(abl); } } abl.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public final void onOffsetChanged(AppBarLayout appBarLayout, int i) { mToolBar.setAlpha(Float.valueOf(Math.abs(i)) / Float.valueOf(appBarLayout.getTotalScrollRange())); } }); return handled; } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int x) { isAnimate = true; if (target instanceof DisInterceptNestedScrollView) return true;//这个布局就是middleLayout return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes,x); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int x) { if (!isRecovering) { if (mTargetView != null && ((dy < 0 && child.getBottom() >= mParentHeight) || (dy > 0 && child.getBottom() > mParentHeight))) { scale(child, target, dy); return; } } super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed,x); } @Override public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY) { if (velocityY > 100) {//当y速度>100,就秒弹回 isAnimate = false; } return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY); } @Override public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl, View target, int x) { recovery(abl); super.onStopNestedScroll(coordinatorLayout, abl, target,x); } private void initial(AppBarLayout abl) { abl.setClipChildren(false); mParentHeight = abl.getHeight(); mTargetViewHeight = mTargetView.getHeight(); mMiddleHeight = middleLayout.getHeight(); } private void scale(AppBarLayout abl, View target, int dy) { mTotalDy += -dy; mTotalDy = Math.min(mTotalDy, TARGET_HEIGHT); mLastScale = Math.max(1f, 1f + mTotalDy / TARGET_HEIGHT); ViewCompat.setScaleX(mTargetView, mLastScale); ViewCompat.setScaleY(mTargetView, mLastScale); mLastBottom = mParentHeight + (int) (mTargetViewHeight / 2 * (mLastScale - 1)); abl.setBottom(mLastBottom); target.setScrollY(0); middleLayout.setTop(mLastBottom - mMiddleHeight); middleLayout.setBottom(mLastBottom); if (onProgressChangeListener != null) { float progress = Math.min((mLastScale - 1) / MAX_REFRESH_LIMIT, 1);//计算0~1的进度 onProgressChangeListener.onProgressChange(progress, false); } } public interface onProgressChangeListener { /** * 范围 0~1 * * @param progress * @param isRelease 是否是释放状态 */ void onProgressChange(float progress, boolean isRelease); } public void setOnProgressChangeListener(AppBarLayoutOverScrollViewBehavior.onProgressChangeListener onProgressChangeListener) { this.onProgressChangeListener = onProgressChangeListener; } onProgressChangeListener onProgressChangeListener; private void recovery(final AppBarLayout abl) { if (isRecovering) return; if (mTotalDy > 0) { isRecovering = true; mTotalDy = 0; if (isAnimate) { ValueAnimator anim = ValueAnimator.ofFloat(mLastScale, 1f).setDuration(200); anim.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); ViewCompat.setScaleX(mTargetView, value); ViewCompat.setScaleY(mTargetView, value); abl.setBottom((int) (mLastBottom - (mLastBottom - mParentHeight) * animation.getAnimatedFraction())); middleLayout.setTop((int) (mLastBottom - (mLastBottom - mParentHeight) * animation.getAnimatedFraction() - mMiddleHeight)); if (onProgressChangeListener != null) { float progress = Math.min((value - 1) / MAX_REFRESH_LIMIT, 1);//计算0~1的进度 onProgressChangeListener.onProgressChange(progress, true); } } } ); anim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { isRecovering = false; } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); anim.start(); } else { ViewCompat.setScaleX(mTargetView, 1f); ViewCompat.setScaleY(mTargetView, 1f); abl.setBottom(mParentHeight); middleLayout.setTop(mParentHeight - mMiddleHeight);// middleLayout.setBottom(mParentHeight); isRecovering = false; if (onProgressChangeListener != null) onProgressChangeListener.onProgressChange(0, true); } } }}感谢你能够认真阅读完这篇文章,希望小编分享的"Android中如何使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!
图片
布局
篇文章
代码
功能
顶部
个人
信息
进度
临界值
事件
价值
兴趣
动画
同时
就是
文件
方法
更多
朋友
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
梦幻3年内最火服务器
物资管理的数据库
网络安全文明上网论文
软件开发业务信息资产识别
关于网络安全判断题
网络安全威胁的案列
服务器能安装360安全卫士
预算软件开发程序
csgo按哪个键搜索服务器
数据库中的正则表达式
无线网络安全绪论
网络安全响应基础
湖南外贸进口软件服务器
数据库70%还原了能恢复吗
记录数据库变动
软件开发中配置管理
网络安全课堂在线
好用的媒体服务器
v2ray管理多个服务器
服务器网口配置指向路由
网络安全2020年投资
有关网络安全基线
数据库的ip地址是指什么
心动外卖服务器故障
大学的软件开发是什么
申请服务器证书
网络安全教育会议的内容
电脑上连接网络安全密钥是什么
大数据库如何运用
学软件开发需要什么学历吗