I'm using AutoResizeTextView avaiable at this post in stackoverflow.
I have made a grid list with image on top and text on bottom, the way its being done is like this:
<ScrollView>
<LinearLayout>
<Programmed LinearLayout HORIZONTAL orientation>
<Programmed LinearLayout VERTICAL orientation>
<Programmed ImageView/>
<Programmed AutoResizeTextView/>
<LinearLayout/>
(Repeats till screen width complete)
<LinearLayout/>
(Repeats till screen heigth complete)
<LinearLayout/>
<ScrollView/>
Here is a image of how it looks and the "problem" i'm having:
As you can see Cassie Cage and Jacqui Briggs has the text autosized to fit in the space reserved for it, the thing is, it seems different fom the rest of the names, and what I want is to get the smallest text and resize all the other ones to that size.
Heres a sketch of the code I started making for it, but its not working.
ArrayList<TextView> TextViewList = new ArrayList<TextView>();
float smallerTextSize=999999f;
//Declaring one of the textViews:
AutoResizeTextView tv = new AutoResizeTextView(this);
//Correction for 4.0.4 android or lower
final String DOUBLE_BYTE_SPACE = "\u3000";
String fixString = "";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR1
&& android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
fixString = DOUBLE_BYTE_SPACE;
}
tv.setText(fixString + "The text" + fixString);
tv.setPadding(Math.round(gap / (qtd + 1)), 0, 0, 0);
tv.setText(name);
la.addView(tv);
TextViewList.add(tv);
if(tv.getTextSize()<smallerTextSize){
smallerTextSize=tv.getTextSize();
}
So in this code above I declare one of the TextViews that I use in the screen (any increments suggestions will be appreciated)
final int tvlSize = TextViewList.size();
for(int i=0;i<tvlSize;i++){
TextViewList.remove(0).setTextSize(smallerTextSize);
}
So I use the smallerTextSize found in the declaration of the textSizes so I can change the textSize of all the TextViews, but it doesn't work, and the result keeps being the same as the image shown.
How can it be done correctly so all the text assume the size of the smallest one so it keeps up a pattern?
Also, is there a way for those texts to be aligned in the center of that gap?
Thanks in advance!
Specify your textsize in sp. It will scale according to the screen size.
http://developer.android.com/training/multiscreen/screendensities.html
Use gravity to align the text in the center.
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 am currently learning android and I am trying to create an array of buttons for my app in the following manner:
LinearLayout answer_layout = (LinearLayout)findViewById(R.id.answer_layout);
idCount = answer_layout.getId() + 1000;
for(int i = 0 ; i<letters.length ; i++)
{
Button b = new Button(this);
b.setText(letters[i]);
b.setTypeface(null, Typeface.BOLD);
b.setBackgroundResource(R.drawable.puzzletilebg);
b.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
b.setIncludeFontPadding(false);
b.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
b.setId(idCount + i);
b.setTag(Integer.valueOf(i));
bLetters[i] = b;
answer_layout.addView(b);
}
}
When i run this code, i am able to get a row of buttons depending on the length value of string. My problem is the buttons appear stretched and when the length value is more than 7, The buttons dont appear. For this problem i tried implementing the method suggested here(How do I programmatically add buttons into layout one by one in several lines?) but i didnt get any result. What parameters do i have to use to make the shape of the buttons as a perfect square and make sure they are of the same size for all screen sizes? My button background drawable size is 50x50.
If you want a perfect square change
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
to
LinearLayout.LayoutParams(50, 50);
And ofc if your linearLayour is horizontal the buttons will dissapear
on the edge of the screen.
You can use Gridlayout instead of LinearLayout, but if you want something like the LinearLayout i recommend: FlowLayout
example:
Last edit: sorry is not AutoFitLayout is FlowLayout i edited the answer;
Solve your problem?
Instead of LinearLayout use a GridLayout
Try with
b.setWidth(50);
b.setHeight(50);
The numbers are pixels, so maybe you have to convert dp to pixels.
For the problem with button more than 7 not appear, you could try to wrap your LinearLayout answer_layout in a ScrollView or HorizontalScrollView for horizontal scroll behaviour in the xml file.
And for programmatically change the width and the height of the button, you could try this answer https://stackoverflow.com/a/11294075/1331743
from existing post.
I am adding "How to Play" instructions to a game which I have created using libGDX. The instructions scroll need to be shown only inside a fixed area of the screen, not as a full screen scroll. I have created a stage and added some background and other actors, and then some labels which are the title(outside the scroller) and the instructions text(the only thing that need to be scrolled). It also should not be scrolling horizontally, just vertically. So I set the width of the Label and wrapped the text. In short I need full control of the position and size of the scroller, it shouldn't be full screen. So I wrote the following code to add the instruction scroller:
private void addHelpContent()
{
int width = (int) (0.85*alertBounds.width);
int height = scrollStartY - scrollEndY;
int x = Constants.APP_WIDTH/2 - width/2;
BitmapFont font = Model.getInstance().createFont(Constants.ROCK_NORMAL_FONT_FILE_PATH, 20);
Label.LabelStyle labelStyle = new Label.LabelStyle();
labelStyle.font = font;
labelStyle.fontColor = Color.valueOf("A07E10FF");
Label label = new Label(getHelpString(), labelStyle);
label.setWidth(width);
label.setWrap(true);
label.pack();
label.setFillParent(true);
ScrollPane scrollPane = new ScrollPane(label);
scrollPane.setBounds(x, scrollEndY, width, height); //This should be the bounds of the scroller and the scrollable content need to be inside this
scrollPane.layout();
scrollPane.setTouchable(Touchable.enabled);
addActor(scrollPane);
}
But now I am facing two problems:
I am not able to scroll the scrollpane. The label is cut off right at the bounds making the Scrollpane useless.
The other actors except the Labels doesn't appear at first, they will appear only after I scroll the scrollpane(and it won't scroll). This problem is not there if I comment off the code to add the scroll pane. So I am sure it is related to the scrollpane itself.
Can anyone please help me solve this?
I just forgot to add the act() method in the stage class. Adding it solved the issue.
The scrollpanel is a little tricky to get it to work. From my understanding, you cannot set the size of the scrollpane as it will automatically size itself to the same size as the label.
The trick is to add your scrollpane to a table. Then when the size of the label is larger than the size of the table the scrollpane will allow the label to scroll within the table. To make sure it doesn’t scroll horizontal, set the width of the table to the same width as the label. You also shouldn’t have to set the bounds of the scrollpane, let it size itself to the label.
Then instead of adding the scrollpane, add the table that contains the scrollpane.
addActor(table);
I'm using the following method which programatically creates a linearlayout and populates it with two textviews, adds text and then turns it into a drawable that I later use a layer above a shape. However, I've noticed that I can't create a small fontsize - it seems stuck at a minimum size which is relatively.. large, and anything that I specify below that value just seems to make it look increasingly blurry (but still the same size). What could be the reason for this?
This behavior occurs whether or not I used TypedValue.COMPLEX_UNIT_SP.
Edit: This size stays the same even if I specify something ridiculous like:
.setTextSize(TypedValue.COMPLEX_UNIT_SP, 60);
it doesn't get any bigger - it just gets "sharper".
Edit 2: If I specify the top textview as having a very large size, then the smaller I set the second textview, the smaller it becomes - as a ratio (for example, if I set the top at 100 and the bottom at 50 it looks exactly the same as the top at 10 and the bottom at 5). However, in no way can I reduce the size of the top textview.
Edit 3: If I remove one of the textviews, and leave only the other one as a single textview in the layout - I can't change the size at all. I can only make it more or less blurry depending how low I set the number but it will always appear the exact same size on screen.
private Drawable createTextLayer() {
LinearLayout newLinearLayout = new LinearLayout(getContext());
newLinearLayout.setOrientation(LinearLayout.VERTICAL);
newLinearLayout.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
newLinearLayout.setBackgroundColor(getColor(R.color.somecolor));
newLinearLayout.setLayoutParams(layoutParams);
TextView headlinetv = new TextView(getContext());
TextView bodytv = new TextView(getContext());
headlinetv.setText(headlineText);
headlinetv.setTextSize(7);
headlinetv.setGravity(Gravity.CENTER);
bodytv.setText(bodyText);
bodytv.setTextSize(6);
bodytv.setGravity(Gravity.CENTER);
newLinearLayout.addView(headlinetv);
newLinearLayout.addView(bodytv);
newLinearLayout.setDrawingCacheEnabled(true);
newLinearLayout.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
newLinearLayout.layout(0, 0, newLinearLayout.getMeasuredWidth(), newLinearLayout.getMeasuredHeight());
newLinearLayout.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(newLinearLayout.getDrawingCache());
newLinearLayout.setDrawingCacheEnabled(false);
return new BitmapDrawable(getResources(), b);
}
Change your code to:
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 7);
Change the font size of 7 to any font size as you wish.
This turned out to be quite tricky and took me several hours to solve, but I'm posting the answer for anyone else who ends up in a similar situation.
The cause:
The entire drawable layer was the uppermost layer above a shape, and was therefore stretched to the size of the shape no matter what. In order to stretch it to the size of the shape, the largest view was stretched (essentially, the longest textview) and therefore couldn't be enlarged or reduced in size.
The solution:
I defined two more textviews, gave them the longest string by 1 character, and made the textcolor transparent. I would have preferred to give them blank space as content but android refused to measure a textview containing whitespace, so it had to be actual text. I put one textview at the top and one at the bottom and thus the visible text appears perfectly centered and in the correct font size.
Edit:
There turns out to be a better way of doing this. Define the textview as the same size as the shape on which it sits as a layer and define padding around the textview (play around with it to find the minimal amount of padding needed). If you have several textviews, divide the size of the shape by the number of textviews and give each one a fraction.
I have an Android application layout which contains a multiline TextView. When the screen is in portrait orientation, the TextView can display a different length of text to when running in landscape mode. Also when running on a small screen, the TextView can display a different length of text to when running on a larger screen.
Is there any way I can check if the text fits or will be truncated? Or is there any way I can check if the TextView if full?
The problem is the TextView can potentially contain a different number of lines, depending on whether it is landscape, portrait, small screen, large screen, etc.
Thank you for your advice,
Best regards,
James
These answers didn't work very well for me. Here's what I ended up doing
Paint measurePaint = new Paint(myTextView.getPaint());
float pWidth = measurePaint.measureText("This is my big long line of text. Will it fit in here?");
float labelWidth = myTextView.getWidth();
int maxLines = myTextView.getMaxLines();
while (labelWidth > 0 && pWidth/maxLines > labelWidth-20) {
float textSize = measurePaint.getTextSize();
measurePaint.setTextSize(textSize-1);
pWidth = measurePaint.measureText("This is my big long line of text. Will it fit in here?");
if (textSize < TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 7,
getContext().getResources().getDisplayMetrics())) break;
}
myTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, measurePaint.getTextSize());
I'm not saying this will work for every situation as I'm certainly cutting corners here, but the general idea is to measure the text with the textview's paint and keep shrinking it until it will fit inside the textview.
I have found a "cheeky" solution to the problem of measuring the height of the text in a MULTILINE TextView :-
//Calculate the height of the text in the MULTILINE TextView
int textHeight = textView.getLineCount() * textView.getLineHeight();
if (textHeight > textViewHeight) {
//Text is truncated because text height is taller than TextView height
} else {
//Text not truncated because text height not taller than TextView height
}
However this solution has some caveats :-
Firstly regarding getLineHeight() , markup within the text can cause individual lines to be taller or shorter than this height, and the layout may contain additional first- or last-line padding. See http://developer.android.com/reference/android/widget/TextView.html#getLineHeight()
Secondly , the application needs to calculate the actual height of the TextView in pixels , and (in the case of my layout) it might not be as simple as textView.getHeight() , and calculation may vary from one layout to another layout.
I would recommend avoiding LinearLayout because the actual pixel height of the TextView can vary depending on text content. I am using a RelativeLayout (see http://pastebin.com/KPzw5LYd).
Using this RelativeLayout, I can calculate my TextView height as follows :-
//Calculate the height of the TextView for layout "http://pastebin.com/KPzw5LYd"
int textViewHeight = layout1.getHeight() - button1.getHeight() - button2.getHeight();
Hope that helps,
Regards,
James
Basically, you need to calculate the size of your textview and the size of your text when the orientation mode changed. Try ViewTreeObserver.OnGlobalLayoutListener to do so.
Inside the change orientation method:
main_view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
main_view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//Calculation goes here
int text_size = getTextSize(text_view.getText().toString());
int text_view_size = text_view.getLayoutParams().width;
//Compare your text_size and text_view_size and do whatever you want here.
}
});
Here is the code of calculate the text_size:
private int getTextSize(String your_text){
Paint p = new Paint();
//Calculate the text size in pixel
return p.measureText(your_text);
}
Hope this help.
For checking whether a multiline (or not) TextView is going to be truncated, check this post.
Or, have you looked into using a scrolling textview? (marquee).. where the text will scroll by (horizontally, animated) if it is too long for a given width?
Here is an example TextView in a layout file, that has some of these characteristics:
<TextView
android:id="#+id/sometextview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:scrollHorizontally="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:freezesText="true"
android:textColor="#808080"
android:textSize="14sp"
android:text="This is a long scrolling line of text.. (etc)"/>
This extension function in Kotlin worked for me, just make sure to call it when the view is already laied out, e.g. view.post() is a good place for me;
/**
* Make sure to call this method only when view layout is finished, e.g. view.post() is a good place to check this
*/
fun TextView.isTruncated() = (lineCount * lineHeight) > height
Usage
textView.post {
if(isTruncated()) {
// Do something
}
}
Just check textView.getLineCount(), if line count > 1 then your text is multiline