Android中实现平行四边形ImageView:解决skew/matrix顶部截断问题
实现无内容截断的平行四边形ImageView
你遇到的内容截断问题,本质是直接用skew/matrix变换时,控件的实际布局边界没跟着调整,导致超出部分被裁剪了。下面给你两种靠谱的解决方法:
方法一:用Drawable遮罩实现(无需自定义View)
这种方法通过叠加平行四边形遮罩,同时调整padding来适配倾斜,不会截断内容。
- 创建平行四边形遮罩的shape文件(
res/drawable/parallelogram_mask.xml):
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@android:color/white" /> <transform> <skew android:skewX="-15" /> <!-- 调整倾斜角度,负数左斜、正数右斜 --> </transform> <padding android:left="25dp" android:right="0dp" /> <!-- 适配倾斜的内边距,按需调整 --> </shape>
- 创建LayerDrawable组合原图和遮罩(
res/drawable/image_parallelogram.xml):
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/your_target_image" /> <!-- 替换成你的图片 --> <item android:drawable="@drawable/parallelogram_mask" /> </layer-list>
- 在布局中使用ImageView:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/image_parallelogram" android:paddingLeft="25dp" android:scaleType="centerCrop" />
方法二:自定义ImageView(灵活度更高)
通过重写测量和绘制方法,主动调整控件边界和画布,从根源避免截断。
自定义View代码:
public class ParallelogramImageView extends AppCompatImageView { private static final float SKEW_ANGLE = -15f; // 倾斜角度,按需修改 private final float skewRadian = Math.abs(SKEW_ANGLE) * Math.PI / 180; public ParallelogramImageView(Context context) { super(context); init(); } public ParallelogramImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setLayerType(LAYER_TYPE_SOFTWARE, null); // 关闭硬件加速避免画布变换异常 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 补偿倾斜带来的宽度增量,确保内容能完整显示 float extraWidth = getMeasuredHeight() * (float) Math.tan(skewRadian); setMeasuredDimension((int) (getMeasuredWidth() + extraWidth), getMeasuredHeight()); } @Override protected void onDraw(Canvas canvas) { canvas.save(); // 计算偏移量,让内容在平行四边形内居中 float offset = getHeight() * (float) Math.tan(skewRadian); // 执行倾斜变换 canvas.skew(SKEW_ANGLE / 180 * Math.PI, 0); // 裁剪画布到平行四边形区域,避免内容溢出 canvas.clipRect(offset, 0, getWidth(), getHeight()); // 绘制原图 super.onDraw(canvas); canvas.restore(); } }
布局中使用:
<com.yourpackage.ParallelogramImageView android:layout_width="220dp" android:layout_height="160dp" android:src="@drawable/your_target_image" android:scaleType="centerCrop" />
两种方法都能解决截断问题,方法一适合快速实现,方法二更适合需要动态调整倾斜角度的场景。
内容的提问来源于stack exchange,提问作者WhizKidz
相关产品推荐
相关产品推荐

