Закруглить углы Canvas
Есть такая вьюшка
public class PieChartView extends View {
private final static String[] RColors = {"#448c9b", "#789a98", "#a4a795", "#ac6226", "#ef3c5e", "#b17170", "#9a9a82", "#bda763"};
private RectF rec;
private Paint p = new Paint();
private String[][] data = {
{"Facebook", "20"},
{"Twitter", "20"},
{"Whats app", "20"},
{"Pinterest", "20"},
{"Baby App", "20"}
};
private int d = 0;
private float textSize = 20f;
//========================
public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
}
//========================
public PieChartView(Context ctx){super(ctx);}
//========================
@Override
public void onSizeChanged(int nw, int nh, int ow, int oh){
super.onSizeChanged(nw, nh, ow, oh);
d = nw>nh?nh:nw;
rec = new RectF(0, 0, d, d);
p.setFlags(Paint.ANTI_ALIAS_FLAG);
}
//========================
public void setTextSize(float size){textSize=size;}
//========================
/**Set data to be shown in pie chart view
* @param dList ArrayList of Object[], 1st element will contain the name, 2nd the percentage (int)
*/
public void setData(ArrayList<Object[]> dList){
data = new String[dList.size()][2];
int i=0;
for(Object[] op:dList){
data[i++] = new String[]{op[0]+"",op[1]+""};
}
}
//========================
@Override
public void onDraw(Canvas c){
int size = data.length;
int sa=0, ea=0, ci=0;
//== draw arc
for(int i=0;i<size;i++){
int perc = Integer.parseInt(data[i][1]);
int pdeg = (perc*360)/100;
ea = sa+pdeg;
p.setColor(Color.parseColor(RColors[ci++]));
if(ci==RColors.length)
ci=0;
c.drawArc(rec, sa+3, pdeg-2, true, p);
sa = ea;
}
//== draw circle in center
p.setColor(Color.WHITE);
c.drawCircle(rec.right/2, rec.bottom/2, (int)(0.8*(d/2)) , p);
//== write text
p.setColor(Color.BLACK);
p.setFakeBoldText(true);
p.setTextSize(textSize);
sa=0;ea=0;ci=0;
double ra = 0; // Radian angle
for(int i=0;i<size;i++){
p.setColor(Color.parseColor(RColors[ci++]));
if(ci==RColors.length)
ci=0;
int perc = Integer.parseInt(data[i][1]);
int pdeg = (perc*360)/100;
ea = sa+pdeg; //== in degrees
ra = (sa+pdeg/2)*Math.PI/180;
int x = (int)(rec.right/2+(((rec.right/2)*.5)*Math.cos(ra)));
int y = (int)(rec.right/2+(((rec.right/2)*.5)*Math.sin(ra)));
String text = data[i][0];
c.drawText(text, x-p.measureText(text)/2, y, p);
text = data[i][1]+"%";
c.drawText(text, x-p.measureText(text)/2, y-p.ascent()+p.descent(), p);
sa = ea;
}
}
}
Вопрос к знатокам Canvas, как можно сделать такую же View, но только чтобы углы у линий были закруглены (на красном участке показал примерно как нужно закруглять), желательно конечно возможность управлять градусом закругления.

Ответы (1 шт):
Автор решения: DuosDuo
→ Ссылка
Сделал вот так. Если есть, что добавить, то велком!
class Data(
val color: Int,
val percent: Float
)
class PieChart : View {
private val paint = Paint()
private val tPaint = Paint()
private var oval = RectF()
private var demo: Boolean = false
var lineOffset: Int = 0
var startAngle: Float = 0F
set(value) {
field = value
invalidate()
}
var descriptionTextSize: Float = 14F
set(value) {
field = value
initPaintByText()
invalidate()
}
var description: String = "Test description"
set(value) {
field = value
invalidate()
}
var data: List<Data> = listOf()
set(value) {
field = value
invalidate()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
initAttrs(context = context, attrs = attrs)
initStart()
}
constructor(context: Context?) : super(context) {
initStart()
}
init {
initPaintByText()
initPaint()
}
private fun initAttrs( context: Context, attrs: AttributeSet) {
val a = context.theme.obtainStyledAttributes(attrs, R.styleable.PieChart, 0, 0)
try {
demo = a.getBoolean(R.styleable.PieChart_demo, false)
lineOffset = a.getDimensionPixelOffset(R.styleable.PieChart_lineOffset, 0)
description = a.getString(R.styleable.PieChart_description) ?: ""
startAngle = a.getFloat(R.styleable.PieChart_startAngle, 0F)
descriptionTextSize = a.getDimensionPixelOffset(R.styleable.PieChart_descriptionTextSize, 14).toFloat()
} finally {
a.recycle()
}
}
private fun initPaint(){
paint.isAntiAlias = true
paint.strokeWidth = 30f
paint.strokeCap = Paint.Cap.ROUND
paint.style = Paint.Style.STROKE
}
private fun initPaintByText() {
tPaint.color = Color.BLACK
tPaint.isFakeBoldText = true
tPaint.textSize = descriptionTextSize
}
private fun initStart(){
if (demo) {
data = listOf(Data(Color.GREEN, 45F), Data(Color.BLUE, 35F), Data(Color.RED, 20F))
}
initPaint()
initPaintByText()
}
public override fun onDraw(canvas: Canvas) {
val width = width.toFloat()
val height = height.toFloat()
val radius: Float
radius = if (width > height) {
height / 3
} else {
width / 3
}
val centerX = width / 2
val centerY = height / 1.6f
val left = centerX - radius
val top = centerY - radius
val right = centerX + radius
val bottom = centerY + radius
oval[left, top, right] = bottom
var mAngle: Float = startAngle
for ((index, item) in data.withIndex()) {
paint.color = item.color
val pInAngle = item.percent * 3.6F
val sAngle = pInAngle - (lineOffset)
canvas.drawArc(oval, mAngle, sAngle, false, paint)
mAngle += lineOffset + sAngle
}
}
}

