Android九补丁 - 只允许背景的特定区域绘制拉伸

时间:2015-08-18 13:10:26

标签: android android-view android-custom-view android-drawable

如何创建具有三角形穿孔边界的View

this

到目前为止,我一直在使用背景绘图来实现这一目标。当View的尺寸固定时,这种方法有效。现在我的情况是View高度不是常数,所以我需要动态调整高度变量。我不能再使用固定高度的背景画了。

这是原始背景drawable:

enter image description here

这就是最终的View需要看起来的样子:

enter image description here

另一种看待同一问题的方法是,我们可以让图像的中心在不扭曲边界的情况下伸展吗?如果我们可以这样做,我们可以使用现有的drawable作为背景。

如何实现这一目标?以前有其他人遇到过这个问题吗?框架是否有处理这类问题的现有方法?

4 个答案:

答案 0 :(得分:2)

您可以使用 NinePatch图像作为该视图的可绘制对象。要了解如何创建NinePatch图像,请转到Draw 9-patch

答案 1 :(得分:1)

您可以生成9补丁程序,而不是使用普通图像。

请使用Simple Nine-patch Generator

技巧是左侧的黑线。这告诉Android,png可以沿着这个区域垂直扩展。

请看这个例子:

Nine Patch Example

将其保存为九个补丁,格式为imagename.9.png

答案 2 :(得分:0)

您可以在视图的背景中绘制Z字形路径

Rect rectZigzag = new Rect();
private Path pathZigzag = new Path();
private Paint paintZigzag;
private void init(){
    this.paintZigzag = new Paint();
    this.paintZigzag.setColor(zigzagBackgroundColor);
    this.paintZigzag.setStyle(Style.FILL);
}


private void drawZigzag() {
    float left = rectZigzag.left;
    float right = rectZigzag.right;
    float top = rectZigzag.top;
    float bottom = rectZigzag.bottom;
    int width = (int) (right - left);

    pathZigzag.moveTo(right, bottom);
    pathZigzag.lineTo(right, top);
    pathZigzag.lineTo(left, top);
    pathZigzag.lineTo(left, bottom);

    int h = zigzagHeight;
    int seed = 2 * h;
    int count = width / seed;
    int diff = width - (seed * count);
    int sideDiff = diff / 2;


    float x = (float) (seed / 2);
    float upHeight = bottom - h;
    float downHeight = bottom;

    for (int i = 0; i < count; i++) {
        int startSeed = (i * seed) + sideDiff + (int) left;
        int endSeed = startSeed + seed;

        if (i == 0) {
            startSeed = (int) left + sideDiff;
        } else if (i == count - 1) {
            endSeed = endSeed + sideDiff;
        }

        this.pathZigzag.lineTo(startSeed + x, upHeight);
        this.pathZigzag.lineTo(endSeed, downHeight);
    }
}

refrence

答案 3 :(得分:0)

对于我的用例,9补丁机制无法起到类似作用,因为它需要在水平和垂直方向上定义可拉伸区域。只有将ImageView约束到源可绘制对象的确切宽度,以避免任何水平拉伸,才能使用9补丁。

如果需要允许视图水平伸展,并保持图像的顶部和底部边界部分的纵横比,而允许中间部分在两个方向上自由伸展,则9个色块将不适用于这个。我创建了此布局来完成此任务:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/backgroundImage"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageTop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:adjustViewBounds="true"
        android:layout_weight="0"
        android:src="@drawable/image_top" />

    <ImageView
        android:id="@+id/imageMiddle"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        android:layout_weight="1"
        android:background="@drawable/image_middle" />

    <ImageView
        android:id="@+id/imageBottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:adjustViewBounds="true"
        android:layout_weight="0"
        android:src="@drawable/image_bottom" />

</LinearLayout>

image_top.png enter image description here

image_middle.png enter image description here (请注意,如果不需要右侧的细微灰色渐变,则该图像可能会缩小到1像素高。)

image_bottom.png enter image description here

键在边界图像上具有android:adjustViewBounds="true",而可绘制对象由android:src指定。然后,中间图像使用android:background指定可绘制对象,并调整大小以使用android:layout_height="match_parent"android:layout_weight="1"填充父版式的高度。

另外,还需要

android:scaleType="fitXY"以便在调整图像的视界以处理高分辨率显示器上对齐时可能出现的微小像素差异后强制对图像进行最终缩放。它们都被调整大小以完全填充其边界。