Dynamically created ImageView not respecting RelativeLayout rules - android

I'm adding ImageViews dynamically to a RelativeLayout. I'm trying to align each image to the right of the last image. The initial image aligns correctly but when I set the next image to align to the right side of the last image, it displays at the top left of the screen, disregarding the alignment rules.
Hierarchy View in the Android Device Monitor is indicating that the IDs are correctly getting set and the ImageView is recognizing that it's supposed to align to the id of the last ImageView.
List<String> image_urls = rally.getTransportationImgs();
List<String> methods = rally.getTransportationStrs();
ArrayList<ImageView> IMGS = new ArrayList<ImageView>();
for(int i = 0; i < methods.size(); i++) {
String method = methods.get(i);
for(int j = 0; j < image_urls.size(); j++) {
String img_url = image_urls.get(j);
if(img_url.toLowerCase().contains(method.toLowerCase()) == true) {
ImageView methodImage = new ImageView(this);
methodImage.setId(j + 100);
IMGS.add(methodImage);
RelativeLayout detailsLayout = (RelativeLayout) findViewById(R.id.details_layout);
TextView transportationText = (TextView) detailsLayout.findViewById(R.id.transportationText);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (IMGS.size() > 1) {
params.addRule(RelativeLayout.RIGHT_OF, IMGS.get(IMGS.size() - 1).getId());
params.addRule(RelativeLayout.ALIGN_TOP, IMGS.get(IMGS.size() - 1).getId());
params.addRule(RelativeLayout.END_OF, IMGS.get(IMGS.size() - 1).getId());
params.height = 5000;
params.width = 65;
} else {
params.addRule(RelativeLayout.RIGHT_OF, transportationText.getId());
params.addRule(RelativeLayout.ALIGN_TOP, transportationText.getId());
params.addRule(RelativeLayout.END_OF, transportationText.getId());
params.height = 65;
params.width = 65;
}
methodImage.setLayoutParams(params);
detailsLayout.addView(methodImage);
Picasso.with(getApplicationContext()).load(img_url).fit().centerCrop().placeholder(R.drawable.ic_launcher).into(methodImage);
}
}
}
XML file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:orientation="vertical"
android:weightSum="1"
android:id="#+id/details_layout">
<ImageView
android:layout_width="match_parent"
android:layout_height="275dp"
android:id="#+id/image" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/name2"
android:layout_below="#id/image"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/date2"
android:layout_below="#id/name2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/creator_name2"
android:layout_below="#id/date2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/venues"
android:layout_below="#id/creator_name2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/transportationText"
android:layout_below="#id/venues"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/categories"
android:layout_below="#id/transportationText"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp" />
For debugging purposes, I set the image height obnoxiously large. The gray is part of an image that is supposed to go to the right side of the ImageView that correctly aligns next to "Transportation:"

The problem is with this line:
methodImage.setId(j + 100);
If there's more than one Object in methods array there will be conflict in ImageViews ids. You're generating your ids based on only the index of the inner array (j).
For example if:
There are two items in methods
There are three items in image_urls
Your ImageViews would have ids: [101, 102, 103, 101, 102, 103]
Therefore you will add multiple Views with the same ids.
To solve the issue either generate ids based on both i and j, or generate them in more conventional way.
EDIT:
Well, the other issue is that you're trying to set RelativeLayout Rules that are aligning a particular View to the same View.
Take a look at your code:
You're creating an ImageView, setting its id and immediately adding it to the IMGS list, with this:
IMGS.add(methodImage);
And then you're trying to set your RelativeLayout Rules, that should align your ImageView, but you're referencing to the last item of the IMGS list, with:
IMGS.get(IMGS.size() - 1)
And the last item in the array is the same View, you're trying to set up!
To solve the issue either:
a) Move IMGS.add(methodImage); after the if-else, and change the if condition to if (IMGS.size() > 0) {
or
b) Change the if body to:
params.addRule(RelativeLayout.RIGHT_OF, IMGS.get(IMGS.size() - 2).getId());
params.addRule(RelativeLayout.ALIGN_TOP, IMGS.get(IMGS.size() - 2).getId());
params.addRule(RelativeLayout.END_OF, IMGS.get(IMGS.size() - 2).getId());

Related

Adding checkboxes dynamically to BottomSheetDialog: setMargins() and setPadding() not working as expected

I want to add checkboxes dynamically to a BottomSheetDialog. However, the buttons are not aligning as I want them to. Styling the checkboxes works if I style them directly on the XML, however, they don't style at all programmatically.
Here's my XML layout code with two hardcoded checkboxes:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/id_layout_bottom_sheet_choices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:padding="10dp"
android:text="Escolha uma resposta"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#000000"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:textSize="20sp"
android:textStyle="bold" />
<CheckBox
android:id="#+id/checkBox2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
android:paddingLeft="10dp"
android:text="CheckBox" />
<CheckBox
android:id="#+id/checkBox3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
android:paddingLeft="10dp"
android:text="CheckBox" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="horizontal">
<Button
android:id="#+id/cancel_btn"
style="#style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancelar" />
<Button
android:id="#+id/confirm_btn"
style="#style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK" />
</LinearLayout>
</LinearLayout>
Here, I try to add more of them programmatically:
LinearLayout mainLinearLayout = bottomSheetDialog.findViewById(R.id.id_layout_bottom_sheet_choices);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
// margin-left: 10, margin-bottom: 10, like the margins in the two hardcoded xml checkboxes
params.setMargins(10, 0, 0, 10);
for (int i = 0; i < answerChoices.size(); i++) {
CheckBox checkBox = new CheckBox(getContext());
checkBox.setText(answerChoices.get(i));
// left padding
checkBox.setPadding(10,0,0,0);
// i + 3 since there's already a textview and two sample checkboxes added, and i want to add the new checkbox after them and before the remaining elements
mainLinearLayout.addView(checkBox, i + 3, params);
}
Here's of the output in the BottomSheetModal with that code, after the buttons are added:
As you can see, the first hardcoded checkboxes are aligned correctly, however the two other checkboxes added via coding are not. Even the checkbox select colors are different (but why???)
Here's the output that I pretend (I hardcoded the other two checkboxes just to showcase how I want the output to be after coding)
How can I solve this problem?
Because in xml file you use dp unit but in code you use pixel unit. You must convert from dp to pixel before set margin for checkbox.
LinearLayout mainLinearLayout = bottomSheetDialog.findViewById(R.id.id_layout_bottom_sheet_choices);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
// margin-left: 10, margin-bottom: 10, like the margins in the two hardcoded xml checkboxes
int margin = (int)convertDpToPixel(10F, this);
params.setMargins(margin, 0, 0, margin);
for (int i = 0; i < answerChoices.size(); i++) {
CheckBox checkBox = new CheckBox(getContext());
checkBox.setText(answerChoices.get(i));
// left padding
checkBox.setPadding(margin, 0, 0, 0);
// i + 3 since there's already a textview and two sample checkboxes added, and i want to add the new checkbox after them and before the remaining elements
mainLinearLayout.addView(checkBox, i + 3, params);
}
// Add this method to convert dp to pixel
public static float convertDpToPixel(float dp, Context context){
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

android :Removing random space between dynamically generated ImageView and TextView

I am currently working at developing an app that requires a dynamically generated GridView. In the layout added to the GridView through an adapter I have a LinearLayout that takes information from an ArrayList and then it should display an ImageView followed by a TextView. I have done that programmatically, but some random space appears between the two of them.
I have tried removing the padding, removing the margin, setting the adjustViewBounds of the image to true and also removing the inner padding of the TextView and none of these things work.
Here is the .xml file containing the LinearLayout to be populated:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#drawable/rounded_text_black">
<ImageView
android:id="#+id/separator"
android:layout_width="match_parent"
android:layout_height="2dp"
android:scaleType="fitXY"
android:src="#drawable/horizontal_white_line"
android:layout_centerVertical="true"/>
<LinearLayout
**android:id="#+id/orderLayout"**
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignBottom="#id/separator"
android:orientation="vertical"
android:paddingTop="40dp">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignTop="#id/separator"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_marginTop="10dp">
<ImageView
android:layout_width="15dp"
android:layout_height="15dp"
android:scaleType="fitXY"
android:src="#mipmap/effects"
android:layout_gravity="center"/>
<TextView
android:id="#+id/moodText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
style="#style/smallText"
android:padding="0dp"/>
<TextView
android:id="#+id/tastesText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
style="#style/smallText"
android:textAllCaps="false"
android:padding="0dp"/>
<TextView
android:id="#+id/tastesText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
style="#style/smallText"
android:textAllCaps="false"
android:padding="0dp"/>
</LinearLayout>
</RelativeLayout>
Here is the code that generates the image-text pairs:
for(int i = 0; i < 3; i++){
int currentPos = orderSize - i;
if(currentPos >= 0){
LinearLayout container = new LinearLayout(v.getContext());
LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
container.setOrientation(LinearLayout.HORIZONTAL);
container.setGravity(Gravity.RIGHT);
container.setLayoutParams(containerParams);
ImageView img = new ImageView(v.getContext());
LinearLayout.LayoutParams imgParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
imgParams.gravity=Gravity.RIGHT;
img.setLayoutParams(imgParams);
img.setPadding(0,0,0,0);
if(order.get(currentPos).delivered){
img.setImageResource(R.drawable.green_circle);
}
else{
img.setImageResource(R.drawable.yellow_circle);
}
TextView txt = new TextView(v.getContext());
txt.setTextColor(Color.WHITE);
txt.setText(order.get(currentPos).orderItem);
txt.setPadding(0,0,0,0);
container.addView(img);
container.addView(txt);
ll.addView(container);
}
And here is the result:
The red rectangle indicates the extra space.
Thank you very much.
I suggest you to create your line item view (green ball and drink name) in an xml layout, checking that all is working fine on a single line.
Then you can change your for cycle as follows:
for(int i = 0; i < 3; i++){
int currentPos = orderSize - i;
if(currentPos >= 0){
// inflate a new instance of view starting from an xml file
View tableLineView = getLayoutInflater().inflate(R.layout.table_line, null);
// Image view
ImageView iv = (ImageView)tableLineView.findViewById(R.id.ball);
if(order.get(currentPos).delivered){
iv.setImageResource(R.drawable.green_circle);
} else{
iv.setImageResource(R.drawable.yellow_circle);
}
// TextView
TextView tv = (TextView)tableLineView.findViewById(R.id.textview);
tv.setText(order.get(currentPos).orderItem);
// add to LinearLayout
ll.addView(tableLineView);
}
}
I can't test it now, if you find problems ask me.
Here you can read a discussion about view inflating
TextView txt = new TextView(this);
LinearLayout.LayoutParams txtParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
txt.setLayoutParams(txtParams);
txt.setTextColor(Color.BLACK);
txt.setText("Hello World");
txt.setPadding(0,0,0,0);
Use this and you wont see padding anymore!!

Why are programmatically set weights for Android linear layout columns not working correctly?

I am attempting to create a key for an above pie chart within this Linear layout. However, the weights aren't working properly, and the three columns are split up equally. Does anyone know what may be causing this? Thanks!
Layout XML:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tableLayout1"
android:orientation="vertical"
android:layout_centerHorizontal="true">
<TableRow android:gravity="center"
android:id="#+id/tableRow"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:weightSum="4">
<ImageButton
android:layout_width="0dp"
android:layout_height="100dp"
android:id="#+id/aiButton"
android:layout_gravity="center_horizontal"
android:src="#drawable/barchartwhite"
android:background="#CCAF00"
android:layout_weight="1"
android:scaleType="fitCenter"
/>
<TextView
android:layout_width="0dp"
android:layout_height="100dp"
android:text="TP Activity"
android:id="#+id/textView2"
android:layout_gravity="center|center_vertical"
android:textSize="40sp"
android:background="#CCAF00"
android:layout_weight="3"
android:layout_alignParentTop="true"
android:textColor="#FFFFFF"
android:layout_centerHorizontal="true"
android:gravity="center_vertical" />
</TableRow>
<TableRow android:gravity="center"
android:id="#+id/tableRowSub"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Percentage of Activity per TP"
android:id="#+id/textViewSub"
android:layout_gravity="center"
android:textSize="16sp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
</TableRow>
<TableRow
android:id="#+id/tableRow2"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dip">
<com.shannonsystemsllc.ediconnect.PieChartView
xmlns:chart="http://schemas.android.com/apk/res-auto"
android:id="#+id/piechart"
android:paddingRight="12dp"
android:paddingLeft="12dp"
android:layout_width="300sp"
android:layout_height="300dp"/>
</TableRow>
</LinearLayout>
Code for creating key:
for (int i = 0; i < customers.size(); i++) {
int c[] = {Color.parseColor("#FF4B66"),Color.parseColor("#00A9AC"),Color.parseColor("#70A200"),Color.parseColor("#FAB448"),Color.parseColor("#BFBFBF"),Color.GREEN,custColor,Color.CYAN,Color.BLUE};
TableRow.LayoutParams lp = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT);
TableLayout.LayoutParams tl = new TableLayout.LayoutParams();
final float scale = getActivity().getResources().getDisplayMetrics().density;
int pixels = (int) (30 * scale + 0.5f); //set pixels to dp
TableRow row = new TableRow(activity);
row.setWeightSum(9);
//first row
tl.weight = 1;
lp.weight = 6;
lp.height = pixels;
row.setLayoutParams(lp);
TextView tv1a = new TextView(getActivity());
tv1a.setTextSize(22);
tv1a.setText(customers.get(i));
tv1a.setLayoutParams(lp);
tv1a.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
TextView tv1b = new TextView(getActivity());
tv1b.setTextSize(24);
Float perFloat = ((float)pieChartValues[i]/dataTotal*100);
remainderTotal = remainderTotal - perFloat.intValue();
String percentage;
if (perFloat.intValue() == 0)
{
percentage = ("1%");
}
else
{
percentage = (perFloat.intValue() + "%");
}
lp.weight = 2;
tv1b.setText(percentage);
tv1b.setLayoutParams(lp);
tv1b.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
lp.weight = 1;
ImageView tv1c = new ImageView(getActivity());
tv1c.setLayoutParams(lp);
tv1c.setBackgroundColor(c[i]);
row.setWeightSum(3);
row.addView(tv1b);
row.addView(tv1c);
row.addView(tv1a);
row.setId(i);
ll.addView(row);
}
Screenshot:
Set the weight of the contents inside each row as follows:
- For the percentage TextView, set the weight to 3.
- For the ImageView, set the weight to 8.
- For the name Textview, set the weight to 7.
This will result to the entire row to look slightly offset from the centre. Make sure all three views are set to match parent width.
Once you set weights for the views call:
yourLinearLayout.invalidate()
Try this out and see if it works.

Textview with long text pushes out other views in GridLayout despite ellipsize=end

My problem is very similar to How to get a layout where one text can grow and ellipsize, but not gobble up the other elements on the layout, but read on below why I can't use TableLayouts as proposed there.
I'm trying to create a listview row that basically looks like this:
| TextView | View 1 | View 2 |
All views contain variable width elements. The TextView has ellipsize="end" set. View 1 should align left of the TextView, while View 2 should align to the right of the screen. So, normally, there would be whitespace between View 1 and View 2. As the text in the TextView grows longer, the TextView should grow, pushing View 1 to the right until there is no more whitespace left. Then, ellipsize should kick in, cutting of the text in TextView and appending an ellipsis ("...") at the end.
So, the result should look something like this:
+----------------------------------------+
| short text [view1] [view2] |
+----------------------------------------+
| long text with ell ... [view1] [view2] |
+----------------------------------------+
I've tried:
TableLayouts, but they seem to make scrolling extremely slow on some devices.
RelativeLayouts, but I either had overlapping views, or view1 or view2 disappeared completely.
GridLayouts, but the TextView always grows until it takes up the whole width of the screen, thus pushing view1 and view2 out of the screen.
This is the GridLayout I tried:
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_gravity="left|fill_horizontal"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
<TextView
android:layout_gravity="left"
android:text="(view1)" />
<TextView
android:layout_gravity="right"
android:text="(view2)" />
</GridLayout>
View 1 and View 2 are not really TextViews, I just used them in the example to simplify things.
Is there any way to achieve this without using TableLayouts?
EDIT:
As requested, here is my attempt at solving this with a RelativeLayout. The TextView takes up the full width of the screen in this case, so neither view1 nor view2 are visible.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/rl0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
<TextView
android:id="#+id/rl1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/rl0"
android:layout_marginLeft="10dp"
android:text="(view1)" />
<TextView
android:id="#+id/rl2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/rl1"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dp"
android:text="(view2)" />
</RelativeLayout>
I seem to have found a potential solution to prevent a TextView in GridLayout from growing unboundedly and pushing out other views. Not sure if this has been documented before.
You need to use fill layout_gravity and set an arbitrary layout_width or width on the long TextView in need of ellipsizing.
android:layout_gravity="fill"
android:layout_width="1dp"
Works for both GridLayout and android.support.v7.widget.GridLayout
I'm a big fan of LinearLayouts, so here's my suggestion using those:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(view1)" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="(view2)" />
</LinearLayout>
I will suggest you to play with layout_weight property of your widget
Example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="10">
<LinearLayout
android:id="#+id/ll_twoViewContainer"
android:layout_weight="8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/rl0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text" />
<TextView
android:id="#+id/rl1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_toRightOf="#id/rl0"
android:layout_weight="1"
android:minWidth="120dp"
android:text="(view1)" />
</LinearLayout>
<TextView
android:id="#+id/rl2"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/rl1"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dp"
android:text="(view2)" />
</LinearLayout>
</LinearLayout>
finally your layout will look like as follow:
+----------------------------------------+
| short text [view1] [view2] |
+----------------------------------------+
| long text with ell ... [view1] [view2] |
+----------------------------------------+
I think you should create custom layout for your purpose. I don't know how to do this using only default layouts/view and make it work for all cases.
The trick which worked for me was to use maxWidth to restrict the width of the first view. You need to do it with Java, here is the basic logic:
firstView.setMaxWidth(parentView.getWidth() - view2.getWidth() - view1.getWidth() - padding * 2);
Not pretty, but it works.
I think there's just a small issue on the layout that could be solved, anchoring the view3 to the right and start from there to force the view to have a delimited area (hence being able to properly set the ellipse):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/rl3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="(view2)" />
<TextView
android:id="#+id/rl2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/rl3"
android:text="(view1)" />
<TextView
android:id="#+id/rl1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#id/rl2"
android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
</RelativeLayout>
Hope this helps...
Regards!
Try this
<?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:baselineAligned="false"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="(view1)"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="(view2)"/>
</LinearLayout>
</LinearLayout>
Currently, all views are centered. You can change android:gravity property to meet your needs. For example, you may want to align view1 right and view2 left in which case last two LinearLayouts would look something like (with 5dp margin on the right and left respectively):
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center|right">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginRight="5dp"
android:text="(view1)"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center|left">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="5dp"
android:text="(view2)"/>
</LinearLayout>
I find my solution for the case number 2 (the one with a long text):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="3" >
<TextView
android:id="#+id/rl0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="3"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
<TextView
android:id="#+id/rl1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="(view1)" />
<TextView
android:id="#+id/rl2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="(view2)" />
</LinearLayout>
The real problem is case one, and i didn't try a lot of things for this. I hope it helps (and if i have more spare time, i will try to achieve first one!).
If the views on the right get pushed over by the text by design, you might as well use a ListView instead of a GridView.
You would just need to make the base of the list item layout a RelativeLayout, and set rules like this:
You can set the two views on the right to alignParentRight (using android:layout_alignParentLeft="true"), but make sure the first view stays to the left of the second so it will push itself to the left as the views stretch out.
You can make the TextView on the left align to the left, but stay to the left of the first view (using android:layout_toLeftOf="#+id/viewId") so it won't overlap with the views.
Try using Layout Weight
<TableRow
android:id="#+id/tableRow3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/tableRow2"
android:layout_alignParentBottom="true"
android:gravity="center"
android:weightSum="10"
android:background="#android:color/black" >
<TextView
android:id="#+id/txtInningsTotal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center"
android:text="0"
android:textColor="#android:color/white" />
<TextView
android:id="#+id/txtTeamOneTotal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:gravity="center"
android:text="0"
android:textColor="#android:color/white" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.2" />
<TextView
android:id="#+id/txtTeamTwoTotal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:gravity="center"
android:text="0"
android:textColor="#android:color/white" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.2" />
<TextView
android:id="#+id/txtGrandTotal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:gravity="center"
android:text="0"
android:textColor="#android:color/white" />
</TableRow>
Here i have taken table row in which there is layout weight sum which is of 10 means that it is 100% width of its parent. and in all its child views i have set width to 0Dp and given weight to 1 or 2. so that it will take up to that percent of total 10. so the layout will be adjusted accordingly screen and also there will be no issue of overlapping.
If i have understood you correctly then this is the answer you wanted.
Hope it Helps!
First, you must layout [view 2] to parent Right;
Again, you reference the reference to the last two layout!
<Relativelayout android:layout_width="match_parent"
android:layout_height="wrap_content"
<TextView
android:id="#+id/view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeft="#id/view2"
android:gravity="left">
<TextView
android:id="#+id/shortORlongtTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/view1"
android:ellipsize="end"
android:maxLines="1"
android:textSize="18dp"/>
<TextView
android:id="#+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
I had the same problem with the grid layout. what i did is given a fixed width for the text view and also given layout_columnWeight property for each text view then the issue was fixed ,hope it helps ...
<TextView
android:id="#+id/txtName"
style="#style/MyDetailTitle"
android:layout_width="#dimen/detail_length"
android:layout_height="wrap_content"
android:text="#string/app_name"
app:layout_column="3"
app:layout_columnWeight="1"
app:layout_gravity="start"
app:layout_row="1" />
GridLayout is like the other things on Android : flawed by design.
You will need a custom Layout, the following example will allow you to layout things like:
[ label | short text | very long label | short text ]
[ long label | very very very | label | very long text ]
[ | long text | | ]
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class TwoColumsGridLayout extends ViewGroup {
private final List<List<View>> rows;
private int rowCount = 0;
private int firstColumWidth;
private int secondColumWidth;
private int thirdColumWidth;
private int fourthColumnWidth;
private final List<Integer> rowHeights = new ArrayList<>();
private final List<List<Integer>> cellHeights = new ArrayList<>();
private final List<Integer> firstCellsWidths = new ArrayList<>(4);
private final List<Integer> thirdCellsWidths = new ArrayList<>(4);
public TwoColumsGridLayout(Context context, int rowCount) {
super(context);
rows = new ArrayList<>(rowCount);
}
public void add(Context ctx, TextView l1, View t1, TextView l2, View t2) {
final List<View> row = new ArrayList<>(4);
row.add(l1);
row.add(t1);
row.add(l2);
row.add(t2);
rows.add(row);
this.addView(l1);
this.addView(t1);
if (l2 != null)
this.addView(l2);
if (t2 != null)
this.addView(t2);
this.rowCount++;
}
public int getRowCount() {
return rowCount;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int curLeft = 0;
int curBottom;
int curRight;
int curTop = 0;
int i = 0;
for (List<View> row : rows) {
final int rowHeight = this.rowHeights.get(i);
final List<Integer> rowCellHeights = this.cellHeights.get(i);
final View v0 = row.get(0);
curLeft = 0;
curRight = curLeft + this.firstColumWidth;
if (v0 != null) {
curBottom = curTop + rowCellHeights.get(0);
// Right align
v0.layout(curLeft + this.firstColumWidth - this.firstCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
}
//
final View v1 = row.get(1);
curLeft += this.firstColumWidth;
curRight = curLeft + this.secondColumWidth;
if (v1 != null) {
curBottom = curTop + rowCellHeights.get(1);
v1.layout(curLeft, curTop, curRight, curBottom);
}
//
final View v2 = row.get(2);
curLeft += this.secondColumWidth;
curRight = curLeft + this.thirdColumWidth;
if (v2 != null) {
curBottom = curTop + rowCellHeights.get(2);
// Right align
v2.layout(curLeft + this.thirdColumWidth - this.thirdCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
}
//
final View v3 = row.get(3);
curLeft += this.thirdColumWidth;
curRight = curLeft + this.fourthColumnWidth;
if (v3 != null) {
curBottom = curTop + rowCellHeights.get(3);
v3.layout(curLeft, curTop, curRight, curBottom);
}
curTop += rowHeight;
i++;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
// Compute first column width
firstColumWidth = 0;
for (List<View> row : rows) {
final View v = row.get(0);
if (v != null) {
v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
measureChild(v, widthMeasureSpec, heightMeasureSpec);
final int w = v.getMeasuredWidth();
if (firstColumWidth < w) {
firstColumWidth = w;
}
}
}
// Compute third column width
thirdColumWidth = 0;
for (List<View> row : rows) {
final View v = row.get(2);
if (v != null) {
v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
measureChild(v, widthMeasureSpec, heightMeasureSpec);
final int w = v.getMeasuredWidth();
if (thirdColumWidth < w) {
thirdColumWidth = w;
}
}
}
secondColumWidth = (parentWidth - firstColumWidth - thirdColumWidth) / 2;
fourthColumnWidth = parentWidth - firstColumWidth - secondColumWidth - thirdColumWidth;
// Clear
this.rowHeights.clear();
this.cellHeights.clear();
this.firstCellsWidths.clear();
this.thirdCellsWidths.clear();
// Compute heights
int height = 0;
for (List<View> row : rows) {
final ArrayList<Integer> rowCellHeights = new ArrayList<>(4);
cellHeights.add(rowCellHeights);
int rowHeight = 0;
// First column
final View v0 = row.get(0);
if (v0 != null) {
int h = v0.getMeasuredHeight();
this.firstCellsWidths.add(v0.getMeasuredWidth());
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
} else {
this.firstCellsWidths.add(0);
}
// Second column
final View v1 = row.get(1);
if (v1 != null) {
v1.setLayoutParams(new ViewGroup.LayoutParams(secondColumWidth, LayoutParams.WRAP_CONTENT));
measureChild(v1, widthMeasureSpec, heightMeasureSpec);
int h = v1.getMeasuredHeight();
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
}
// Third column
final View v2 = row.get(2);
if (v2 != null) {
int h = v2.getMeasuredHeight();
this.thirdCellsWidths.add(v2.getMeasuredWidth());
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
} else {
this.thirdCellsWidths.add(0);
}
// Fourth column
final View v3 = row.get(3);
if (v3 != null) {
v3.setLayoutParams(new ViewGroup.LayoutParams(fourthColumnWidth, LayoutParams.WRAP_CONTENT));
measureChild(v3, widthMeasureSpec, heightMeasureSpec);
int h = v3.getMeasuredHeight();
rowCellHeights.add(h);
if (rowHeight < h) {
rowHeight = h;
}
}
height += rowHeight;
this.rowHeights.add(rowHeight);
}
setMeasuredDimension(parentWidth, height);
}
}
Have fun.
TableLayout will give expected behavior. May cause performance issue as question's author mention, but works great with simple layout. If the row is repeatable and scrollable, consider use gridview instead
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:shrinkColumns="0"
>
<TableRow>
<TextView/>
<View1/>
<View2/>
</TableRow>
</TableLayout>

Add dynamic text to RelativeLayout

I want to create a "Enter your name"-page (for the highscore) for my Android-game but I’m experiencing some problems.
I want it to look like this:
You have reached (=enthst1)
.........here’s the score..............
points! (=enthst2)
Please type in your name to save your score! (= enthst3)
........EditText for name.....
Back (=button) ................... Enter (=button)
But I don’t seem to be able to add the score (int) to my ContentView!
Here’s the code:
Java in "onCreate":
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_hs);
layo = new RelativeLayout(this);
MySco = new TextView(this) ;
Back = (Button)findViewById(R.id.enthsre1);
Back.setOnClickListener(this);
Enter =(Button)findViewById(R.id.enthsok1);
Enter.setOnClickListener(this);
Eingabe = (EditText) findViewById(R.id.editText1) ;
Texta = (TextView) findViewById(R.id.enthst1) ;
Textb = (TextView) findViewById(R.id.enthst2) ;
Textc = (TextView) findViewById(R.id.enthst3) ;
Intent intentk = getIntent();
kontro = intentk.getStringExtra("from").equals("MainActivity") ;
score = 0 ;
if(kontro == false){
score = punkteRechnen(tuleb, le0leb, le1leb, le2leb) ; //calculate the score
} else {
score = 10 ;
}
scoint = "" + score ;
MySco.setText(scoint) ;
MySco.setTextColor(Color.WHITE) ;
MySco.setTextSize(20);
/*I know that this will throw me an IllegalStateException (the specified child already has a parent)
layo.addView(Texta) ;
layo.addView(MySco) ;
layo.addView(Textb) ;
layo.addView(Textc) ;
layo.addView(Eingabe) ;
layo.addView(Back) ;
layo.addView(Enter) ;
*/
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:orientation="vertical"
tools:context=".EnterHSActivity" >
<TextView
android:id="#+id/enthst1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="#string/enthst1a"
android:textColor="#color/white"
android:textColorHint="#color/white"
android:textSize="20sp" />
<TextView
android:id="#+id/enthst2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_centerHorizontal="true"
android:text="#string/enthst1b"
android:textColor="#color/white"
android:textColorHint="#color/white"
android:textSize="20sp" />
<TextView
android:id="#+id/enthst3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:layout_centerHorizontal="true"
android:text="#string/enthst1c"
android:textColor="#color/white"
android:textColorHint="#color/white"
android:textSize="18sp" />
<Button
android:id="#+id/enthsre1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="20dp"
android:layout_marginLeft="100dp"
android:text="#string/retour" />
<Button
android:id="#+id/enthsok1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="20dp"
android:layout_marginRight="100dp"
android:text="#string/allesklar" />
<EditText
android:id="#+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/enthsre1"
android:layout_alignRight="#+id/enthsok1"
android:layout_below="#+id/enthst3"
android:ems="10"
android:inputType="text"
android:textColor="#color/white"
android:textColorHint="#color/white"
android:textColorLink="#color/red" >
<requestFocus />
</EditText>
</RelativeLayout>
So, how do I add the score to my layout?
You should not add a view to a layout if it is already a child of that layout. When you call setcontentview your XML layout is inflated and all those views are created and added to your view hierarchy.
I would add the MySco text view to your layout XML then call findviewbyid to get it. I would avoid dynamically adding views. You can always create a view that is hidden and then show it later to get a similar effect.
Here is the modified / stripped down code for your onCreate method.
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_hs);
MySco = (TextView)findViewById(R.id.score);
Intent intentk = getIntent();
kontro = intentk.getStringExtra("from").equals("MainActivity") ;
score = 0 ;
if(kontro == false){
score = punkteRechnen(tuleb, le0leb, le1leb, le2leb) ; //calculate the score
} else {
score = 10 ;
}
scoint = "" + score ;
MySco.setText(scoint) ;
MySco.setTextColor(Color.WHITE) ;
MySco.setTextSize(20);
In your layout add this:
<TextView
android:id="#+id/score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:textColorHint="#color/white"
android:textSize="20sp" />
You can't call addView on textA, textB, etc, because they're already existant in your XML file, and are already children of a view. Instead you should make an empty RelativeLayout in your XML file, then create textA, etc, with new TextView(), and add those to the layout instead.
Try this it might help you.
Add the textview in relative layout to add score on layout.
MySco.setLayoutParams(new RelativeLayout.LayoutParams(300,300);
layo.addView(MySco);

Categories

Resources