La risposta accettata non funziona quando una parola intera è posto sulla riga successiva, al fine di evitare di rompere la parola:
|hello |
|world! |
L'unico modo per essere sicuri al 100% circa il numero di linee è utilizzare lo stesso motore di flusso di testo utilizzato da TextView. Poiché TextView non condivide la logica del reflusso, ecco un processore di stringhe personalizzato che suddivide il testo in più righe, ciascuna delle quali si adatta alla larghezza specificata. Lo fa anche del suo meglio per non spezzare le parole a meno che l'intera parola non va bene:
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 start = 0;
for(int i = 1; i <= source.length(); i++) {
String substr = source.substring(start, i);
if(paint.measureText(substr) >= maxWidthPx) {
//this one doesn't fit, take the previous one which fits
String fits = source.substring(start, i - 1);
result.add(fits);
start = i - 1;
}
if (i == source.length()) {
String fits = source.substring(start, 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.clear();
//ok because chunk fits
currentLine.add(chunk);
}
}
Ecco una parte di una prova di unità:
String text = "Hello this is a very 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 very long and meanless chunk:", strings.get(0));
assertEquals("abcdefghijkonetuhosnahrc.pgraoneuhnotehurc.pganso", strings.get(1));
assertEquals("htunsaohtu. Hope you like it!", strings.get(2));
Ora si può essere sicuri al 100% sulla linea contare in TextView senza bisogno di renderlo:
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()
possibile duplicati di http://stackoverflow.com/questions/12037377/how- to-get-number-of-lines-of-textview – Krishnabhadra
Non è una domanda duplicata. perché voti per chiudere questa domanda? è una buona domanda e qualcuno ha risposto alla mia domanda ed è la risposta corretta. – Nandha
Confermato non un duplicato. Ho usato questo nella mia soluzione a causa della necessità di calcolare il numero di linee senza utilizzare una vista precaricata (perché la vista precaricata è stata abbreviata dal metodo "SetMaxLines" di TextView). Il thread duplicato fornito non copre questa possibilità. Upvoting sia la soluzione che la domanda perché erano estremamente utili. – moscro