Android开发:基于滚动百分比实现View向上位移动画
解决CollapsingToolbarLayout中View随滚动向上移动的问题
我来帮你搞定这个移动动画的问题!你遇到的核心问题是mBookCoverThumb锚定在AppBarLayout上,AppBar本身滚动时会带着View移动,直接用translationY的话容易和AppBar的原生移动叠加,加上之前的数值计算逻辑不对,导致效果不符合预期。下面是具体的解决思路和代码修改方案:
核心思路
- 先确定你希望View在AppBar完全折叠时,额外向上移动的最大距离(比如50dp,可自行调整)
- 结合你已经算出的滚动百分比,实时计算当前应该移动的距离(注意:Android中Y轴向下为正,所以向上移动需要设置负数的translationY)
- 避开布局约束的影响:translationY属于视图的“绘制偏移”,不会改变布局位置,所以只要你的View没有被设置成不可移动的约束(比如固定在父容器底部),这个方法就有效
修改后的代码示例
首先在初始化时定义最大移动距离(转成像素值,适配不同屏幕):
// 定义最大向上移动距离,这里设为50dp,可根据需求调整 int maxUpwardTranslation = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics() );
然后修改你的OnOffsetChangedListener代码,加入移动逻辑:
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { float totalScrollRange = Math.abs(appBarLayout.getTotalScrollRange()); float offset = Math.abs(verticalOffset); float scrollOffsetPercentageReverse; float scrollOffsetPercentage; float percentage; if (offset > 0) { percentage = (offset / totalScrollRange) * 100; } else { percentage = 0; } int reverse = 100 - (int) percentage; // 原有透明度和缩放逻辑保留 if (reverse > 0) { scrollOffsetPercentageReverse = 255.0f * (reverse / 100.0f); scrollOffsetPercentage = 255 * (percentage / 100); mBookCoverThumb.setImageAlpha((int) scrollOffsetPercentageReverse); } float scalePercentage = reverse / 100.0f; mBookCoverThumb.setScaleX(scalePercentage); mBookCoverThumb.setScaleY(scalePercentage); // 新增:向上移动的逻辑 // 计算当前移动比例:reverse从100(展开)到0(折叠),对应移动距离从0到-maxUpwardTranslation float translationRatio = 1 - (reverse / 100.0f); float currentTranslationY = maxUpwardTranslation * translationRatio; // 向上移动,设置负数的translationY mBookCoverThumb.setTranslationY(-currentTranslationY); } });
为什么之前的方法效果不好?
- 你之前直接用
percentage作为translationY的值,percentage是0-100的百分比数值,对应到像素的话移动距离极小,几乎看不到效果 - 没有考虑Y轴的方向:Android视图的Y轴向下为正,向上移动需要设置负数的translationY
- AppBar本身滚动时会带着View移动,我们需要的是在这个基础上额外让View向上偏移,所以需要用负数来叠加这个偏移量
优化建议
- 你可以调整
maxUpwardTranslation的数值(比如30dp、60dp),找到最符合你预期的移动幅度 - 如果想要动画更平滑,可以考虑用
ViewPropertyAnimator或者ValueAnimator来过渡,但因为AppBar的滚动是连续触发onOffsetChanged的,直接设置translationY已经足够流畅
内容的提问来源于stack exchange,提问作者Dale Julian
相关产品推荐
相关产品推荐

