[关闭]
@act262 2017-06-29T12:31:53.000000Z 字数 2227 阅读 2388

自定义Shape半圆角效果的问题

Android_Drawable


需求:半圆矩形效果,不用贴图的方式

将shape的radius设置大于控件的大小后就会产生半圆形的矩形效果

分别给4个设置角度,相同圆角,理论上效果应该要和下面的方式一样的

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android">
  3. <solid android:color="#f00" />
  4. <corners
  5. android:bottomLeftRadius="100dp"
  6. android:bottomRightRadius="100dp"
  7. android:topLeftRadius="100dp"
  8. android:topRightRadius="100dp" />
  9. </shape>

只设置一个角度,代表4个相同的圆角

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android">
  3. <solid android:color="#f00" />
  4. <corners android:radius="100dp" />
  5. </shape>

将上面2个shape文件设置到相同的View上,查看运行效果图
在4.3以上的效果
image.png-26.5kB
在4.3以下的效果
image2.png-28.8kB

可以看到使用单独设置一个radius的方式在不同版本都是我们想要的半圆形效果,但是分别设置圆角的在4.3版本以下的设备显示却不是我们要的效果。

如果想要某个边上半圆角效果,但是在低版本上还是有问题的,表现出的不是半圆而是半椭圆。

  1. <shape xmlns:android="http://schemas.android.com/apk/res/android">
  2. <solid android:color="#f00" />
  3. <corners
  4. android:bottomLeftRadius="100dp"
  5. android:topLeftRadius="100dp" />
  6. </shape>

源码解析

GradientDrawabledraw方法

  1. public void draw(Canvas canvas) {
  2. // ...
  3. switch (st.mShape) {
  4. case RECTANGLE:
  5. // 单独分别设置圆角的情况下,不同版本这里实现有些不同,使用Path的方式处理
  6. if (st.mRadiusArray != null) {
  7. buildPathIfDirty();
  8. canvas.drawPath(mPath, mFillPaint);
  9. if (haveStroke) {
  10. canvas.drawPath(mPath, mStrokePaint);
  11. }
  12. } else if (st.mRadius > 0.0f) { // 只设置radius的情况下,直接画圆角矩形
  13. // since the caller is only giving us 1 value, we will force
  14. // it to be square if the rect is too small in one dimension
  15. // to show it. If we did nothing, Skia would clamp the rad
  16. // independently along each axis, giving us a thin ellipse
  17. // if the rect were very wide but not very tall
  18. // 取矩形宽高的一半或者圆角最小的一个作为半径画圆角矩形
  19. float rad = Math.min(st.mRadius,
  20. Math.min(mRect.width(), mRect.height()) * 0.5f);
  21. canvas.drawRoundRect(mRect, rad, rad, mFillPaint);
  22. if (haveStroke) {
  23. canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
  24. }
  25. } else { // 纯矩形
  26. if (mFillPaint.getColor() != 0 || colorFilter != null ||
  27. mFillPaint.getShader() != null) {
  28. canvas.drawRect(mRect, mFillPaint);
  29. }
  30. if (haveStroke) {
  31. canvas.drawRect(mRect, mStrokePaint);
  32. }
  33. }
  34. break;
  35. }

解决方案

  1. 对于需要2边都是半圆效果的,用单独设置相同的radius的方式,而不用分别设置的方式来避免。
  2. 对于想要1边半圆角效果来说,需要自定义View来绘制一边的半圆效果
  1. @Override
  2. protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  3. super.onLayout(changed, left, top, right, bottom);
  4. rectF.set(0, 0, getWidth(), getHeight());
  5. int radius = getHeight() / 2;
  6. // { 0, 0, r, r, r, r, 0, 0}
  7. radii[2] = radii[3] = radii[4] = radii[5] = radius;
  8. path.addRoundRect(rectF, radii, Path.Direction.CW);
  9. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注