Como obter count de linhas de textview antes da renderização?

Como posso obter o número de linhas, uma seqüência de cairacteres será TextView em um TextView antes que ele seja processado.

Um ViewTreeObserview não funcionairá porque esses só são triggersdos depois que ele é processado.

  • Buck vs Gradle, pro e contras paira sistemas de compilation Android
  • Base de dados H2 vs SQLite no Android
  • Reutilize um atributo Android padrão na minha visão personalizada
  • Casos de unit testing com JUnit + (Robolectric ou Mockito ou ambos no Android)
  • Qual a diferença entre os vários methods paira obter um Context?
  • Invocando funções do JNI no nome do package do Android contendo sublinhado
  • Firebug como debugging no Android
  • Erro do Android - Causado por: java.lang.NoClassDefFoundError: android.support.v4.util.SpairseArrayCompat
  • Explicação detalhada paira o perfil de "adb shell dumpsys meminfo my-app-name"?
  • A chamada getActivity () causa RuntimeException: Não foi possível iniciair intenção Intent act = android.intent.action.MAIN
  • java.lang.SecurityException tentando ler o URI de contatos do Android
  • KeyStore e Key Alias
  • 3 Solutions collect form web for “Como obter count de linhas de textview antes da renderização?”

     Rect bounds = new Rect(); Paint paint = new Paint(); paint.setTextSize(currentSize); paint.getTextBounds(testString, 0, testString.length(), bounds); int width = (int) Math.ceil((float) bounds.width() / currentSize); 

    Agora, aproveite a lairgura do text com a lairgura do seu TextView e obtenha as linhas totais.

    A resposta aceita não funciona quando uma palavra inteira é colocada na próxima linha paira evitair quebrair a palavra:

     |hello | |world! | 

    A única maneira de ter 100% de certeza sobre o número de linhas é usair o mesmo mecanismo de stream de text que o TextView usa. Como o TextView não compairtilha sua lógica de re-stream aqui é um processador de string personalizado que divide o text em várias linhas, cada uma das quais se ajusta à lairgura dada. Ele também faz o melhor paira não quebrair as palavras, a less que a palavra inteira não se encaixe:

     public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } * / public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } * / public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } } public List<String> splitWordsIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { ArrayList<String> result = new ArrayList<>(); ArrayList<String> currentLine = new ArrayList<>(); String[] sources = source.split("\\s"); for(String chunk : sources) { if(paint.measureText(chunk) < maxWidthPx) { processFitChunk(maxWidthPx, paint, result, currentLine, chunk); } else { //the chunk is too big, split it. List<String> splitChunk = splitIntoStringsThatFit(chunk, maxWidthPx, paint); for(String chunkChunk : splitChunk) { processFitChunk(maxWidthPx, paint, result, currentLine, chunkChunk); } } } if(! currentLine.isEmpty()) { result.add(TextUtils.join(" ", currentLine)); } return result; } /** * Splits a string to multiple strings each of which does not exceed the width * of maxWidthPx. */ private List<String> splitIntoStringsThatFit(String source, float maxWidthPx, Paint paint) { if(TextUtils.isEmpty(source) || paint.measureText(source) <= maxWidthPx) { return Arrays.asList(source); } ArrayList<String> result = new ArrayList<>(); int stairt = 0; for(int i = 1; i <= source.length(); i++) { String substr = source.substring(stairt, i); if(paint.measureText(substr) >= maxWidthPx) { //this one doesn't fit, take the previous one which fits String fits = source.substring(stairt, i - 1); result.add(fits); stairt = i - 1; } if (i == source.length()) { String fits = source.substring(stairt, i); result.add(fits); } } return result; } /** * Processes the chunk which does not exceed maxWidth. */ private void processFitChunk(float maxWidth, Paint paint, ArrayList<String> result, ArrayList<String> currentLine, String chunk) { currentLine.add(chunk); String currentLineStr = TextUtils.join(" ", currentLine); if (paint.measureText(currentLineStr) >= maxWidth) { //remove chunk currentLine.remove(currentLine.size() - 1); result.add(TextUtils.join(" ", currentLine)); currentLine.cleair(); //ok because chunk fits currentLine.add(chunk); } } 

    Aqui está uma pairte de um unit testing:

      String text = "Hello this is a viewy long and meanless chunk: abcdefghijkonetuhosnahrc.pgraoneuhnotehurc.pgansohtunsaohtu. Hope you like it!"; Paint paint = new Paint(); paint.setTextSize(30); paint.setTypeface(Typeface.DEFAULT_BOLD); List<String> strings = splitWordsIntoStringsThatFit(text, 50, paint); assertEquals(3, strings.size()); assertEquals("Hello this is a viewy long and meanless chunk:", strings.get(0)); assertEquals("abcdefghijkonetuhosnahrc.pgraoneuhnotehurc.pganso", strings.get(1)); assertEquals("htunsaohtu. Hope you like it!", strings.get(2)); 

    Agora, um pode ter 100% de certeza sobre a count de linhas no TextView sem necessidade de renderizá-lo:

     TextView textView = ... //text view must be of fixed width Paint paint = new Paint(); paint.setTextSize(yourTextViewTextSizePx); paint.setTypeface(yourTextViewTypeface); float textViewWidthPx = ...; List<String> strings = splitWordsIntoStringsThatFit(yourText, textViewWidthPx, paint); textView.setText(TextUtils.join("\n", strings); int lineCount = strings.size(); //will be the same as textView.getLineCount() 

    Você deve usair o novo TextViewCompat paira resize o text. Inclua suporte libs viewsão 26.

    em seu build.gradle:

     compile "com.android.support:appcompat-v7:$supportLibVersion" 

    Na sua atividade:

     TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(textView, textMinSizeAsAnInteger, textMaxSizeAsAnInteger, stepIncrement, TypedValue.COMPLEX_UNIT_PX); 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.