I am writing a reader under Android. Pages are separated into different View. How to calculate how many characters fit on the screen to correctly divide the text into different View? Maybe there is a simple method to do this?
The code for adding text to Views:
for (int i = 0; i < pages; i++) {
TextView textView = new TextView(getApplicationContext());
textView.setText(text);
realViewSwitcher.addView(textView);
}
you could probably make assumptions based on text size, maybe the default here would be 12dip. And then assuming that the average word length is 5 words. determining how many dips a 5 character words takes. and then taking the width and height and and divide it by that number.
Maybe Paint can help you. There is methods like "measureText", or "breakText". You can get a Paint object from a TextView with getPaint().
perhaps you could calculate the number of ems that fit in the textview somehow.
or perhaps you could create an algorithm that try's to fit the characters based on computerVerticalScrollRange(). Through trial and error, it could eventually find the perfect fit.
Related
I'm coding an App for learning tones of Chinese characters. The test words contain anything from 1 to 12 Chinese characters, which I want to be evenly distributed over the width of the page, with shorter words having larger characters than longer words. In order to achieve this, I'm filling a horizontal linear layout with programmatically created textviews. Each of these textviews contains one single Chinese character and gets assigned a weight through layout parameters.
The width of the textviews gets applied correctly, however, I fail to auto-size the containing characters (again: only one Chinese character per textview) .
I've tried different versions of auto-size, but the text size doesn't change, as it only seems to take the height of the textview into account, not the width. This results in characters being cropped in width for longer words.
This is the Container in which I create single text views:
XML
<LinearLayout
android:id="#+id/hanziframe"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="20"
android:orientation="horizontal"
android:weightSum="100"
>
Here I iterate through the single characters of the test word, giving each the same weight in the above layout:
public void proceedToQuestion(String han) {
int nhanzi = han.length(); //number of characters
float widthperhanzi = 100 / nhanzi;
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
0, LayoutParams.MATCH_PARENT,widthperhanzi);
for (int i = 0; i < nhanzi; i++) {
TextView h = new TextView(getApplicationContext());
h.setLayoutParams(lp);
h.setText(han.substring(i, i + 1));
TextViewCompat.setAutoSizeTextTypeWithDefaults(h, AUTO_SIZE_TEXT_TYPE_UNIFORM);
hanziframe.addView(h);
hanzis.add(h);
}
A word with three characters gets displayed ok
A longer word - here the single characters get cropped in width.
How can I make the characters assume the correct size depending on how many there are? Is there any way to calculate the text size directly from the screen size? Or have I just set the layout parameters incorrectly?
Any help is greatly appreciated!
textview 新特性 Autosizing 了解一下 向下支持到 Android Level 14
I want to calculate the ems value according to the string or text length count If text length increase it should occupy it's width size according to the characters count without cut-off text in a single line, thanks
Tried to keep string length as ems but it gives very long width size with empty spaces, Thanks in advance
Using monospaced fonts you could count the em-width of a string. Since letters like i and m do in other cases not have the same length, the pixel/em/dp count cannot be predicted.
If someone would write a sophisticated logic for the widths of letters, count them, then multiply count with per-letter-length, this solution would still be too inaccurate without even more refinements: Ligatures and kerning make the actual width of a word even more complex. For example, A and V can overlap a little, while a capital A following another A or the letter V following another V are same width at at base or top, respectively. Therefore their centers have to be moved away from each other so as to not overlap.
Is there a way to know how many characters of font size 10sp can fit into a TextView of a fixed width (let's say 100dp)?
I need to track if the whole string will fit (be visible) into a TextView of predefined width.
I haven't been able to find a way to track or calculate this.
Since Android uses proportional fonts, each character occupies a different width. Also if you take kerning into account the width of a string may be shorter than the sum of the widths of individual characters.
So it's easiest to measure the whole string by adding one character at a time until (a) the entire string if found to fit within the limit, or (b) the width of the string exceeds the limit.
The following code shows how to find how many characters of size 11px fits into TextView 100px wide. (You can find formulas to convert between px & dp on the Web).
We'll do it by using measureText(String text, int start, int end) in a loop incrementing the value of end until it it no longer fits the TextView's width.
String text = "This is my string";
int textViewWidth = 100;
int numChars;
Paint paint = textView.getPaint();
for (numChars = 1; numChars <= text.length; ++numChars) {
if (paint.measureText(text, 0, numChars) > textViewWidth) {
break;
}
}
Log.d("tag", "Number of characters that fit = " + (numChars - 1));
If performance is poor, you may try using a binary search method instead of a linear loop.
The best way to determine this would just be to test it. Since you are using DP it will be relatively device-independent. Unless you are using a fixed-width font there isn't really a way to determine it theoretically unless you want to actually try and measure the width of each letter, the kerning, etc. and compare to the width of the TextView
I have built a ListView and my items - at least in part - contain titles of various (text) lengths.
In order to enable the user to read as much of the title as possible, I'm trying to change my adapter to auto-pick a feasible font size for my texts.
So I'm working with the TextView's paint object to measure the text in a basline font size (14dp) and try to compare against the available space. If the text is too big, I reduce the font size to 12dp (later I might think about reducing it even further).
// Note: vh.filmTitleTextView is my TextView, filmText contains the title I want to display
filmTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
float textWidth = vh.filmTitleTextView.getPaint().measureText(filmText);
if (textWidth > vh.filmTitleTextView.getWidth())
vh.filmTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
The issue is that on first run, vh.filmTitleTextView.getWidth() always returns zero. I guess this is because the layout has not been rendered before and the size is not yet known.
I can't just go with the full size of the ListView because the textView doesn't have the same width (despite the fact that it is set to layout_width="fill_parent") - there are some elements around it.
Any ideas?
Had a similar problem that was my bane for a long time - this might help ya: Auto Scale TextView Text to Fit within Bounds
I think the answer to this question is probably so simple, but I'm struggling....
I have a TableLayout with multiple columns. I want the last column to be of a fixed width, but I want to define that width to just be able to hold the widest possible string from my program. i.e. it is always wide enough to contain "THIS STRING" without wrapping, or wasting any space.
I would like to do this as I have these TableLayouts within a ListView, so it looks very poor when the last column is of variable widths.
I have tried obtaining the string width, even going so far as to put it into a TextView, call getTextSize() then setWidth() on all appropriate TextViews. The problem I hit there is that gettextSize() returns pixels, but setWidth uses ScaledPixels.
I'm sure there is a really simple solution. Can anyone help?
Are you using android:width="wrap_content" in your XML layout to define the width of that last column?
Edit: I think I just understood, you have a list view, that holds a table and you want all rows of the list view to have the same length for the last row of the table. Right?
I can only think of one, very unelegant solution right now and it involves going over all strings before building the list view.
The general logic would be as follows:
Im going to suppose you are getting al strings from an array, lets call it data.
Establish a global float variable to represent the longest string you have, lets call it maxLength.
Create a textview (lets call it invisibleText) in your layout that wont be visible, you can do this by setting
android:visibility="gone"
Then:
int size = data.length;
maxLength = 0.0f;
for(int i = 0;i<size;i++){
invisibleText.setText(data[i]);
float thisLength = invisibleText.getTextSize();
if(thisLength>maxLength) maxLength = thisLength;
}
In you list view constructor:
TextView text = (TextView)findViewById(R.id.the_text_view_you_want);
text.setText(data[position]);
text.setWidth(maxLength)
The table columns should use android:width="wrap_content"
I didnt test this code, but it should work, i've done similar stuff before.