1

I'm having some difficulty with a runtime-generated UI that isn't following constraints. Per other answers and documentation for Android, I have tried ConstraintSet as well as some other methods.

I am extending ConstraintLayout for a custom class that has an integral part in the app's functionality. I pull data from a web server that then creates these objects and adds them to a LinearLayout. The LinearLayout, ConstraintLayout, and TextViews all show their proper sizes; however, the TextViews overlap one another and refuse to follow any constraints.

I can create a copy of what I want to do manually through the layout editor, and it works fine.

My current setup (this extends ConstraintLayout, text_name and text_points are TextViews):

    this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

    this.addView(text_name);
    this.addView(text_points);

    ConstraintSet constraints = new ConstraintSet();

    constraints.clone(this);

    constraints.constrainHeight(text_points.getId(), WRAP_CONTENT);
    constraints.constrainWidth(text_points.getId(), WRAP_CONTENT);
    constraints.constrainHeight(text_name.getId(), WRAP_CONTENT);
    constraints.constrainWidth(text_name.getId(), WRAP_CONTENT);

    constraints.connect(text_name.getId(), LEFT, getId(), LEFT);
    constraints.connect(text_points.getId(), RIGHT, getId(), RIGHT);

    constraints.applyTo(this);

constrainWidth and constrainHeight work; when I get rid of them or change the values, it has an effect. Any of the connect business, however, does nothing. The TextViews have the right sizes for their text, but fail to obey any constraints. Am I missing some line that makes .connects work?

To clarify: I have ScrollView -> LinearLayout -> ConstraintLayout -> TextViews. When created in-editor, constraints work fine. When created in the instantiation of the ConstraintLayout at runtime using a ConstraintSet, connected constraints have no effect, but other properties do.

Display in-app - TextViews overlap, not following constraints

EDIT: Just to confirm, here's an output of the # of rows added to the LinearLayout (LOCS), size of the LinearLayout (LDIM), size of the ConstraintLayout (LOCDIM), and sizes of the TextViews (TVDIM, TV2DIM):

09-03 14:19:18.664 D/LOCS: 2
09-03 14:19:18.665 D/LDIM: 1080 w
09-03 14:19:18.665 D/LDIM: 58 h
09-03 14:19:18.665 D/LOCDIM: 1080 w
09-03 14:19:18.666 D/LOCDIM: 29 h
09-03 14:19:18.667 D/TVDIM: 165 w
09-03 14:19:18.667 D/TVDIM: 29 h
09-03 14:19:18.668 D/TV2DIM: 29 w
09-03 14:19:18.668 D/TV2DIM: 29 h

2 Answers2

0

See this answer, I think you are missing the clone() instruction.

Add view programatically in ConstraintLayout

Juan
  • 5,525
  • 2
  • 15
  • 26
  • No luck with this one. Is it possible it would have to be done after first render? – Carson Wilber Sep 03 '17 at 19:13
  • These methods I assumed were used in an onCreate Activity method or an onCreateView Fragment method. I have never tried it as part of the View. If you post your layout I may be able to provide additional info. I think the way your are trying is more complicated. – Juan Sep 03 '17 at 19:33
  • I am streaming data from a web server given the current location of the device. Surely dynamically loading data has been done before! The layout is as said before - `ScrollView` -> `LinearLayout` -> `ConstraintLayout` -> `TextView`. ConstraintLayout and TextViews are created when data is loaded. Extended ConstraintLayout for custom constructor in order to pass data around. The snippet above is from the constructor of the extending class. – Carson Wilber Sep 03 '17 at 19:50
0

The problem is that, programmatically, View ids are not properly assigned. I discovered this while attempting different combinations of margin, width, height, scale, and rotation - the two views all had the same changes applied to them.

The solution is to set the IDs yourself by generating them in some way. However, targeting low API versions (<17), View.generateViewId() is not allowed; thus, you have to use one of those unfortunately ugly blocks wrapped around it:

int view_id;

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
    view_id = View.generateViewId();
} else {
    view_id = new Random(System.currentTimeMillis()).nextInt();
}

view.setId(view_id);

From then on, you may use view_id or view.getId() for ConstraintSet.

For the parent of the Views you want to add to the ConstraintLayout, you can use ConstraintSet.PARENT_ID.