Android中如何使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能
发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,这篇文章主要介绍了Android中如何使用CoordinatorLayout+AppBarLayout实现拉伸顶部图片功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获
千家信息网最后更新 2025年02月04日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 ListlistFragment = 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安全错误
数据库的锁怎样保障安全
网络安全改编歌曲
现在魔兽哪个服务器人多
湖北学习软件开发费用
一台服务器有多少tcp
网络安全宣传周 市青少年
境外3安全验证服务器
汇丰软件开发 面试
宽城县税务局加强网络安全建设
华为网络技术ospf
dbc 怪物数据库
应用软件开发多少钱
让网络安全宣传活起来
电脑我的世界服务器必备指令
帝国神话服务器怎么打开控制面板
人脸识别系统的软件开发
李强 网络安全审查
警察网络安全保卫工作
天速互联网络科技有限公司
数据库索引的用处
海淀区特色软件开发差异
数据库中add表达什么
数据库批量挂接图片
迅雷网络技术有限公司旗下软件
数据库链接权限不够
服务器保障速度和数据安全
苹果服务器可能出现问题
佳为软件开发有限公司
网吧电脑都是连接服务器吗
天速互联网络科技有限公司
开机有个sql数据库运行