需求:TextView 邊框僅顯示左、上、底三邊,**右邊框隱藏**。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_three_sides"
android:translationX="2dp" /> <!-- 向右平移 2dp,右邊框移出可視區 -->
bg_three_sides.xml (正常四邊框):
<shape xmlns:android="...">
<stroke android:width="2dp" android:color="#2F6699"/>
<solid android:color="#FFFFFF"/>
<corners android:radius="0dp"/>
<padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp"/>
</shape>
原理:整體右移 2dp,右邊框超出父容器或被遮擋。缺點:佈局佔用寬度增加、可能遮蓋鄰近 View。
bg_three_sides_exact.xml
<layer-list xmlns:android="...">
<!-- 底層:完整四邊框 -->
<item>
<shape>
<stroke android:width="2dp" android:color="#2F6699"/>
<solid android:color="#FFFFFF"/>
</shape>
</item>
<!-- 頂層:白色矩形遮蓋右邊框 -->
<item android:right="-2dp"> <!-- 負值向右擴展 2dp 覆蓋右邊框 -->
<shape>
<solid android:color="#FFFFFF"/>
</shape>
</item>
</layer-list>
原理:`android:right="-2dp"` 使白色矩形向右超出 2dp,精確遮蓋右邊框,**不影響佈局測量**。
public class ThreeSideBorderTextView extends AppCompatTextView {
private Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
{ borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(dp(2)); borderPaint.setColor(0xFF2F6699); }
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float w = getWidth(), h = getHeight();
canvas.drawLine(0, 0, 0, h, borderPaint); // 左
canvas.drawLine(0, 0, w, 0, borderPaint); // 上
canvas.drawLine(0, h, w, h, borderPaint); // 底
// 右邊不畫
}
}
| 方案 | 優點 | 缺點 |
|---|---|---|
| 負 margin | 代碼極少 | 影響佈局、可能遮蓋 |
| Layer-list | 精確、無副作用、純 XML | 需理解負 inset |
| 自定義 View | 完全可控、支持動態顏色/寬度 | 代碼量大 |
推薦 **Layer-list 方案**:純 XML、零運行時開銷、完美精確。