When a single line of text is too long, how can I make TextView always display the last part of it?
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/display_sum"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="0.00"
android:text=""
android:textSize="50sp"
android:textStyle="bold"
android:layout_gravity="right"
android:gravity="right"/>
</HorizontalScrollView>
I want this:
not this:
I think so the below code may help to you.
HorizontalScrollView horizontalScrollView = (HorizontalScrollView) findViewById(R.id.YourIdName)
horizontalScrollView.fullScroll(HorizontalScrollView.FOCUS_FORWARD);
//Observe for a layout change
ViewTreeObserver viewTreeObserver = horizontalScrollView .getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
horizontalScrollView .fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
});
}
}
In that case you have to set
android:ellipsize="start"
android:singleLine="true"
your textview should like
<TextView
android:id="#+id/textView"
android:ellipsize="start"
android:singleLine="true"
android:text="very big text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Related
I want to show a notification counter like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:padding="#dimen/_5sdp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:alpha=".5"
android:id="#+id/gvIcon"
android:src="#drawable/ic_person_reading"
android:scaleType="centerCrop"
android:layout_width="#dimen/_70sdp"
android:layout_height="#dimen/_70sdp" />
<LinearLayout
android:id="#+id/llTexts"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
style="#style/gridItemsText"
android:id="#+id/gvText"
android:text="Guten Morgen"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/partNoticeTooltip"
android:orientation="vertical"
android:background="#drawable/bg_tooltip_red"
android:layout_width="#dimen/tooltipWH"
android:layout_height="#dimen/tooltipWH">
<TextView
android:id="#+id/tvCounter"
android:text="4"
android:textColor="#color/white"
android:textSize="#dimen/h6"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
Which has an output like this:
This is my expectation, but with dynamic way. So I wrote this in the setOnItemClickListener of my GridView:
View tooltip = context.getLayoutInflater().inflate(R.layout.part_tooltip, null);
TextView tvCounter = (TextView) tooltip.findViewById(R.id.tvCounter);
tvCounter.setText("" + counter);
LinearLayout llText = (LinearLayout) view.findViewById(R.id.llTexts);
llText.addView(tooltip);
the part_tooltip has exactly the same code but with another layout. And here is the output:
The red layout does not being displayed with full width. What am I missing?
You need to use a global layout listener and also the view tree observer:
ViewTreeObserver mVTO = parentLayoutOfTheViewAddedDynamically.getViewTreeObserver();
mVTO.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if(viewAddedDynamically != null){
int viewWidth = viewAddedDynamically.getWidth();
// any operation based on viewWidth is to be done here
}
}
});
I have an OnClickListener that listens to Button A clicks. I also have 2 TextViews below the Button.
I want that on every click on Button A, the 2 TextViews will switch their places between them, like this:
Before clicking:
TextView A
TextView B
After clicking:
TextView B
TextView A
How can I do it? Is there a special function that meant to do that? or some kind of a trick? Thanks!
actvity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="start"
tools:context="com.intap.tof.MainActivity">
<TextView
android:id="#+id/txtA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="20dp"
android:visibility="visible"/>
<TextView
android:id="#+id/txtB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_below="#+id/txtA
android:layout_marginTop="83dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="visible"
android:textSize="20dp" />
</RelativeLayout>
MainActivity.java:
txtA = (TextView) findViewById(R.id.txtA);
txtB = (TextView) findViewById(R.id.txtB);
float mAX = txtA.getX();
float mAY = txtA.getY();
float mBX = txtB.getX();
float mBY= txtB.getY();
txtA.setX(mBX);
txtA.setY(mBY);
txtB.setX(mAX);
txtB.setY(mAY);
Trick is changing the x and y axis of both views :
Your xml code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="start"
tools:context="com.intap.tof.MainActivity">
<TextView
android:id="#+id/txtA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="20dp"
android:text="A"
android:tag="A"
android:clickable="true"
android:visibility="visible"/>
<TextView
android:id="#+id/txtB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_below="#+id/txtA"
android:text="B"
android:tag="B"
android:clickable="true"
android:layout_marginTop="83dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="visible"
android:textSize="20dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="switch"
android:id="#+id/btn1"
android:onClick="onClickButton"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Java Code :
public class MainActivity extends Activity {
TextView txtA,txtB;
boolean _isOnTxtA;
Button btn1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtA = (TextView)findViewById(R.id.txtA);
txtB = (TextView)findViewById(R.id.txtB);
btn1 = (Button)findViewById(R.id.btn1);
}
public void onClickButton(View v)
{
float mPos1x,mPos1y,mPos2x,mPos2y;
mPos1x = txtB.getX();
mPos1y = txtB.getY();
mPos2x = txtA.getX();
mPos2y= txtA.getY();
if(_isOnTxtA)
{
txtB.setX(mPos2x);
txtB.setY(mPos2y);
txtA.setX(mPos1x);
txtA.setY(mPos1y);
_isOnTxtA = false;
}
else
{
txtB.setX(mPos2x);
txtB.setY(mPos2y);
txtA.setX(mPos1x);
txtA.setY(mPos1y);
_isOnTxtA= true;
}
}
}
View.bringToFront method may be useful.
Where your layout is like:
<LinearLayout>
<TextView A>
<TextView B>
</LinearLayout>
To call bringToFront on TextView A will bring it front (the last position in the parent LinearLayout).
<LinearLayout>
<TextView B>
<TextView A>
</LinearLayout>
For more detailed example, below is layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/text_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="#+id/text_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/text_a" />
<TextView
android:id="#+id/text_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/text_b" />
</LinearLayout>
In your OnClickListener (in your Activity) call:
View textViewA = findViewById(R.id.text_a);
textViewA.bringToFront();
This should work.
Toggling behavior can be achieved by this application. For example:
ViewGroup textHolder = (ViewGroup) findViewById(R.id.text_holder);
textHolder.getChildAt(0).bringToFront();
ViewGroup.getChildAt(0) always returns the first child of the ViewGroup. So everytime you call bringToFront on the first child will be bring to front.
All previous answers do not work because you use a relative layout where a linear layout will suffice.
If you have to go RelativeLayout, do the following in your click listener
TextView textA = (TextView) findViewById(R.id.txtA);
TextView textB = (TextView) findViewById(R.id.txtB);
RelativeLayout.LayoutParams textALayoutParams = (RelativeLayout.LayoutParams) textA.getLayoutParams();
textALayoutParams.addRule(RelativeLayout.BELOW, R.id.txtB);
textA.setLayoutParams(textALayoutParams);
RelativeLayout.LayoutParams textBLayoutParams = (RelativeLayout.LayoutParams) textB.getLayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textBLayoutParams.removeRule(RelativeLayout.BELOW);
} else {
textBLayoutParams.addRule(RelativeLayout.BELOW,0);
}
textB.setLayoutParams(textBLayoutParams);
This will place A under B. You can do the same for reversing.
It's the first time I post on this forum, hope it's gonna be fine :)
I'm developping an Android App for public transportation in my city.
Here is what I have
[ |short destination ||next departure| ]
[ |way too long dest...||next departure| ]
Here is what I want:
[ |short destination||next departure| ]
[ |way too long dest...||next departure| ]
Here is a more complete example: s28.postimg.org/5gejnvfd9/actual2.png
Weird coloured backgrounds are just here to easily identify layouts/textviews. You can also ignore the brown line (which is ok).
Basically, I want to have the destination [red background] which have a variable length, and on its right, I want the first departure time [green background]. Everything on one line.
I need to always have the first departure information fully displayed (nowrap). The destination could be wrapped with an ellipsis (...).
[Optional question, how to replace the ellipsis '...' with '.' ?]
Here is the best working code I have so far:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtTitleDestination"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/txtTitleFirstDeparture"
android:background="#FF0000"
android:ellipsize="end"
android:maxLines="1"
android:padding="0dp"
android:scrollHorizontally="true"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="#+id/txtTitleFirstDeparture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_alignParentRight="true"
android:background="#00FF00"
android:ellipsize="none"
android:maxLines="1"
android:padding="0dp"
android:textSize="18sp"
android:textStyle="bold"
/>
</RelativeLayout>
I've tried TableLayout and LinearLayour instead of the RelativeLayout, but with no success :(
Any idea how I could do that?
Thanks in advance!
Louloox
[SOLVED]
Just have to lightly modify the valbertos answer:
titleDestination.post(new Runnable() {
#Override
public void run() {
int widthTextViewDeparture = measureTextWidthTextView(titleFirstTime, pContext);
int widthTextViewDestination = titleDestination.getWidth();
int widthTextViewParent = rl_parent.getWidth();
if(widthTextViewDestination + widthTextViewDeparture > widthTextViewParent) {
titleDestination.setWidth(widthTextViewParent - widthTextViewDeparture);
titleDestination.setEllipsize(TruncateAt.END);
titleDestination.setHorizontallyScrolling(true);
}
}
});
Setting the Ellipsis only if necessary makes the text properly truncated.
Before:
Lingolsheim Thiergaten --> Lingolsheim... [1'23"] 21h23
With the modification:
Lingolsheim Thiergaten --> Lingolsheim Thi... [1'23"] 21h23
Thanks again :)
You don't need do it programmatically, ConstraintLayout is a magic!
Just use this code
app:layout_constraintHorizontal_bias="0" align view left
app:layout_constrainedWidth="true" to wrap left text
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:padding="8dp">
<TextView
android:id="#+id/leftText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
app:layout_constrainedWidth="true"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintEnd_toStartOf="#id/rightText"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="|short destination|" />
<TextView
android:id="#+id/rightText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/leftText"
app:layout_constraintTop_toTopOf="parent"
tools:text="|next departure|" />
</androidx.constraintlayout.widget.ConstraintLayout>
Here is result
I found a way to do it using Linear Layout, the trick is not to forget width="wrap_content" for the linearLayout, hope it can help.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true" />
To do what you are asking for, you must adjust the width of the first view dynamically based on the text width of the second view.
//Code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
final TextView tv_1 = (TextView) findViewById(R.id.tv_1);
tv_1.post(new Runnable() {
#Override
public void run() {
View rl_parent = findViewById(R.id.rl_parent);
TextView tv_2 = (TextView) findViewById(R.id.tv_2);
int widthTextView2 = measureTextWidthTextView(tv_2);
if(tv_1.getWidth() + widthTextView2 > rl_parent.getWidth()) {
tv_1.setWidth(tv_1.getWidth() - widthTextView2);
}
}
});
}
private int measureTextWidthTextView(TextView textView) {
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(getScreenWidth(), View.MeasureSpec.AT_MOST);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
textView.measure(widthMeasureSpec, heightMeasureSpec);
return textView.getMeasuredWidth();
}
private int getScreenWidth() {
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size.x;
}
//Layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/rl_parent"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#348D63">
<TextView
android:id="#+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#BD160B"
android:gravity="center_vertical"
android:maxLines="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="Elsau Elsau Elsau Elsau Elsau Elsau Elsau"
android:textStyle="bold" />
<TextView
android:id="#+id/tv_2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toRightOf="#+id/tv_1"
android:gravity="center_vertical"
android:minWidth="50dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="[11:30 14:23]"
android:textStyle="bold" />
</RelativeLayout>
<!-- Rest of the layout -->
</LinearLayout>
Use android:maxLines="1" instead of android:singleLine="true" to get rid off the ugly dots -as I did in my example.
Also, I recommend you to use include for the "time" section, instead of repeating the TextViews twice. I’ve just done it like that to keep simple the example.
Maybe you should use a LinearLayout instead of RelativeLayout and use the layout_weight attribute.
<LinearLayout android:orientation="horizontal" ...>
<TextView android:id="#+id/txtTitleDestination" android:layout_width="wrap_content" ... />
<TextView android:id="#+id/txtTitleFirstDeparture" android:layout_width="0dp" android:layout_weight="1" ... />
</LinearLayout>
I am trying to show Dynamic TableView with the help of Listview and Adapter. I am setting Shape drawable for border.
Logically I m trying to get heighest Height among childs of the row and then setting that height to all child views.
For that I used addOnGlobalLayoutListener , but Its called only once.
Let me know How can I achieve as Table.
I want to achieve Table , but as you can see Borders are not aPParing Proerly. Refer http://i.stack.imgur.com/NZyrc.png
Using Listview with Adapter
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final viewHoler holder;
if (convertView == null) { // if it's not recycled, initialize some attributes
convertView = inflater.inflate(R.layout.inflateordertakingproductview, null);
holder = new viewHoler();
holder.tvproductName=(TextView)convertView.findViewById(R.id.tvitem);
holder.tvprice=(TextView)convertView.findViewById(R.id.tvprice);
holder.edqty=(EditText)convertView.findViewById(R.id.edqty);
holder.edfree=(EditText)convertView.findViewById(R.id.edfree);
convertView.setTag(holder);
} else {
holder=(viewHoler)convertView.getTag();
}
ViewTreeObserver vto = holder.tvproductName.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onGlobalLayout() {
int height=0;
Log.v("Name Height",""+holder.tvproductName.getHeight());
Log.v("Price Height",""+holder.tvprice.getHeight());
Log.v("Edqty Height",""+holder.edqty.getHeight());
Log.v("Edfree Height",""+holder.edfree .getHeight());
android.view.ViewGroup.LayoutParams _lP=holder.tvproductName.getLayoutParams();
_lP.height=LayoutParams.WRAP_CONTENT;
holder.tvproductName.setLayoutParams(_lP);
holder.tvproductName.requestLayout();
_lP=holder.tvprice.getLayoutParams();
_lP.height=LayoutParams.WRAP_CONTENT;
holder.tvprice.setLayoutParams(_lP);
holder.tvprice.requestLayout();
_lP=holder.edqty.getLayoutParams();
_lP.height=LayoutParams.WRAP_CONTENT;
holder.edqty.setLayoutParams(_lP);
holder.edqty.requestLayout();
_lP=holder.edfree .getLayoutParams();
_lP.height=LayoutParams.WRAP_CONTENT;
holder.edfree.setLayoutParams(_lP);
holder.edfree.requestLayout();
if(holder.tvproductName.getHeight()>height){
height=holder.tvproductName.getHeight();
}
if(holder.tvprice.getHeight()>height){
height=holder.tvprice.getHeight();
}
if(holder.edqty.getHeight()>height){
height=holder.edqty.getHeight();
}
if(holder.edfree .getHeight()>height){
height=holder.edfree .getHeight();
}
Log.v("MAX Height",""+height);
_lP=holder.tvproductName.getLayoutParams();
_lP.height=height;
holder.tvproductName.setLayoutParams(_lP);
holder.tvproductName.setGravity(Gravity.LEFT);
_lP=holder.tvprice.getLayoutParams();
_lP.height=height;
holder.tvprice.setLayoutParams(_lP);
holder.tvprice.setGravity(Gravity.RIGHT);
_lP=holder.edqty.getLayoutParams();
_lP.height=height;
holder.edqty.setLayoutParams(_lP);
holder.edqty.setGravity(Gravity.RIGHT);
_lP=holder.edfree .getLayoutParams();
_lP.height=height;
holder.edfree .setLayoutParams(_lP);
holder.edfree .setGravity(Gravity.RIGHT);
holder.tvproductName.requestLayout();
holder.tvprice.requestLayout();
holder.edqty.requestLayout();
holder.edfree.requestLayout();
Log.v("Product Name",holder.tvproductName.getText().toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
holder.tvproductName.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
holder.tvproductName.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
hybridProductOffer _hp=_arrlist_product.get(position);
String _price,_itemcode,_offerid;
if(_hp.get_offerid()!=null ){
_price=_hp.get_offerprice();
_offerid=_hp.get_offerid();
holder.tvprice.setText( _hp.get_offermrp());
}else{
_price=_hp.get_itemprice();
_offerid=null;
holder.tvprice.setText(_hp.get_itemprice());
}
_itemcode=_hp.get_itemcode();
holder.tvproductName.setText(_hp.get_itemname());
return convertView;
}
Linear Layout XML :
<?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="40dp"
android:baselineAligned="false"
android:weightSum="1" >
<TextView
android:id="#+id/tvitem"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="0.4"
android:background="#drawable/tableborderoffwhite"
android:gravity="left"
android:paddingBottom="2dp"
android:paddingLeft="5dp"
android:paddingRight="2dp"
android:paddingTop="2dp"
android:text="Item"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="15sp" />
<TextView
android:id="#+id/tvprice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="0.2"
android:background="#drawable/tableborderoffwhite"
android:gravity="right"
android:paddingBottom="2dp"
android:paddingLeft="2dp"
android:paddingRight="5dp"
android:paddingTop="2dp"
android:text="Price"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="15sp" />
<EditText
android:id="#+id/edqty"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="0.2"
android:background="#drawable/tableborderoffwhite"
android:gravity="right"
android:paddingBottom="2dp"
android:paddingLeft="2dp"
android:paddingRight="5dp"
android:paddingTop="2dp"
android:text="0"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="15sp" />
<EditText
android:id="#+id/edfree"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="0.2"
android:background="#drawable/tableborderoffwhite"
android:gravity="right"
android:paddingBottom="2dp"
android:paddingLeft="2dp"
android:paddingRight="5dp"
android:paddingTop="2dp"
android:text="0"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="15sp" />
</LinearLayout>
Thanks in Advance , Any helP aPPreciated!
As far as I understand, you want to have different height of listview rows (depends on the highest child's height in the layout) and implement the same height to all of the children.
Why don't you make the height of the children as "match_parent" ? Then you don't need to deal with the height of the children. And then you can set the parent layout's height as "wrap_content", so each layout will have the height of the highest child.
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.