Programatically setting constraints is leading to views overlapping - java

I'm trying to write some code to display two views within a constraint layout. I have used the following code so that the first view should appear on the left of the screen, and the second on the right.
ConstraintSet set = new ConstraintSet();
set.clone(cl);
set.connect(tv.getId(), ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT, 0);
set.connect(img.getId(), ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 0);
set.applyTo(cl);
However when I run my app the two views just appear in the centre overlapping each other.
The code for my two views is:
ConstraintLayout.LayoutParams params3 = new
ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.WRAP_CONTENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT
);
params3.setMargins(8,8,8,8);
ConstraintLayout.LayoutParams params4 = new
ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.WRAP_CONTENT,
ConstraintLayout.LayoutParams.WRAP_CONTENT
);
params4.setMargins(5,5,5,5);
LinearLayout.LayoutParams params5 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
TextView tv = new TextView(mContext);
tv.setText(LeagueName);
tv.setTextSize(18);
tv.setLayoutParams(params3);
ImageView img = new ImageView(mContext);
img.setImageResource(R.mipmap.basketball);
img.setLayoutParams(params4);
cl.addView(tv);
cl.addView(img);
card.addView(cl);
mLayout.addView(card);
I'm new to android so I've almost certainly missed something fundamental.
Thanks

So after a lot of playing around I've discovered that getId() returns the same default value for each element and so each time I added a new constraint I was applying it to every view. The way around this is to use setId() every time you create a new view in order to ensure they remain unique.

Related

Cannot add a RelativeLayout to a RelativeLayout programmatically

So I'm trying to add a RelativeLayout to a RelativeLayout however, when I run my app, it's an IllegalStateException that shows this error: The specified child already has a parent. You must call removeView() on the child's parent first. I'm sure you guys have seen this before. My question is how do I properly nest two relative layouts together?
Here is the code snippet that produces the exception:
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
RelativeLayout newFrame = new RelativeLayout(vidRipperService.getBaseContext());
newFrame.setLayoutParams(layoutParams);
// configure image view constraints...
// have the frame be right in the center of the layout.
ImageView editedFrame = new ImageView(vidRipperService.getBaseContext());
// Note: when doing padding the height and the width must be a multiple of two. A nice example is 70+30 = 100/2 = 50, but 80+30 = 110/2 = 55 <- not a multiple of two. Keep this in mind.
editedFrame.setId(View.generateViewId());
editedFrame.setPadding(30,30,30,0); // padding of 30 around the whole view.
editedFrame.setImageBitmap(frame); // set the frame to be that of the actual background.
RelativeLayout.LayoutParams frameLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
frameLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); // place frames in center of the view.
editedFrame.setLayoutParams(frameLayoutParams);
newFrame.addView(breakingNewsLayout); // add the breaking news layout to this view!
newFrame.addView(editedFrame);
The problem is specifically triggered from the second to last line newFrame.addView(breakingNewsLayout) That line triggers the exception. The breakingNewsLayout is another relative layout that I would like to add to newFrame. I would appreciate any knowledge on how to get this to work. I never ran into a problem when nesting layouts before, but for some reason, this is really not playing nice.
Here is the code that creates the breakingNewsLayout:
private void createBreakingNewsLayout()
{
breakingNewsLayout = new RelativeLayout(vidRipperService.getBaseContext()); // create the new breaking new layout.
breakingNewsLayout.setElevation(5);
breakingNewsLayout.setPadding(0,0,0,15);
breakingNewsLayout.setBackgroundColor(ContextCompat.getColor(vidRipperService, R.color.transparent)); // ensure that the background is transparent.
// MATCH_PARENT for both width and height so that banner is shown on the frame for the video.
RelativeLayout.LayoutParams breakingNewsParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
breakingNewsParams.setMargins(0,50,0,0); // todo: ensure that the margin is 50dp not pixels!
breakingNewsParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
breakingNewsLayout.setLayoutParams(breakingNewsParams); // set the layout params for the breaking news layout.
// set all of the text view attributes.
TextView liveBannerText = getLiveBannerText();
TextView breakingNewsTime = getBreakingNewsTime();
TextView breakingNewsHeadline = getBreakingNewsHeadline(breakingNewsTime.getId()); // headline goes about the breaking news time.
TextView breakingNewsBanner = getBreakingNewsBanner(breakingNewsHeadline.getId()); // banner goes above the breaking news headline
TextView viddyWatermarkText = getViddyWatermarkText(breakingNewsHeadline.getId()); // viddy watermark goes above the breaking news headline.
TextView breakingNewsDescription = getBreakingNewsDescription(breakingNewsTime.getId()); // breaking news description goes to the end of the breaking news time
// Add all of the views for the breaking news layout.
breakingNewsLayout.addView(liveBannerText);
breakingNewsLayout.addView(breakingNewsBanner);
breakingNewsLayout.addView(viddyWatermarkText);
breakingNewsLayout.addView(breakingNewsHeadline);
breakingNewsLayout.addView(breakingNewsTime);
breakingNewsLayout.addView(breakingNewsDescription);
}
maybe you should remove breakingNewsLayout before you add it:
((ViewGroup) breakingNewsLayout.getParent()).removeView(breakingNewsLayout);
I figured it out! After extensive researching and testing the reason I was getting this issue was because I was attempting to reuse the breakingNewsLayout when creating a new frame. I have x amount of frames and I needed to generate the breakingNewsLayout every single time I wanted to apply the layout to the frame. Since I was trying to reuse the layout that I have already added, the layout already has a parent and thus the exception above was called.
Apologies for the question and any lack of details.

Android ConstraintLayout programmatically connect but only work top to top

LinearLayout.LayoutParams navigationBarParams =
new LinearLayout.LayoutParams(0, (int)(BAR_DEFAULT_HEIGHT_DP * density) );
_navigationBar.setId(R.id.navigation_fragment_navigation_bar);
_navigationBar.setPadding(0, 0, 0, 0);
_navigationBar.setLayoutParams(navigationBarParams);
_navigationBar.setOrientation(LinearLayout.HORIZONTAL);
_navigationBar.setBaselineAligned(false);
_navigationBar.setWeightSum(6f);
_navigationBar.setElevation(20.0f);
ConstraintLayout con = (ConstraintLayout)_rootView.findViewById(_rootConstraintLayoutId);
con.addView(_navigationBar);
ConstraintSet set = new ConstraintSet();
set.clone(con);
set.constrainWidth(_navigationBar.getId(), 0);
set.connect(_navigationBar.getId(), ConstraintSet.TOP, con.getId(), ConstraintSet.TOP, 100 ); //work!
set.connect(_navigationBar.getId(), ConstraintSet.LEFT, con.getId(), ConstraintSet.LEFT,100 ); //not work!!
set.connect(_navigationBar.getId(), ConstraintSet.RIGHT, con.getId(), ConstraintSet.RIGHT, 100 ); //not work!!
set.applyTo(con);
I add LinearLayout to root ConstraintLayout.
and connect constraint TOP to TOP, LEFT to LEFT, RIGHT to RIGHT with all value 100.
but only top value 100 is work.
not work left, right. what wrong my code?
임근영 Use Start and End instead on that way your view it will support different languages.
set.connect(boton.getId() , ConstraintSet.START , ConstraintSet.PARENT_ID , ConstraintSet.START , 80);
I know there is a bug reported on google for that.
android.support.constraint.ConstraintLayout
on that try removing it and use
"LinearLayout"
you will be able to change your orientation as you like.
by writing
andriod:oreiantation="horizontal" or andriod:oreiantation="vertiacl"
its your choice

How can I set a textview's style programmatically?

How can I add a style to a textview in java? I am trying to add one under my values/styles.xml, not to add each attribute individually.
LinearLayout messagesLayout = (LinearLayout) findViewById(R.id.messages_layout);
TextView sentOne = new TextView(this);
sentOne.setText(sentMessage);
messagesLayout.addView(sentOne);
You may find this answer by Benjamin Piette handy. To change this into working code for a TextView just change it up a bit:
TextView tv = new TextView (new ContextThemeWrapper(this, R.style.mystyle), null, 0);
EDIT: to set other things like margins, height & width and others, use LayoutParams. To set the params throrin19's answer can be helpful.
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
tv.setLayoutParams(params);
There is an answer for this already: https://stackoverflow.com/a/7919203/5544859
textview.setTypeface(Typeface.DEFAULT_BOLD);
to preserve the previously set typeface attributes you can use:
textview.setTypeface(textview.getTypeface(), Typeface.DEFAULT_BOLD);
Credit to: #Raz

Android: calling setPadding() on a view doesn't work when I also set the layoutParams on the view

If I call setPadding() on a view, I can successfully set the padding, however, if I first set the layoutParams and then the padding, or set the padding and then set the layoutParams, the padding is not applied.
Demonstration:
//This doesn't work
textView.setLayoutParams(linearLayoutParams);
textView.setPadding(0, 100, 0 , 0);
//This doesn't work either
testView.setPadding(0, 100, 0 , 0);
textView.setLayoutParams(linearLayoutParams);
//This does work
textView.setPadding(0, 100, 0 , 0);
Does anyone know how to use setLayoutParams() and setPadding() at the same time, or why setLayoutParams() is stopping setPadding() from working?
Edit:
More detail:
I call this method in onCreate()
public void initTextView(){
Textview textView = (TextView) findViewById(R.id.textView);
LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams(myWidth, myHeight);
textView.setLayoutParams(linearLayoutParams);
//This doesn't work
textView.setPadding(0, 100 ,0 , 0);
}
but if I comment out this line from above:
// textView.setLayoutParams(linearLayoutParams);
Then the setPadding() method does work.
Thanks in advance.
I don't believe there's anything wrong with the code, rather just not understanding what it's doing.... if your myHeight value is smaller than the padding, you're just simply not going to notice the effect.
In the attached series of screenshots, the first screenshot is the default TextView containing a price (it has no layout params other than what's set in xml).
In the 2nd screenshot I set the textview to the following (height=30, top padding = 100:
LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 30);
textview.setLayoutParams(linearLayoutParams);
textview.setPadding(0, 100, 0, 0);
The text is there, the top padding is there, but it's all forced to "crop" to the set height of 30 (note I also lost all my original xml parameters (gravity, margins, etc) because setting LayoutParams cancels all of that and only applies whatever I set in those LayoutParams).
In the 3rd screenshot I set the textview to the following (height=150, top padding = 100:
LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 150);
textview.setLayoutParams(linearLayoutParams);
textview.setPadding(0, 100, 0, 0);
Voila! Since I've given the view ample height, it can fully display the text and the top padding (though again, I lost all my xml parameters).. If you go back to your source, try it out: replace myHeight with some fixed value (try at least 150) and see if things display as they should.
object ScreenUtils {fun dpToPixel(dp: Int): Int {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), Resources.getSystem().displayMetrics).toInt()}}
in Kotlin
setPadding(ScreenUtils.dpToPixel(8), 0, ScreenUtils.dpToPixel(8), 0)

How to fix my TableLayout and TableRow into specific positions dynamically?

I'm having problems setting up my TableRow with some TextViews in TableLayout dynamically. I have two pictures, one is my current situation shown, and the other is my mockup, expected situation (the goal which I need to achieve). I do not have any XML layouts; All of these are created programmatically, which is also something I need to achieve.
The snapshots shown are for a High Score screen, where I get a list of players with high scores, and display them altogether in a TableLayout. I'm just having trouble with the row/column positions.
Here's my code:
public void onResume() {
super.onResume();
//=============================================
TextView number = new TextView(this);
number.setText("1");
TextView place = new TextView(this);
place.setText("4th");
TextView testScore = new TextView(this);
testScore.setText("113489");
table = new TableLayout(this);
//rows = new Stack<TableRow>();
TableRow row = new TableRow(this);
row.addView(number);
row.addView(place);
row.addView(testScore);
table.addView(row);
this.setContentView(table);
}
If anyone knows how I should change my code from the Current Situation to the mockup Expected Situation, I gladly appreciate it. If I'm doing something wrong, please post a comment. Thanks in advance.
Set the layout weight of each textview to 1 and the layout width to 0dp. That will cause them to split the available space equally. You could use layout gravity left, center and right as appropriate to further ensure maximum separation.
I just found a good link about TableLayout and TableRow, creating specific positions dynamically. Link is here. Of course, the code here is just the barebones of it, used to demostrate a simple position layout.
Here's my code and the given picture of the result:
public void onResume() {
super.onResume();
//=============================================
dip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) 1, this.getResources().getDisplayMetrics());
if (dip <= 0)
dip = 1;
TextView number = new TextView(this);
TextView place = new TextView(this);
TextView testScore = new TextView(this);
number.setText("1");
place.setText("4th");
testScore.setText("113489");
number.setWidth(50 * dip);
place.setWidth(75 * dip);
testScore.setWidth(150 * dip);
number.setPadding(20*dip, 0, 0, 0);
table = new TableLayout(this);
TableRow row = new TableRow(this);
row.addView(number);
row.addView(place);
row.addView(testScore);
table.addView(row, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
this.setContentView(table);
}
I'm actually astonished that there's a method for obtaining the DIP unit. Should've searched for that in the first place. :P

Categories