JcMinarro / RoundKornerLayouts

Round Korner Layouts is an Android library create to build a layout with the round corners
https://jcminarro.github.io/RoundKornerLayouts/
Apache License 2.0
202 stars 36 forks source link

Some questions #6

Open AndroidDeveloperLB opened 6 years ago

AndroidDeveloperLB commented 6 years ago
  1. Is it possible to have the same technique used here, for ConstraintLayout ? If so , how?
  2. Is it possible to set which corners will be round, and which won't (or have different values) ?
  3. How can I add stroke around the whole shape, of a given color and width?
JcMinarro commented 6 years ago

Hello @AndroidDeveloperLB

  1. Nop I have not implemented ContraintLayout yet
  2. For now, the radius is applied to all corners and is not possible to have different ones.
  3. It is an extra functionality that is not cover for now on the library
AndroidDeveloperLB commented 6 years ago

1.+3. Never mind. I got it. But not sure yet what to change further to make it easy to use:

attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundedCornersView">
        <attr name="corner_radius" format="dimension"/>
        <attr name="corner_stroke_width" format="dimension"/>
        <attr name="corner_stroke_color" format="color"/>
    </declare-styleable>

</resources>

RoundedConstraintLayout.kt

class RoundedConstraintLayout : ConstraintLayout {
    private lateinit var canvasRounder: CanvasRounder

    constructor(context: Context) : super(context) {
        init(context, null, 0)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(context, attrs, 0)
    }

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        init(context, attrs, defStyle)
    }

    private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) {
        val array = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornersView, 0, 0)
        val cornerRadius = array.getDimension(R.styleable.RoundedCornersView_corner_radius, 0f)
        val cornerStrokeColor = array.getColor(R.styleable.RoundedCornersView_corner_stroke_color, 0)
        val cornerStrokeWidth = array.getDimension(R.styleable.RoundedCornersView_corner_stroke_width, 0f)
        array.recycle()
        canvasRounder = CanvasRounder(cornerRadius,cornerStrokeColor,cornerStrokeWidth)
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            setLayerType(FrameLayout.LAYER_TYPE_SOFTWARE, null)
        }
    }

    override fun onSizeChanged(currentWidth: Int, currentHeight: Int, oldWidth: Int, oldheight: Int) {
        super.onSizeChanged(currentWidth, currentHeight, oldWidth, oldheight)
        canvasRounder.updateSize(currentWidth, currentHeight)
    }

    override fun draw(canvas: Canvas) = canvasRounder.round(canvas) { super.draw(canvas) }

    override fun dispatchDraw(canvas: Canvas) = canvasRounder.round(canvas) { super.dispatchDraw(canvas) }

}

CanvasRounder.kt

class CanvasRounder(cornerRadius: Float, cornerStrokeColor: Int = 0, cornerStrokeWidth: Float = 0F) {
    private val path = android.graphics.Path()
    private lateinit var rectF: RectF
    private var strokePaint: Paint?
    var cornerRadius: Float = cornerRadius
        set(value) {
            field = value
            resetPath()
        }

    init {
        if (cornerStrokeWidth <= 0)
            strokePaint = null
        else {
            strokePaint = Paint()
            strokePaint!!.style = Paint.Style.STROKE
            strokePaint!!.isAntiAlias = true
            strokePaint!!.color = cornerStrokeColor
            strokePaint!!.strokeWidth = cornerStrokeWidth
        }
    }

    fun round(canvas: Canvas, drawFunction: (Canvas) -> Unit) {
        val save = canvas.save()
        canvas.clipPath(path)
        drawFunction(canvas)
        if (strokePaint != null)
            canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)
        canvas.restoreToCount(save)
    }

    fun updateSize(currentWidth: Int, currentHeight: Int) {
        rectF = android.graphics.RectF(0f, 0f, currentWidth.toFloat(), currentHeight.toFloat())
        resetPath()
    }

    private fun resetPath() {
        path.reset()
        path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
        path.close()
    }

}
  1. OK.
JcMinarro commented 6 years ago

Would be great if you could create a PR with the update ;)

AndroidDeveloperLB commented 6 years ago

As I wrote, I'm not sure how people who use the library would like to access the stroke (etc) programmatically (currently it's all in XML, because this was enough in my case)

I'm also not sure how to correctly add support for it in code, because I'm not experienced enough with such operations. I just tried various things until it was enough for the requirements of our project.

AndroidDeveloperLB commented 6 years ago

Would you like a PR still, and you will take care of the extra functions ?

JcMinarro commented 5 years ago

Hello @AndroidDeveloperLB

17 Added support for setting radius for individual corners, So your question number 2 is fixed now.

What about the rest of them? Do you think that you could do a PR with the updates?

AndroidDeveloperLB commented 5 years ago

@JcMinarro The changes seems problematic now. In the round function, there is a call to : canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)

But now cornerRadius isn't always the same for X and Y, and the corner of one side might be different than the other.

       /**
        * Draw the specified round-rect using the specified paint. The roundrect will be filled or
        * framed based on the Style in the paint.
        *
        * @param rect The rectangular bounds of the roundRect to be drawn
        * @param rx The x-radius of the oval used to round the corners
        * @param ry The y-radius of the oval used to round the corners
        * @param paint The paint used to draw the roundRect
        */
       public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
           super.drawRoundRect(rect, rx, ry, paint);
       }

It's weird though. Shouldn't there be an alternative for drawing rounded corners, where each corner has a different radius?

AndroidDeveloperLB commented 5 years ago

I've noticed some things that are not considered recommended for libraries:

  1. You use extension functions. I don't think this should exist in libraries as they can be used in the wrong way by others. Same goes for having global gradle constants (ANDROID_MIN_SDK_VERSION for example). I don't know about this. Do you think that whoever uses the library should be able to access those?
  2. You didn't set resourcePrefix (link here about it). Currently the attributes might cause collisions with other codes.
  3. You have a resource that's not really needed (app_name) in the library.
  4. You still use buildToolsVersion , even though it's not needed anymore
  5. Not sure, but I think it's safe to move to android-x instead of support library. Wonder how it will affect people who use this library, and haven't moved to android-x yet, though.

I've prepared a PR here, handling just 3&4 ,adding ConstraintLayout support, and updating some SDKs:

https://github.com/JcMinarro/RoundKornerLayouts/pull/19

https://github.com/AndroidDeveloperLB/RoundKornerLayouts

AndroidDeveloperLB commented 5 years ago

But sadly, I've failed to add the thing I wanted, of the stroke.

Please do consider adding it.