Cómo rotar el texto con lienzo en Android

I fue dibujar un gráfico circular utilizando el lienzo en android y utilizando el siguiente código i dibujar un texto en cada rebanada de ese gráfico circular (dibujar arco en el camino), ahora quiero dibujar la longitud del texto sabio, es decir, de centro a final de la cada Rebanada, así que cómo girar el arco usando el ángulo del comienzo y del barrido.

p.addArc(mEventsRect, fStartAngle, fSweepAngle); mBgPaints.setColor(iTextColor); canvas.drawTextOnPath(sTextValue, p, fHOffSet, fVOffSet, mBgPaints); 

Introduzca aquí la descripción de la imagen

Puedes probar este fragmento: (desde: http://www.helloandroid.com/tutorials/how-use-canvas-your-android-apps-part-2 )

 int x = 75; int y = 185; paint.setColor(Color.GRAY); paint.setTextSize(25); String rotatedtext = "Rotated helloandroid :)"; //Draw bounding rect before rotating text: Rect rect = new Rect(); paint.getTextBounds(rotatedtext, 0, rotatedtext.length(), rect); canvas.translate(x, y); paint.setStyle(Paint.Style.FILL); canvas.drawText(rotatedtext , 0, 0, paint); paint.setStyle(Paint.Style.STROKE); canvas.drawRect(rect, paint); canvas.translate(-x, -y); paint.setColor(Color.RED); canvas.rotate(-45, x + rect.exactCenterX(),y + rect.exactCenterY()); paint.setStyle(Paint.Style.FILL); canvas.drawText(rotatedtext, x, y, paint); 

Puede ser esto le ayudará, aquí 39.5 es el radio, esto mostrará perfectamente el resultado en la pantalla del mdpi

  protected void onDraw(){ canvas.save(); PointF pf = PointOnCircle(35f, 45f, new PointF(39.5f, 39.5f)); canvas.rotate(-45, pf.x, pf.y); canvas.drawText("67%", pf.x, pf.y, red);//23.5 canvas.restore(); canvas.save(); PointF pfa = PointOnCircle(35f, 135f, new PointF(39.5f, 39.5f)); canvas.rotate(45, pfa.x, pfa.y); canvas.drawText("33%", pfa.x, pfa.y, red);//23.5 canvas.restore(); canvas.save(); pfa = PointOnCircle(27.5f, 225f, new PointF(39.5f, 39.5f)); canvas.rotate(-45, pfa.x, pfa.y); canvas.drawText("45%", pfa.x, pfa.y, red);//23.5 canvas.restore(); canvas.save(); pfa = PointOnCircle(27.5f, 315f, new PointF(39.5f, 39.5f)); canvas.rotate(45, pfa.x, pfa.y); canvas.drawText("55%", pfa.x, pfa.y, red);//23.5 canvas.restore();} protected static final PointF PointOnCircle(float radius, float angleInDegrees, PointF origin) { // Convert from degrees to radians via multiplication by PI/180 float x = (float) (radius * Math.cos(angleInDegrees * Math.PI / 180F)) + origin.x; float y = (float) (radius * Math.sin(angleInDegrees * Math.PI / 180F)) + origin.y; return new PointF(x, y); } 

He aquí cómo lo hice finalmente después de dos días de búsqueda con la ayuda de esta biblioteca https://github.com/Ken-Yang/AndroidPieChart Y las ecuaciones para centrar el texto hecho con la ayuda de mis amigos y un montón de búsqueda

On MainActivity onCreate o oncreateView si está utilizando fragmentos:

 PieChart pie = (PieChart) rootView.findViewById(R.id.pieChart); ArrayList<Float> alPercentage = new ArrayList<Float>(); alPercentage.add(2.0f); alPercentage.add(8.0f); alPercentage.add(20.0f); alPercentage.add(10.0f); alPercentage.add(10.0f); alPercentage.add(10.0f); alPercentage.add(10.0f); alPercentage.add(10.0f); alPercentage.add(10.85f); alPercentage.add(9.15f); try { // setting data pie.setAdapter(alPercentage); // setting a listener pie.setOnSelectedListener(new OnSelectedLisenter() { @Override public void onSelected(int iSelectedIndex) { Toast.makeText(getActivity(), "Select index:" + iSelectedIndex, Toast.LENGTH_SHORT).show(); } }); } catch (Exception e) { if (e.getMessage().equals(PieChart.ERROR_NOT_EQUAL_TO_100)) { Log.e("kenyang", "percentage is not equal to 100"); } } public class PieChart extends View { public interface OnSelectedLisenter { public abstract void onSelected(int iSelectedIndex); } private OnSelectedLisenter onSelectedListener = null; private static final String TAG = PieChart.class.getName(); public static final String ERROR_NOT_EQUAL_TO_100 = "NOT_EQUAL_TO_100"; private static final int DEGREE_360 = 360; private static String[] PIE_COLORS = null; private static int iColorListSize = 0; ArrayList<Float> array; private Paint paintPieFill; private Paint paintPieBorder; private Paint paintCenterCircle; private ArrayList<Float> alPercentage = new ArrayList<Float>(); private int mCenterX = 320; private int mCenterY = 320; private int iDisplayWidth, iDisplayHeight; private int iSelectedIndex = -1; private int iCenterWidth = 0; private int iShift = 0; private int iMargin = 0; // margin to left and right, used for get Radius private int iDataSize = 0; private Canvas canvas1; private RectF r = null; private RectF centerCircle = null; private float fDensity = 0.0f; private float fStartAngle = 0.0f; private float fEndAngle = 0.0f; float fX; float fY; public PieChart(Context context, AttributeSet attrs) { super(context, attrs); PIE_COLORS = getResources().getStringArray(R.array.colors); iColorListSize = PIE_COLORS.length; array = new ArrayList<Float>(); fnGetDisplayMetrics(context); iShift = (int) fnGetRealPxFromDp(30); iMargin = (int) fnGetRealPxFromDp(40); centerCircle = new RectF(200, 200, 440, 440); // used for paint circle paintPieFill = new Paint(Paint.ANTI_ALIAS_FLAG); paintPieFill.setStyle(Paint.Style.FILL); // used for paint centerCircle paintCenterCircle = new Paint(Paint.ANTI_ALIAS_FLAG); paintCenterCircle.setStyle(Paint.Style.FILL); paintCenterCircle.setColor(Color.WHITE); // used for paint border paintPieBorder = new Paint(Paint.ANTI_ALIAS_FLAG); paintPieBorder.setStyle(Paint.Style.STROKE); paintPieBorder.setStrokeWidth(fnGetRealPxFromDp(3)); paintPieBorder.setColor(Color.WHITE); Log.i(TAG, "PieChart init"); } // set listener public void setOnSelectedListener(OnSelectedLisenter listener) { this.onSelectedListener = listener; } float temp = 0; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i(TAG, "onDraw"); float centerX = (r.left + r.right) / 2; float centerY = (r.top + r.bottom) / 2; float radius1 = (r.right - r.left) / 2; radius1 *= 0.5; float startX = mCenterX; float startY = mCenterY; float radius = mCenterX; float medianAngle = 0; Path path = new Path(); for (int i = 0; i < iDataSize; i++) { // check whether the data size larger than color list size if (i >= iColorListSize) { paintPieFill.setColor(Color.parseColor(PIE_COLORS[i % iColorListSize])); } else { paintPieFill.setColor(Color.parseColor(PIE_COLORS[i])); } fEndAngle = alPercentage.get(i); // convert percentage to angle fEndAngle = fEndAngle / 100 * DEGREE_360; // if the part of pie was selected then change the coordinate if (iSelectedIndex == i) { canvas.save(Canvas.MATRIX_SAVE_FLAG); float fAngle = fStartAngle + fEndAngle / 2; double dxRadius = Math.toRadians((fAngle + DEGREE_360) % DEGREE_360); fY = (float) Math.sin(dxRadius); fX = (float) Math.cos(dxRadius); canvas.translate(fX * iShift, fY * iShift); } canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieFill); float angle = (float) ((fStartAngle + fEndAngle / 2) * Math.PI / 180); float stopX = (float) (startX + (radius/2) * Math.cos(angle)); float stopY = (float) (startY + (radius/2) * Math.sin(angle)); // if the part of pie was selected then draw a border if (iSelectedIndex == i) { canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieBorder); canvas.drawLine(startX, startY, stopX, stopY, paintPieFill); canvas.restore(); } fStartAngle = fStartAngle + fEndAngle; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // get screen size iDisplayWidth = MeasureSpec.getSize(widthMeasureSpec); iDisplayHeight = MeasureSpec.getSize(heightMeasureSpec); if (iDisplayWidth > iDisplayHeight) { iDisplayWidth = iDisplayHeight; } /* * determine the rectangle size */ iCenterWidth = iDisplayWidth / 2; int iR = iCenterWidth - iMargin; if (r == null) { r = new RectF(iCenterWidth - iR, // top iCenterWidth - iR, // left iCenterWidth + iR, // right iCenterWidth + iR); // bottom } if (centerCircle == null) { // centerCircle=new RectF(left, top, right, bottom); } setMeasuredDimension(iDisplayWidth, iDisplayWidth); } @Override public boolean onTouchEvent(MotionEvent event) { // get degree of the touch point double dx = Math.atan2(event.getY() - iCenterWidth, event.getX() - iCenterWidth); float fDegree = (float) (dx / (2 * Math.PI) * DEGREE_360); fDegree = (fDegree + DEGREE_360) % DEGREE_360; // get the percent of the selected degree float fSelectedPercent = fDegree * 100 / DEGREE_360; // check which pie was selected float fTotalPercent = 0; for (int i = 0; i < iDataSize; i++) { fTotalPercent += alPercentage.get(i); if (fTotalPercent > fSelectedPercent) { iSelectedIndex = i; break; } } if (onSelectedListener != null) { onSelectedListener.onSelected(iSelectedIndex); } invalidate(); return super.onTouchEvent(event); } private void fnGetDisplayMetrics(Context cxt) { final DisplayMetrics dm = cxt.getResources().getDisplayMetrics(); fDensity = dm.density; } private float fnGetRealPxFromDp(float fDp) { return (fDensity != 1.0f) ? fDensity * fDp : fDp; } public void setAdapter(ArrayList<Float> alPercentage) throws Exception { this.alPercentage = alPercentage; iDataSize = alPercentage.size(); float fSum = 0; for (int i = 0; i < iDataSize; i++) { fSum += alPercentage.get(i); } if (fSum != 100) { Log.e(TAG, ERROR_NOT_EQUAL_TO_100); iDataSize = 0; throw new Exception(ERROR_NOT_EQUAL_TO_100); } } 

En su Layout:

 <com.example.piecharts.PieChart android:id="@+id/pieChart" android:layout_width="match_parent" android:layout_height="match_parent" > </com.example.piecharts.PieChart> 

Esta pregunta es bastante antigua, pero pensé que escribiría una respuesta general.Aquí presumo que desea dibujar su gráfico circular en el centro del lienzo y que tiene sus ángulos de inicio y de filtración en una matriz.

 x = canvas.getWidth/2 //Horizontal center of canvas view y = canvas.getHeight/2 //Vertical center of canvas view canvas.rotate(fStartAngle[i]+ fSweepAngle[i]/2, x ,y ); //Rotates canvas to a line in the middle //of start and end of arc canvas.translate(50f,0);//Moves the text a little out of the center of the circle (50f is arbitrary) paintText.setStyle(Paint.Style.FILL); canvas.drawText(rotatedtext, x, y, paintText); //Undo the translations and rotations so that next arc can be drawn normally canvas.translate(-50f,0); canvas.rotate(-(temp+ value_degree[i]/2), x ,y ); 
  • Android: Problema con el estilo de ruta en Region.Op
  • Cómo dibujar liso / camino redondeado?
  • En android sdk1.5 donde encontrar mi Sqlite Db en mi sistema
  • ¿Cómo se supone que debes usar un ShapeDrawable con una PathShape para dibujar una línea en una vista personalizada?
  • Necesito establecer la ruta para guardar las imágenes con una aplicación para Android e IOS con UNITY
  • ANDROID NDK - android: comando no encontrado
  • Android path to array - lee los puntos de una ruta?
  • Camino de Android Studio a diferentes directorios
  • Cómo cambiar el tamaño de un camino?
  • Dibuja una ruta en AndEngine para mover una imagen o un sprite
  • Captura de pantalla
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.