Problems inflating a custom LinearLayout into a custom class that extends LinearLayout - android

I'm trying to inflate a LinearLayout containing a few different Textviews and a Button into a custom class that extends LinearLayout.
Here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#173BBC"
android:gravity="center_vertical"
android:minWidth="200dp"
android:minHeight="40dp"
android:orientation="horizontal"
android:padding="10dp"
android:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/textView12"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/compte" />
<TextView
android:id="#+id/textViewCompteT"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TextView" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/textView14"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/valeur" />
<TextView
android:id="#+id/textViewValeurT"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TextView" />
</LinearLayout>
</LinearLayout>
<Button
android:id="#+id/buttonDeleteTransaction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableTop="#android:drawable/ic_menu_delete"
android:minWidth="48dp"
android:paddingLeft="30dp"
android:paddingTop="10dp"
android:paddingRight="30dp"
android:paddingBottom="0dp"
android:textSize="0sp"
app:cornerRadius="20dp"/>
</LinearLayout>
And here is my class: (please don't take care about the names of the variables, they are bad ;) )
public class TransactionTwo extends LinearLayout {
private Context context;
private LinearLayout container;
private LinearLayout content;
private LayoutParams layoutParams;
private LayoutParams contentLayoutParams;
public TransactionTwo(Context context, Activity parent){
super(context);
activity = (Details) parent;
//here i define my layouts to make them have the fine shape.
layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(10, 10, 10, 10);
contentLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
this.setLayoutParams(layoutParams);
this.setOrientation(LinearLayout.VERTICAL);
this.setBackgroundColor(Color.RED);
container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
container.setLayoutParams(contentLayoutParams);
}
public void createViews(){
//here i try to force the display of the inflated layout (which doesn't appear on screen)
content = (LinearLayout) inflate(context, R.layout.modele_transaction2, container);
content.setVisibility(View.VISIBLE);
content.setLayoutParams(contentLayoutParams);
container.setMinimumHeight(100);
this.addView(container);
//then i find a few textviews and set their text (which works correctly even if i can't see it)...
}
#Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
}
Everything seems to work correctly (at least Android doesn't raise any error), but the only trouble is that I can see the LinearLayout "TransactionTwo" having the size of the LinearLayout that I inflate in it, but I can't see the inflated one... And when I ask for the height of content and container it always answer 0. So it is as if the inflated layout was only giving its size without appearing...
If anyone knows what is wrong in my code, that would be really appreciated because I'm stucked on this issue for a long time now ;)
Thank you!

In fact it might have been a bug of Android Studio, because I made a copy of my java class and it worked this time...

Related

FrameLayout does not display correct width

I have a layout like below ( to play media files ) :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="#+id/mediabar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="#+id/btnPlay"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="0.2"
android:text="P">
</Button>
<SeekBar
android:id="#+id/sbProgress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"/>
<TextView
android:id="#+id/txtTimeleft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00:00"
android:textSize="13sp"
android:paddingRight="10dp"/>
</LinearLayout>
</LinearLayout>
I use a class called CustomView which inherits from FrameLayout to contains the above layout.
public class CustomView extends FrameLayout
Then I will add the above layout to the CustomView on startup :
private void initItems(){
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = null;
rowView = inflater.inflate(R.layout.shadow_layout,null,false);
btnPlay = rowView.findViewById(R.id.btnPlay);
seekBar = rowView.findViewById(R.id.sbProgress);
tvTime = rowView.findViewById(R.id.txtTimeleft);
//scriptFrame = (LinearLayout) rowView.findViewById(R.id.scriptframe);
this.addView(rowView);
setUpFont();
}
And finally, in my activity, I will create and add the above class to my view like this :
shadowingView = new CustomView(context);
shadowingView.setLayoutParams(
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
scrollView.addView(shadowingView);
But the result is not what I expected, the layout wasn't MATCH_PARENT (Play button's text is not displaying also) :
Please point me where I did wrong. Thank you!
you miss the android:weightSum attribute in your linearlayout
<LinearLayout
//put the weightSum here
android:id="#+id/mediabar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="#+id/btnPlay"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="0.2"
android:text="P">
</Button>
<SeekBar
android:id="#+id/sbProgress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:layout_gravity="center"/>
<TextView
android:id="#+id/txtTimeleft"
android:layout_width="0dip"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:text="00:00:00"
android:textSize="13sp"
android:paddingRight="10dp"/>
</LinearLayout>
here is the result :
your xml code is working fine here......
SHow me the code of
<FrameLayout
......
......
/>
There might be some error in it.....
try using
shadowingView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
Thanks for the answers guys. Unfortunately none of the answers worked. But I have fixed the problem.
For some unknown reason, the scrollview is the problem, all I have to do is change from FrameLayout to ScrollView
public class CustomView extends ScrollView
And here :
shadowingView = new CustomView(context);
shadowingView.setLayoutParams(
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
// scrollView.addView(shadowingView); REMOVE THIS LINE
// topParent.addView(scrollView); AND THIS LINE
topParent.addView(shadowingView)

Need Help adding programmatically adding ToggleButton to a FrameLayout with half the layout_weight

My goal is to dynamically add a toggleButton to a frameLayout (which has it's own weight), but have the button be half the width of the frameLayout. I am able to create what I want in XML, but I'm having trouble trying to make this work programmatically.
Here's my XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/columns"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal"
android:weightSum="8">
<FrameLayout
android:id="#+id/column_1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
<View
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#android:color/background_dark" />
</LinearLayout>
<LinearLayout
android:id="#+id/buttonLayoutWrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2">
<ToggleButton
android:layout_width="0dp"
android:layout_height="360dp"
android:layout_weight="1"
android:checked="true"
android:text=""
android:textOff=""
android:textOn=""/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</LinearLayout>
Please pay particular attention to the LinearLayout with the id: buttonLayoutWrapper and it's child ToggleButton as those are what I need to add dynamically. For simplicity sake I'm only showing one column, but would repeat this for 7 more.
I tried creating a separate class that Extends LinearLayout and adds the ToggleButton thinking that I could get the weight that way, but no luck.
No matter what I do, I can't seem to get the ToggleButton to obey the layout_weight.
Below is a sample of trying to do this programmatically:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.column_1);
ToggleButton toggleButton = new ToggleButton(this);
LinearLayout.LayoutParams layoutWrapper = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 360, .5f);
toggleButton.setChecked(true);
toggleButton.setText("");
toggleButton.setTextOn("");
toggleButton.setTextOff("");
toggleButton.setLayoutParams(layoutWrapper);
frameLayout.addView(toggleButton);
}
It seems that I need to have a parent LinearLayout that sets weightSum for the layout weight to work in the XML version. However, I can't seem to figure out how to add a LinearLayout parent to this that can then be added to the FrameLayout without getting a strange:
cannot cast LinearLayout to FrameLayout
error when compiling.
Rewrite
Try the following. It adds the ToggleButton to the LinearLayout then adds the LinearLayout to the FrameLayout. I think it is what you are looking for. (Comment out the LinearLayout and ToggleButton in the XML so you can see this work.)
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
final float dpToPx = getResources().getDisplayMetrics().density;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final LinearLayout linearLayout = new LinearLayout(this);
final FrameLayout.LayoutParams frameLP =
new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
linearLayout.setLayoutParams(frameLP);
linearLayout.setId(View.generateViewId()); // API 17+ needed
linearLayout.setWeightSum(2.0f);
final ToggleButton toggleButton = new ToggleButton(this);
final LinearLayout.LayoutParams linearLP =
new LinearLayout.LayoutParams(0, (int) (360 * dpToPx), 1.0f);
toggleButton.setLayoutParams(linearLP);
toggleButton.setChecked(true);
toggleButton.setText("");
toggleButton.setTextOn("");
toggleButton.setTextOff("");
linearLayout.addView(toggleButton);
final FrameLayout frameLayout = (FrameLayout) findViewById(R.id.column_1);
frameLayout.addView(linearLayout);
}
}

Layout weight not working as intended

I have a slight problem getting my layout_weight to work. I am creating a custom bottomBar. But i cant make it to stretch as i want it to.
Bottom Bar View
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bottom_bar_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/bottom_bar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="4"
android:orientation="horizontal"/>
</RelativeLayout>
This is the big container i am adding my buttons (items) to.
Bottom Bar Item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<android.support.v7.widget.AppCompatImageView
android:id="#+id/bottom_bar_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/arrow_up_float"/>
<TextView
android:id="#+id/bottom_bar_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEXT"/>
</LinearLayout>
This is my items that i add dynamically to the view. But somehow the view is not stretched properly.
But when i hardcode it in. It works. So could it be that layout weight does not work dynamically?
How i add the views (items)
private void updateItems(final List<BottomBarTab> bottomBarTabs) {
if (bottomBarTabs.size() < TABS_COUNT) {
throw new RuntimeException("Not enough buttons for bottomBar");
}
for (int i = 0; i < TABS_COUNT; i++) {
bottomBarTabs.get(i).setOnClickListener(this);
bottomBarTabs.get(i).prepareLayout();
container.addView(bottomBarTabs.get(i));
}
}
Screenshot
LayoutWeight is given to inner components of layout only not on parent Linearlayout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:weightSum="2">
<android.support.v7.widget.AppCompatImageView
android:id="#+id/bottom_bar_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="#android:drawable/arrow_up_float"/>
<TextView
android:id="#+id/bottom_bar_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TEXT"/>
</LinearLayout>
public void prepareLayout() {
View view = inflate(getContext(), R.layout.bottom_bar_item,this);
LinearLayout.LayoutParams params =
new LayoutParams(0,LayoutParams.MATCH_PARENT,LAYOUT_WEIGHT);
view.setLayoutParams(params);
if(backgroundColor != null) {
view.setBackgroundColor(backgroundColor);
}
TextView titleText = (TextView) view.findViewById(R.id.bottom_bar_item_text);
titleText.setText(title);
AppCompatImageView imageView = (AppCompatImageView) view.findViewById(R.id.bottom_bar_item_icon);
imageView.setImageResource(iconResId);
}
I changed in my prepareLayout function and put new layoutParams. Because somehow after inflation. The view ignores the weight that was set to it. So i had to force it by code. Maybe this is a android bug?

WRAP_CONTENT not working after dynamically adding views

I'm trying to create a fragment that lays out a series of custom views dynamically. The main content for this layout is a RelativeLayout nested in a LinearLayout (to center it horizontally), nested in a ScrollView.
The RelativeLayout has a few TextViews and a 9 patch ImageView that is meant to scale with the dynamically added custom views. However, the image (achievements_bgImageView below) is ending up as the size of the screen, and is not respecting the size of its parent RelativeLayout even after I've added the appropriate amount of custom views. The image scales fine when I manually set the size of achievements_mainLayout (see the commented out lines below), but does nothing if I try to let that RelativeLayout's wrap_content handle its own sizing.
The ScrollView IS respecting the size of the RelativeLayout, as all the content is present, it's simply the imageView that isn't stretching to match the content at this point.
Any help would be appreciated... My manual calculations don't seem to be good enough to account for different devices, despite the fact I'm accounting for screen density and I'm manually forcing the RelativeLayout to a constant width.
It's worth noting that the measured size of the RelativeLayout is always equal to the height of the screen, regardless of whether or not the sum of its content is greater or less than that height. So, essentially, WRAP_CONTENT is simply not doing what it's supposed to be doing. I have nothing referencing any edge of of the RelativeLayout, so circular dependencies shouldn't be a problem.
fragment_achievements.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<RelativeLayout
android:layout_width="320dp"
android:layout_height="wrap_content"
android:id="#+id/achievements_mainLayout">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/achievements_bgImageView"
android:src="#drawable/bkg_achievements9"
android:adjustViewBounds="true"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_centerHorizontal="true"
android:scaleType="fitXY"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name Field"
android:id="#+id/achievements_nameTextView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="28dp"
android:layout_marginTop="30dp"/>
<ImageView
android:layout_width="52dp"
android:layout_height="52dp"
android:id="#+id/achievements_avatarImageView"
android:layout_below="#+id/achievements_nameTextView"
android:layout_alignLeft="#+id/achievements_nameTextView"
android:src="#drawable/achieve_avatar"
android:layout_marginTop="5dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Top Moment:"
android:id="#+id/textView2"
android:layout_alignBottom="#+id/achievements_avatarImageView"
android:layout_toRightOf="#+id/achievements_avatarImageView"
android:layout_marginBottom="16dp"
android:layout_marginLeft="4dp"
android:textSize="12dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Me Overall:"
android:id="#+id/textView3"
android:layout_alignTop="#+id/textView2"
android:layout_alignLeft="#+id/textView2"
android:layout_marginTop="16dp"
android:textSize="12dp"/>
<TextView
android:layout_width="52dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="153"
android:id="#+id/achievements_totalPointsTextView"
android:gravity="center"
android:layout_alignTop="#+id/achievements_avatarImageView"
android:layout_alignRight="#+id/achievements_bgImageView"
android:layout_alignEnd="#+id/achievements_bgImageView"
android:layout_marginRight="31dp"
android:textColor="#f7a033"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Moment"
android:id="#+id/achievements_topMomentTextView"
android:layout_alignTop="#+id/textView2"
android:layout_toRightOf="#+id/textView2"
android:layout_marginLeft="5dp"
android:textSize="12dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="153"
android:id="#+id/achievements_overallTextView"
android:layout_alignTop="#+id/textView3"
android:layout_toRightOf="#+id/textView3"
android:layout_marginLeft="5dp"
android:textSize="12dp"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>
AchievementFragment.java
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = null;
fragmentView = inflater.inflate(R.layout.fragment_achievements, container, false);
ImageView avatarImageView = (ImageView)fragmentView.findViewById(R.id.achievements_avatarImageView);
...
// Basic Achievement List Setup
RelativeLayout mainLayout = (RelativeLayout)fragmentView.findViewById(R.id.achievements_mainLayout);
AchievementRow currentRow = null;
List achievementTypeList = CampaignManager.sharedManager().sortedAchievementTypeList();
int achievementCount = achievementTypeList.size();
for (int i = 0; i < achievementCount; i++) {
AchievementType achievementType = (AchievementType)achievementTypeList.get(i);
// Every third achievement creates a new row.
if ((i % 3) == 0) {
AchievementRow row = (AchievementRow)inflater.inflate(R.layout.widget_achievementrow, null);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (currentRow == null) {
layoutParams.addRule(RelativeLayout.BELOW, avatarImageView.getId());
layoutParams.setMargins(10, 70, 10, 0);
} else {
layoutParams.addRule(RelativeLayout.BELOW, currentRow.getId());
layoutParams.setMargins(10, 10, 10, 0);
}
layoutParams.addRule(RelativeLayout.ALIGN_LEFT, backgroundImageView.getId());
layoutParams.addRule(RelativeLayout.ALIGN_RIGHT, backgroundImageView.getId());
row.setLayoutParams(layoutParams);
row.setId(i+1);
mainLayout.addView(row);
currentRow = row;
}
// Now setup the Button
AchievementButton achievementButton = currentRow.buttonForIndex(i % 3);
achievementButton.achievementType = achievementType;
achievementButton.setOnClickListener(achievementButtonListener);
achievementButton.setVisibility(View.VISIBLE);
CacheManager.sharedManager().fetchAchievementThumbnail(getActivity(), achievementButton, achievementType);
}
// This is the manual scaling of mainLayout
// float scale = getResources().getDisplayMetrics().density;
// float headerHeight = scale * 150.0f;
// float rowHeight = scale * 78.0f;
// ViewGroup.LayoutParams mainLayoutParams = mainLayout.getLayoutParams();
// mainLayoutParams.height = (int)(headerHeight + (Math.ceil(achievementCount / 3.0) * rowHeight));
return fragmentView;
}
Try calling requestLayout on the children.
I recently had a similar problem and was similarly frustrated that things like invalidate and requestLayout seemed to do nothing. What I didn't understand is that requestLayout doesn't propagate down to its children; it propagates up to its parents. To re-measure something that was previously measured, I had to call requestLayout on the View that changed rather than the View I actually wanted to resize.
Android does NOT refresh layout of views with "wrap_content" once it has been displayed.
So if you add a child view, or modify the content dynamically, you're screwed.
I do agree that this is a nightmare and a real flaw in Android UI!
To solve that, I've written a static class that recomputes the sizes and forces the update of the layout for the views with "wrap_content"
The code and instructions to use are available here:
https://github.com/ea167/android-layout-wrap-content-updater
Enjoy!
A simple way to update the size of a View with WRAP_CONTENT is change the visibility to GONE and back to the old visibility.
int visibility = view.getVisibility();
view.setVisibility(View.GONE);
view.setVisibility(visibility);
TESTED ON ANDROID JELLY BEAN IN 2014
MAY NOT WORK ON NEWER ANDROID VERSIONS
Ok, I solved this by manually measuring the RelativeLayout immediately after adding all the views and setting the mainLayoutParams height explicitly. I wish I was smarter and knew why it wasn't automatically doing this correctly in the first place, but oh well.
...
mainLayout.measure(0, 0);
ViewGroup.LayoutParams mainLayoutParams = mainLayout.getLayoutParams();
mainLayoutParams.height = mainLayout.getMeasuredHeight() + 10;
...
I encountered same issue when working with LinearLayout which has wrap_content and one child as TextView match_parent.
To fix this I did this:
Remove the TextView programatically and then add it again.
linearLayout.removeView(textView)
linearLayout.addView(textView)
I know it sounds stupid but it works.
In my case calling invalidate didn't work, only this worked.
Depending on your implementation you need to take care of view index inside its parent
You are getting this problem because you set your layout first and then add its content dynamically.
You are telling the layout to wrap to the content that is not yet their. Try using your layout inflater after you have grabbed your content
You should use NestedScrollView Instead of simple scrollview.
here is my sample Activity Layout code
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0ECE6"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabIndicatorHeight="6dp"
android:layout_marginTop="-10dp"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<wsit.rentguru.utility.CustomViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
here is code for custom viewpager
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
setup function for viewpager in the activity
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new SampleFragment(), " ");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
here is the sample SampleFragment layout code
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F0ECE6"
android:fillViewport="true"
android:scrollbars="vertical"
android:animateLayoutChanges="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0ECE6"
android:focusableInTouchMode="true"
>
<Spinner
android:id="#+id/product_category"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#drawable/edittext_rectangle_box"
android:gravity="center|left"
android:textSize="14sp"
android:paddingLeft="10dp"
android:drawableRight="#drawable/ic_down_arrow"
/>
<Spinner
android:id="#+id/product_sub_category"
android:layout_below="#+id/product_category"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center|left"
android:visibility="gone"
android:paddingLeft="10dp"
android:background="#android:color/white"
android:drawableRight="#drawable/ic_down_arrow"
/>
<EditText
android:id="#+id/product_title"
android:layout_below="#+id/product_sub_category"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="15dp"
android:background="#android:color/white"
android:hint="PRODUCT TITLE"
android:singleLine="true"
android:imeOptions="actionDone"
android:layout_width="match_parent"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_height="40dp" />
<LinearLayout
android:id="#+id/availability_layout"
android:layout_below="#+id/product_title"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/availability"
android:textStyle="bold"
android:paddingBottom="10dp"
android:textSize="14sp"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<Button
android:id="#+id/from"
android:background="#android:color/white"
android:hint="FROM"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textStyle="normal"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"/>
<Button
android:id="#+id/to"
android:background="#android:color/white"
android:hint="TO"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/product_location_layout"
android:layout_below="#+id/availability_layout"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/product_location"
android:textStyle="bold"
android:paddingBottom="10dp"
android:textSize="14sp"
/>
<Spinner
android:id="#+id/state_spinner"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#drawable/edittext_rectangle_box"
android:gravity="center|left"
android:textSize="14sp"
android:layout_marginBottom="10dp"
android:drawableRight="#drawable/ic_down_arrow"
android:paddingLeft="10dp"
/>
<EditText
android:id="#+id/area"
android:background="#android:color/white"
android:hint="Area"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="match_parent"
android:layout_height="40dp"
android:singleLine="true"
android:imeOptions="actionNext"
android:layout_marginBottom="10dp"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<EditText
android:id="#+id/zipCode"
android:background="#android:color/white"
android:hint="Zip Code"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:singleLine="true"
android:imeOptions="actionNext"
android:layout_marginRight="10dp"/>
<EditText
android:id="#+id/city"
android:background="#android:color/white"
android:hint="City"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:singleLine="true"
android:imeOptions="actionDone"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="#+id/tab1_next"
android:layout_width="150dp"
android:layout_height="40dp"
android:text="NEXT"
android:layout_below="#+id/product_location_layout"
android:layout_margin="20dp"
android:layout_alignParentRight="true"
android:background="#color/next_button"
android:textColor="#android:color/white"
android:layout_marginBottom="20dp"
/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
Set the layout parameters again(width and height), right after adding the view. This worked for me.
if the parent View is a FrameLayout, then do something like this:
ImageView view = (ImageView) LayoutInflater.from(activity).inflate(R.layout.image_object_view, null);
imageObjectsHolder.addView(view);
FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.setLayoutParams(param);
My problem was fixed by seting layout_width to some specific dp.
So changing from "wrap content" or "match parent"
to
android:layout_width="300dp"
will fix it, but i know it's not solution for all cases. But maybe you have some parent width, so you can apply the width to the textview.
height leave with wrap_content, and it will work.

Android: Last line of textview cut off

I have a horizontal LinearLayout containing a TextView followed by a Spinner next to it. This LinearLayout is dynamically inflated multiple times in a fixed vertical LinearLayout contained within a RelativeLayout.
The problem is that since I switched from Theme.light to Theme.holo.light, the last line of the TextView gets cut in half. This happens when the dynamic text is long and spans more than one row.
I have been able to fix this by adding bottom padding to the horizontal LinearLayout containing the TextView and Spinner.
This does not feel like a fix, but more of a hack. Can someone please give me some advice on how to properly fix this?
I have also read some other questions, but none seem to help.
Horizontal Linear layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/textView1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="TextView"/>
<Spinner
android:id="#+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Relative layout where above layout is dynamically inflated at Linear Layout with id ll2_7:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:id="#+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/relLayoutButtonNext"
android:layout_below="#id/textView1" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" >
<TextView
android:id="#+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="30dp"
android:text="2.7" />
<TextView
android:id="#+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_toRightOf="#id/textView10"
android:text="#string/question2_7" />
<LinearLayout
android:id="#+id/ll2_7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView11"
android:layout_below="#+id/textView11"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
EDIT:
Here is the complete layout xml for above:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/textView1"
style="#style/question_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="#string/question2_header" />
<RelativeLayout
android:id="#+id/relLayoutButtonNext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/bottomBar"
android:paddingBottom="3dp"
android:paddingLeft="50dp"
android:paddingRight="50dp"
android:paddingTop="3dp" >
<Button
android:id="#+id/buttonNext"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:onClick="nextStep"
android:text="Next Section"
android:textSize="20sp" />
<Button
android:id="#+id/buttonPrevious"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:onClick="previousStep"
android:text="Previous Section"
android:textSize="20sp" />
</RelativeLayout>
<ScrollView
android:id="#+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/relLayoutButtonNext"
android:layout_below="#id/textView1" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" >
<TextView
android:id="#+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="30dp"
android:text="2.7" />
<TextView
android:id="#+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_toRightOf="#id/textView10"
android:text="#string/question2_7" />
<LinearLayout
android:id="#+id/ll2_7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView11"
android:layout_below="#+id/textView11"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView10"
android:layout_below="#+id/ll2_7"
android:text="2.8" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_7"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_8" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView3"
android:layout_below="#+id/textView3"
android:layout_marginBottom="20dp"
android:orientation="vertical" >
</LinearLayout>
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView2"
android:layout_below="#+id/ll2_8"
android:text="2.9" />
<TextView
android:id="#+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_8"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_9" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView5"
android:layout_toRightOf="#+id/textView10"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
<TextView
android:id="#+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView4"
android:layout_below="#+id/ll2_9"
android:text="2.10" />
<TextView
android:id="#+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_9"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_10" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView7"
android:layout_marginBottom="20dp"
android:layout_toRightOf="#+id/textView10"
android:orientation="vertical" >
</LinearLayout>
<TextView
android:id="#+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView6"
android:layout_below="#+id/ll2_10"
android:text="2.11" />
<TextView
android:id="#+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_10"
android:layout_toRightOf="#+id/textView10"
android:text="#string/quesiton2_11" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView9"
android:layout_below="#+id/textView9"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
<TextView
android:id="#+id/textView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView8"
android:layout_below="#+id/ll2_11"
android:text="2.11.1" />
<TextView
android:id="#+id/textView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ll2_11"
android:layout_toRightOf="#+id/textView10"
android:text="#string/question2_11_1" android:layout_marginBottom="10dp"/>
<LinearLayout
android:id="#+id/ll2_11_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView13"
android:layout_toRightOf="#+id/textView10"
android:orientation="vertical" android:layout_marginBottom="20dp">
</LinearLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
I applied a LayoutGravity to the TextView item:
android:layout_gravity="fill"
I've encountered the same cut-off issue as shown at the screenshot. It is caused by the baseline alignment in the horizontal LinearLayout. TextView and Spinner have different baselines due to font size difference. To fix the issue it is needed to disable baseline alignment for the layout by setting:
android:baselineAligned="false"
or in the code:
layout.setBaselineAligned(false);
I had the same problem, and found that simply adding
android:includeFontPadding="false"
the final line of text no longer had its descenders clipped.
I added some dummy space after text by adding
textView.setText(firstString+"\n");
I tried all other solution.But this was the only solution worked for me
I found a different solution by extending TextView and adding a custom Class like this:
public class AdaptingTextView extends TextView {
public AdaptingTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public AdaptingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AdaptingTextView(Context context) {
super(context);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// set fitting lines to prevent cut text
int fittingLines = h / this.getLineHeight();
if (fittingLines > 0) {
this.setLines(fittingLines);
}
}
}
Put the problematic textview inside a framelayout. I think the text view is not calculated correctly because of the sibling view, Spinner.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:layout_width="150dp"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="TextView"/>
</FrameLayout>
<Spinner
android:id="#+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
When this occurs, you should ensure that the TextView is not growing larger than it's container -
If a TextView is set to wrap_content and it's container (or an ancestor container) doesn't leave room for the TextView to grow into it can be occluded.
If that's not the case, it's also possible the onMeasure() of the TextView sometimes doesn't correctly measure the tails of letters, non-latin characters or the effects from text being italic. You can correct for this by setting a global style for your TextView so it will be picked up without needed to change your entire code base:
Ensure that you're application/activities use a custom theme like so:
<style name="Custom" parent="#android:style/Theme.Light">
<item name="android:textViewStyle">#style/Custom.Widget.TextView</item>
</style>
<style name="Custom.Widget.TextView" parent="#android:style/Widget.TextView">
<item name="android:gravity">fill</item>
<item name="android:padding">1sp</item>
</style>
The answer by #Rynadt was really helpful in getting to the above stage. Setting the gravity of the Text inside the View ensures on some devices that occlusion never takes place (The text is correctly fitted inside the view), on others a helping hand with padding of an sp value, ensures that the tails et al are accounted for with a TextSize specific value.
My solution was close to the accepted one, but I had to change it to
android:layout_gravity="fill_vertical"
instead. Otherwise the other rows would have been stretch as well with added line breaks at random places. For example, the biggest row had 4 lines, so another row was changed from
this is a testphrase
to
thi
s is
a testph
rase
try with removing android:paddingBottom="20dp"
from
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" >
getViewTreeObserver().addOnGlobalLayoutListener does not work in a recycler view. If you're using a recycler, use View.addOnLayoutChangeListener:
I found that the ellipsizing I defined for textView in xml was not always reflected so I programmatically set it before reassigning the text property. This worked for me.
textView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
textView.removeOnLayoutChangeListener(this);
float lineHeight = textView.getLineHeight();
int maxLines = (int) (textView.getHeight() / lineHeight);
if (textView.getLineCount() != maxLines) {
textView.setLines(maxLines);
textView.setEllipsize(TextUtils.TruncateAt.END);
// Re-assign text to ensure ellipsize is performed correctly.
textView.setText(model.getText());
}
}
});
If you have this problem and your TextView is inside a RelativeLayout, try switching the RelativeLayout for a LinearLayout.
That fixed the problem for me
You can use a global layout listener for a TextView in any type of ViewGroup.
final TextView dSTextView = (TextView)findViewById(R.id.annoyingTextView);
dSTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
dSTextView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
float lineHeight = dSTextView.getLineHeight();
int maxLines = (int) (dSTextView.getHeight() / lineHeight);
if (dSTextView.getLineCount() != maxLines) {
dSTextView.setLines(maxLines);
}
}
});
You can read more about it here
I know it's so late, but this is work like charm for me.
add this code to your textview
android:ellipsize="marquee"
android:layout_weight="1"
I think there is very little you can do to get this working by altering the layouts. As I have found that some methods work only in some cases. I think it depends on the entire layout hierarchy and is not a one-size-fits-all solution. I have also noticed that it happens especially when you have a different font that you want to set to the TextView.
A sure shot method that I have experimented and tested is that you can set the font attributes in code after the view is inflated. I am assuming that you have a font in the assets/fonts folder that you want to you.
For eg in a Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_view, container, false);
TextView tv = (TextView)view.findViewById(R.id.text_view);
tv.setText("Insert text that needs to be displayed");
AssetManager assetManager = getContext().getAssets();
Typeface typeFace = Typeface.createFromAsset(assetManager, "Fonts/OpenSans-Light.ttf");
tv.setTypeface(typeFace , 0); // 0 is normal font
tv.setPadding(10, 0, 10, 0); // This is not mandatory
}
And in an Activity:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(Resource.Layout.main_activity);
TextView tv = (TextView)this.findViewById(R.id.text_view);
tv.setText("Insert text that needs to be displayed");
AssetManager assetManager = getContext().getAssets();
Typeface typeFace = Typeface.createFromAsset(assetManager, "Fonts/OpenSans-Light.ttf");
tv.setTypeface(typeFace , 0); // 0 is normal font
tv.setPadding(10, 0, 10, 0); // This is not mandatory
}
I have this same problem, and its very annoying.
It only happens with Arabic text.
If you make the label multi-line and adding a \n at the end of your string, it would fix it, but the problem is that there would be a big gap between this label and the object below it, due to the fact that this field now has a new empty line below it.
A custom control can be done to get around that. But overall, this is an annoying bug.
Best workaround for this is to add a dummy View of desired height (i.e. this will add padding itself) at the bottom of your view.
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" >
<View
android:layout_width="match_parent"
android:layout_height="30dp"/>
</TableRow>
Like in my case I added one more table row at the bottom of the view. Hope this could help someone.
Add padding to the bottom of the text view:
android:paddingBottom="24dp"
I had the same problem and found a handy solution. I get the number of lines of the TextView after rendering and set the height according to the number of lines. Here is the code.
TextView textView = (TextView) layout.findViewById(R.id.textView);
textView.setText(this.text);
textView.post(new Runnable() {
#Override
public void run() {
int linesCount = textView.getLineCount();
textView.setLines(linesCount);
}
});
For me, this solution worked like a charm.
The height and width of my outermost layout was set dynamically, so the TextView contained within got it's text cut even if I set android:maxLines in my xml (for different devices it was behaving differently).
After trying out different methods, finally I got a solution that fixed my issue.
Textview:
public class CustomTextView extends androidx.appcompat.widget.AppCompatTextView {
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTextView(Context context) {
super(context);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// set fitting lines to prevent cut text
int fittingLines = h / this.getLineHeight();
if (fittingLines > 0) {
this.setLines(fittingLines);
this.setEllipsize(TextUtils.TruncateAt.END);
}
}
}
xml:
<com.myproject.android.customviews.CustomTextView
android:id="#+id/tv_partner_description"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top"
android:textColor="#color/white"
android:textSize="#dimen/text_small_medium" />
create theme as for particular language like style-ar which cut-off textview:
<style name="EnnodaCustomTextView" parent="Widget.AppCompat.TextView">
<item name="android:paddingTop">1dp</item>
<item name="android:paddingBottom">1dp</item>
</style>
Apply it in you AppTheme to reflect in overall app for padding bottom, as :
<item name="android:textViewStyle">#style/EnnodaCustomTextView</item>
Note : create same style name in default styles.xml with no item tags for padding..(where no need of extra padding )
I finally fixed it!
I try to add String to the TextView in Service and then call scrollTo(), the last line be cut off!
The scrollTo() should be call in "Runnable", like:
private ScrollView mScrollView;
public void scrollToBottom()
{
mScrollView = (ScrollView) findViewById(R.id.debug_textview_scrollview);
mScrollView.post(new Runnable()
{
public void run()
{
mScrollView.fullScroll(View.FOCUS_DOWN);
}
});
}
I think it because in the monent of call scrollTo() in service, the update of TextView is not ready.

Categories

Resources