2017-04-19 106 views
2

我希望爲自己的框架佈局設置自定義形狀(矩形每個角的不同半徑),以便框架佈局中的視圖將剪裁到形狀的邊界。創建自定義凸形路徑Android

ViewOutlineProvider provider = new ViewOutlineProvider() { 
     @Override 
     public void getOutline(View view, Outline outline) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       configurePath(getWidth(), getHeight()); 
       outline.setConvexPath(borderPath); 
      } 
     } 
    }; 

    setOutlineProvider(provider); 
    setClipToOutline(true); 

而且configurePath()看起來是這樣的:

private void configurePath (int width, int height) { 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 
     return; 
    } 

    borderPath.rewind(); 

    float minSize = Math.min(width, height); 
    float maxRadiusWidth = 2 * Math.max(Math.max(topLeftRadius, topRightRadius), 
      Math.max(bottomLeftRadius, bottomRightRadius)); 

    if (minSize < maxRadiusWidth) { 
     borderPath.addRect(0, 0, width, height, Path.Direction.CCW); 
     return; 
    } 

    // Top left circle 
    oval.set(0, 0, 2 * topLeftRadius, 2 * topLeftRadius); 
    borderPath.moveTo(0, topLeftRadius); 
    borderPath.arcTo(oval, 180, -90); 

    borderPath.rLineTo(width - topLeftRadius - topRightRadius, 0); 

    // Top right circle 
    oval.set(width - 2 * topRightRadius, 0, width, 2 * topRightRadius); 
    borderPath.arcTo(oval, 90, -90); 

    borderPath.rLineTo(0, height - topRightRadius - bottomRightRadius); 

    // Bottom right circle 
    oval.set(width - 2 * bottomRightRadius, height - 2 * bottomRightRadius, width, height); 
    borderPath.arcTo(oval, 0, -90); 

    borderPath.rLineTo(-width + bottomRightRadius + bottomLeftRadius, 0); 

    // Bottom left circle 
    oval.set(0, height - 2 * bottomLeftRadius, 2 * bottomLeftRadius, height); 
    borderPath.arcTo(oval, -90, -90); 

    borderPath.rLineTo(0, -height + bottomLeftRadius + topLeftRadius); 
} 

當我運行它,我得到了java.lang.IllegalArgumentException: path must be convex,我不能進入native_isConvex(),看看它是如何決定如果路徑是凸的。

那麼什麼是凸路徑?爲什麼congfigurePath()的路徑不是凸的? 如何創建自定義凸形路徑?謝謝。

+0

面對同樣的問題。現在,我知道當我只使用'lineTo'方法時,'isConvex'可以返回'true'。使用'quadTo'或'arcTo'會導致'isConvex'返回'false'。也許這可能是一些小費... – pxsx

+0

@pxsxYeah,'arcTo'是我認爲會導致問題。但是我必須使用它,因爲我打算爲視圖組創建自定義形狀。無論如何,我用clipPath解決了自定義形狀問題。 –

回答

1

我自己想通了。路徑不是凸的,因爲我沒有正確繪製路徑。這實現了多個圓角半徑的影響,我想正確的路徑應該是:

// Top left circle 
    oval.set(0, 0, 2 * topLeftRadius, 2 * topLeftRadius); 
    borderPath.moveTo(0, topLeftRadius); 
    borderPath.arcTo(oval, -180, 90); 

    borderPath.rLineTo(width - topLeftRadius - topRightRadius, 0); 

    // Top right circle 
    oval.set(width - 2 * topRightRadius, 0, width, 2 * topRightRadius); 
    borderPath.arcTo(oval, -90, 90); 

    borderPath.rLineTo(0, height - topRightRadius - bottomRightRadius); 

    // Bottom right circle 
    oval.set(width - 2 * bottomRightRadius, height - 2 * bottomRightRadius, width, height); 
    borderPath.arcTo(oval, 0, 90); 

    borderPath.rLineTo(-width + bottomRightRadius + bottomLeftRadius, 0); 

    // Bottom left circle 
    oval.set(0, height - 2 * bottomLeftRadius, 2 * bottomLeftRadius, height); 
    borderPath.arcTo(oval, 90, 90); 

    borderPath.rLineTo(0, -height + bottomLeftRadius + topLeftRadius); 

更新:雖然道路現在是正確的,但還不是凸的路徑,似乎是自定義的路徑將不會被視爲凸路徑。

0

不錯,你得到它的工作,但有內置的工具。
最簡單的就是以可抽拉的xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
    <corners 
     android:bottomLeftRadius="8dp" 
     android:topLeftRadius="8dp" 
     android:topRightRadius="8dp" 
     android:bottomRightRadius="0dp" /> 

    <solid android:color="#fff" /> 

</shape> 

通過編程可以使用RoundRectShape類。這也是從上面的XML充氣。
在操縱桿中,您可以傳遞外角半徑,線寬和內角半徑。您還可以查看源代碼以瞭解它們如何創建路徑(提示:path.addRoundRect())。

+1

謝謝你讓我知道'addRoundRect(RectF rect,float [] radii,Direction dir)'。但根據'Outline'的源代碼:'public boolean canClip(){ return mMode!= MODE_CONVEX_PATH; }'大綱不支持剪裁自定義形狀 –