Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Envuelva texto fuera de la curva de bezier en android

Quiero envolver texto en forma de bezier curva fuera de la curva en android.

Lo que he intentado :

Path path = new Path(); path.addCircle(x, y, radius, Path.Direction.CW); myCanvas.drawTextOnPath(myText, path, offset, 0, myPaint); 

Lo que estoy tratando de lograr :

Pero este código dibuja el texto en la curva. No quiero escribir el texto en la curva. Quiero envolver el texto según la curva y lo escribo en la línea siguiente.

Para entenderlo claramente, por favor refiérase a baconforme.com .. Quiero crear este comportamiento jquery como en android sin usar el navegador web .

y vio este enlace En Android ¿cómo puedo envolver el texto dentro de un camino de Bezier

Pregunta :

  1. ¿Es posible lograr esto?
  2. Si es así, por favor guíame.

  • ¿Cómo puedo dibujar curva sin fisuras usando gráficos de Android?
  • Buscar un nuevo punto de control cuando cambia el punto final en la curva cúbica de Bézier
  • Android: firma digital con Bezier
  • One Solution collect form web for “Envuelva texto fuera de la curva de bezier en android”

    He implementado una vista básica que realiza lo que estás intentando hacer. La idea aquí es crear un mapa de bits fuera de la ruta que solicitó. Cada píxel fuera de la ruta tendrá un valor 0, y cada píxel dentro de la ruta tendrá algún otro valor.

    Con esto, usted puede saber cuando un punto está dentro del polígono o no. Ahora necesitamos determinar dónde dibujamos el texto.

    Generaré una lista de rectángulos atravesando el mapa de bits generado. Cada rectángulo definirá las filas que comienzan y terminan dentro del polígono.

    Con cada rectángulo, empiezo a rellenar texto hasta que el rectángulo ya no puede acomodar más texto, en cuyo caso me muevo al siguiente rectángulo. Una vez que no hay más rectángulos, o estoy fuera de texto, dejo de dibujar.

    En esta implementación, he añadido algunas personalizaciones como el tamaño de la fuente, el color del texto y el modo de ajuste.

    Aquí está:

    PolygonWrapView.java

     public class PolygonWrapView extends View { public enum WrapMode { Letters, Words } private Path mPath; private String mText; private float mFontSize; private int mTextColor; private Paint mPaint; private Bitmap mPathMap; private WrapMode mWrapMode = WrapMode.Words; public PolygonWrapView(Context context) { super(context); init(); } public PolygonWrapView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public PolygonWrapView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mPaint = new Paint(); mFontSize = 20; mTextColor = 0xFF000000; } public void setPath(Path path) { mPath = path; // invalidate the path map. mPathMap = null; } // This method converts the path into a bitmap which will be used to determine if a point is within the path private void generatePathMap() { if (mPath != null) { // the path map bitmap can have poor quality, we're only checking for color or no color in each pixel. mPathMap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_4444); Canvas canvas = new Canvas(mPathMap); Paint pathPaint = new Paint(); pathPaint.setStyle(Paint.Style.FILL); pathPaint.setColor(0xFFFFFFFF); // draw the path. canvas.drawPath(mPath, pathPaint); } } public void setText(String text) { mText = text; } public void setFontSize(float fontSize) { mFontSize = fontSize; } public void setTextColor(int textColor) { mTextColor = textColor; } public void setWrapMode(WrapMode wrapMode) { mWrapMode = wrapMode; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // make sure we have enough data to begin drawing text. if (mPath == null || mText == null || getMeasuredWidth() == 0 || getMeasuredHeight() == 0) return; // if the path map hasn't been generated, generate it now. if (mPathMap == null) generatePathMap(); final List<Rect> writableRects = getTextRects(); final List<String> textFragments = getTextFragments(); mPaint.setColor(mTextColor); mPaint.setTextSize(mFontSize); int rectIndex = 0; int fragmentIndex = 0; Rect rect = null; String textFragment = null; float textWidth; // maybe find a better way to limit this loop? while (true) { // we don't have a rectangle. Get the next 1 in the list. if (rect == null) { // no more rectangles to draw text on. Finish. if (rectIndex >= writableRects.size()) return; rect = new Rect(writableRects.get(rectIndex)); rectIndex++; } // we don't have text to print. Get the next word in the list. if (textFragment == null) { // no more text to draw. Finish. if (fragmentIndex >= textFragments.size()) return; textFragment = textFragments.get(fragmentIndex); fragmentIndex++; } // find how much width this text wants. textWidth = mPaint.measureText(textFragment); // if the rectangle doesn't have enough width, set it to null, indicating its "used up" and we need to next rect. Don't continue drawing text, find a new rect first. if (textWidth > rect.width()) { rect = null; continue; } // draw the text. canvas.drawText(textFragment, rect.left, rect.centerY(), mPaint); // the word has been drawn. Set it null indicating a new 1 is needed in the next iteration. textFragment = null; // remove the used width from the rect and continue. rect.left += textWidth; // In word mode, account for the space that was removed. if (mWrapMode == WrapMode.Words) { rect.left += mPaint.measureText(" "); } } } // get each String fragment as a list. For letters mode, each element will be a letter or char. For words mode, each element will be a word. private List<String> getTextFragments() { List<String> result = new ArrayList<String>(); if (mWrapMode == WrapMode.Letters) { for (int i = 0; i < mText.length(); i++) { result.add("" + mText.charAt(i)); } } else if (mWrapMode == WrapMode.Words) { String[] words = mText.split("\\s+"); for (String word : words) result.add(word); } return result; } private List<Rect> getTextRects() { final List<Rect> result = new ArrayList<Rect>(); boolean isInPolygon = false; Rect rect = null; // place y in the center of the text, jump in fontsize steps. for (int y = (int)(mFontSize / 2); y < getMeasuredHeight(); y += mFontSize) { // place x at 0, jump with 5 px steps. This can be adjusted for better accuracy / performance. for (int x = 0; x < getMeasuredWidth(); x += 5) { // Havent found a point within the polygon yet, but now I have! if (!isInPolygon && mPathMap.getPixel(x, y) != 0) { isInPolygon = true; rect = new Rect(x, y - (int)(mFontSize / 2), x, y + (int)(mFontSize / 2)); } // We found where the polygon started in this row, and now we found where it ends. else if (isInPolygon && mPathMap.getPixel(x, y ) == 0) { isInPolygon = false; rect.right = x; result.add(rect); } } // If the edge is in the ploygon, limit the rect to the right side of the view. if (isInPolygon) { rect.right = getMeasuredWidth(); result.add(rect); } } return result; } } 

    activity_main.xml:

     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <com.gil.polygonwrap.PolygonWrapView android:id="@+id/polygonWrap" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout> 

    MainActivity.java: (ejemplo de uso)

     public class MainActivity extends ActionBarActivity { private PolygonWrapView mPolygonWrapView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPolygonWrapView = (PolygonWrapView)findViewById(R.id.polygonWrap); final String text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; mPolygonWrapView.setText(text); Path path = new Path(); // sample of adding a path with a bezier curve element path.moveTo(0, 0); path.lineTo(500, 0); path.cubicTo(700, 300, 400, 600, 800, 1000); path.lineTo(0, 1000); path.lineTo(0, 0); // only needed when you don't close the path. path.close(); mPolygonWrapView.setPath(path); mPolygonWrapView.setFontSize(30); mPolygonWrapView.setBackgroundColor(0xFFFFFFFF); mPolygonWrapView.invalidate(); } } 

    Lo he probado aquí y parece que funciona bien, al menos lo suficiente para empezar.

    Es posible que desee agregar algunas mejoras, como asegurarse de que la altura de toda la fila está dentro del polígono, no sólo el centroY de la fila.

    Además, es posible que desee respaldar una lista de rutas, en lugar de sólo 1 ruta, de esta manera podría controlar cómo se distribuye el texto entre los segmentos de ruta, en lugar de hacer un relleno de caja x / y como lo hago aquí.

    También puede mejorar el algoritmo para que todas las filas de texto se fijen al final de la fila correctamente ajustando la cantidad de píxeles que asigna a los espacios. Por ejemplo, si una fila no tiene espacio suficiente para ajustar una palabra adicional, pero sin esa palabra la fila termina notablemente antes del final del polígono, podría aumentar el ancho de espacio entre cada palabra para hacer la última palabra de la fila final exactamente donde está el borde del polígono. Implementar esto requeriría cambiar mi algoritmo para preprocesar la fila antes de dibujarla, pero no debería ser demasiado difícil.

    Déjeme saber si tiene más preguntas.

    Edit: he editado el ejemplo de uso para mostrar cómo implementar esta ruta con una curva de bezier. Aquí está una referencia a cómo crear una curva del bezier con una trayectoria para más detalles.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.