Android中移动View时无失真隐藏超出竖线部分的实现方法
Android实现View左移时无失真逐行隐藏左侧部分的方案
要实现View左移过程中隐藏超出指定竖线的部分、且无失真收缩宽度的效果,推荐以下两种可行方案:
方法一:自定义View重绘时裁剪Canvas
通过重写View的onDraw方法,动态计算裁剪区域,只绘制未超出竖线的部分:
自定义裁剪ImageView示例
public class ClippedImageView extends androidx.appcompat.widget.AppCompatImageView { @Override protected void onDraw(Canvas canvas) { // 计算裁剪左边界:取目标竖线(此处以屏幕左边缘x=0为例)与View当前左位置的最大值 int clipLeft = Math.max(0, getLeft() + (int) getTranslationX()); // 定义裁剪矩形:左边界为计算值,右边界为View当前右位置,上下边界保持原View范围 canvas.clipRect(clipLeft, getTop(), getRight() + (int) getTranslationX(), getBottom()); super.onDraw(canvas); } }
执行左移动画
用ValueAnimator控制translationX,触发View左移并实时更新裁剪区域:
ClippedImageView imageView = findViewById(R.id.clipped_image); // 动画从初始位置左移至完全隐藏(位移距离为View自身宽度) ValueAnimator animator = ValueAnimator.ofFloat(imageView.getTranslationX(), imageView.getTranslationX() - imageView.getWidth()); animator.setDuration(1500); animator.addUpdateListener(animation -> { float value = (float) animation.getAnimatedValue(); imageView.setTranslationX(value); imageView.invalidate(); // 触发重绘,更新裁剪范围 }); animator.start();
方法二:利用系统API设置ClipBounds
无需自定义View,直接通过setClipBounds动态修改View的可见区域:
动画实现代码
ImageView imageView = findViewById(R.id.normal_image); // 先设置View初始居中 imageView.post(() -> { int screenWidth = getResources().getDisplayMetrics().widthPixels; float initialTranslationX = (screenWidth - imageView.getWidth()) / 2f; imageView.setTranslationX(initialTranslationX); }); // 启动左移动画 ValueAnimator animator = ValueAnimator.ofFloat(imageView.getTranslationX(), imageView.getTranslationX() - imageView.getWidth()); animator.setDuration(1500); animator.addUpdateListener(animation -> { float translationX = (float) animation.getAnimatedValue(); imageView.setTranslationX(translationX); // 计算裁剪区域,以屏幕左边缘为竖线边界 int clipLeft = Math.max(0, imageView.getLeft() + (int) translationX); Rect clipRect = new Rect(clipLeft, imageView.getTop(), imageView.getRight() + (int) translationX, imageView.getBottom()); imageView.setClipBounds(clipRect); }); animator.start();
自定义裁剪竖线位置
如果不需要以屏幕左边缘为边界,只需将代码中Math.max(0, ...)的0替换为目标竖线的绝对x坐标即可。
内容的提问来源于stack exchange,提问作者Alexey Simchenko
相关产品推荐
相关产品推荐

