4

If I try to create weighted chains in a ConstraintLayout programmatically then no views are shown. Creating them in a layout xml file works fine.

I tried to set width of views to MATCH_CONSTRAINT, but then they disappear. Also setting a horizontal weight does not change anything.

This works:

<android.support.constraint.ConstraintLayout
    android:id="@+id/constraintLayoutTop"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    app:layout_constraintBottom_toTopOf="@+id/constraintLayoutBottom"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:gravity="center"
        android:text="1"
        app:layout_constraintBottom_toTopOf="@+id/textView3"
        app:layout_constraintEnd_toStartOf="@+id/textView2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:gravity="center"
        android:text="2"
        app:layout_constraintBottom_toTopOf="@+id/textView4"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView1"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:gravity="center"
        android:text="3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/textView4"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView1" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:gravity="center"
        android:text="4"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toBottomOf="@+id/textView2" />
</android.support.constraint.ConstraintLayout>

This does not work:

ConstraintLayout bottomLayout = findViewById(R.id.constraintLayoutBottom);
TextView textView;
ConstraintSet set;

List<List<Integer>> rows = new ArrayList<>();
List<Integer> col1 = new ArrayList<>();
List<Integer> col2 = new ArrayList<>();

col1.add(1);
col1.add(2);
col2.add(3);
col2.add(4);

rows.add(col1);
rows.add(col2);

for (int y = 0; y < rows.size(); y++) {
    List<Integer> cols = rows.get(y);
    for (int x = 0; x < cols.size(); x++) {
        Integer i = cols.get(x);

        textView = new TextView(getApplicationContext());
        textView.setText(i.toString());
        textView.setId(i);

        //ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_CONSTRAINT, ConstraintLayout.LayoutParams.WRAP_CONTENT);
        //textView.setLayoutParams(params); // this makes views disappear!

        bottomLayout.addView(textView);

        int leftId = i == 1 || i == 3 ? ConstraintSet.PARENT_ID : i - 1;
        int topId = i == 1 || i == 2 ? ConstraintSet.PARENT_ID : i - 2;
        int rightId = i == 2 || i == 4 ? ConstraintSet.PARENT_ID : i + 1;
        int bottomId = i == 3 || i == 4 ? ConstraintSet.PARENT_ID : i + 2;

        set = new ConstraintSet();
        set.clone(bottomLayout);
        //set.constrainWidth(textView.getId(), ConstraintSet.MATCH_CONSTRAINT); // this makes views disappear!
        set.connect(textView.getId(), ConstraintSet.LEFT, leftId, ConstraintSet.RIGHT, 0);
        set.connect(textView.getId(), ConstraintSet.TOP, topId, ConstraintSet.BOTTOM, 0);
        set.connect(textView.getId(), ConstraintSet.RIGHT, rightId, ConstraintSet.LEFT, 0);
        set.connect(textView.getId(), ConstraintSet.BOTTOM, bottomId, ConstraintSet.TOP, 0);
        set.applyTo(bottomLayout);
    }
}

How do I achieve the same in java?

General Grievance
  • 4,555
  • 31
  • 31
  • 45
masewo
  • 801
  • 9
  • 11
  • I need a 10x10 table and started with a `TableLayout` and multiple `TableRow` with nested `TextView`, but I could not manage to make them responsive. Looking great on big phones, but not on small ones or vise versa. – masewo Jan 29 '18 at 18:32
  • Just tried it out right now according to your sample code. But it is not responsive either. I have to add `layout_width` in `CardView` and if I pick `spanCount` of 10 then it exceeds display width. – masewo Jan 29 '18 at 19:39
  • If I have 10 `TextView` in a row, I want that they fill the whole display width, so I want a layout by percentage, what a `ConstraintLayout` should be able to do. – masewo Jan 29 '18 at 20:48
  • Finally I picked another approach with a `RecyclerView` and a `GridLayoutManager`. It is round about 10 times faster than with a `ConstraintLayout`. – masewo Jan 31 '18 at 21:42

2 Answers2

1

I think there are some issues to be addressed here.

For example, the code is missing the creation of the chains (both horizontal and vertical) and you only need to apply the ConstraintSet() once, after the configuration is finished.

I've tried to fix the code and it's working for me.

ConstraintLayout bottomLayout = findViewById(R.id.constraintLayoutBottom);
TextView textView;
ConstraintSet set = new ConstraintSet();

List<List<Integer>> rows = new ArrayList<>();
List<Integer> col1 = new ArrayList<>();
List<Integer> col2 = new ArrayList<>();

set.clone(bottomLayout);

col1.add(1);
col1.add(2);
col2.add(3);
col2.add(4);

rows.add(col1);
rows.add(col2);

for (int y = 0; y < rows.size(); y++) {
    List<Integer> cols = rows.get(y);
    for (int x = 0; x < cols.size(); x++) {
        Integer i = cols.get(x);

        textView = new TextView(getApplicationContext());
        textView.setText(i.toString());
        textView.setId(i);

        bottomLayout.addView(textView);

        int leftId = i == 1 || i == 3 ? ConstraintSet.PARENT_ID : i - 1;
        int topId = i == 1 || i == 2 ? ConstraintSet.PARENT_ID : i - 2;
        int rightId = i == 2 || i == 4 ? ConstraintSet.PARENT_ID : i + 1;
        int bottomId = i == 3 || i == 4 ? ConstraintSet.PARENT_ID : i + 2;

        set.connect(textView.getId(), ConstraintSet.LEFT, leftId, ConstraintSet.RIGHT, 0);
        set.connect(textView.getId(), ConstraintSet.TOP, topId, ConstraintSet.BOTTOM, 0);
        set.connect(textView.getId(), ConstraintSet.RIGHT, rightId, ConstraintSet.LEFT, 0);
        set.connect(textView.getId(), ConstraintSet.BOTTOM, bottomId, ConstraintSet.TOP, 0);
    }
}

set.createHorizontalChain(
    ConstraintSet.PARENT_ID,
    ConstraintSet.LEFT,
    ConstraintSet.PARENT_ID,
    ConstraintSet.RIGHT,
    new int[] {1, 2},
    null, // Here you can set a float array with the weights for your views
    ConstraintSet.CHAIN_SPREAD
)

set.createHorizontalChain(
    ConstraintSet.PARENT_ID,
    ConstraintSet.LEFT,
    ConstraintSet.PARENT_ID,
    ConstraintSet.RIGHT,
    new int[] {3, 4},
    null, // Here you can set a float array with the weights for your views
    ConstraintSet.CHAIN_SPREAD
)

set.createVerticalChain(
    ConstraintSet.PARENT_ID,
    ConstraintSet.TOP,
    ConstraintSet.PARENT_ID,
    ConstraintSet.BOTTOM,
    new int[] {1, 3},
    null, // Here you can set a float array with the weights for your views
    ConstraintSet.CHAIN_SPREAD
)

set.createVerticalChain(
    ConstraintSet.PARENT_ID,
    ConstraintSet.TOP,
    ConstraintSet.PARENT_ID,
    ConstraintSet.BOTTOM,
    new int[] {2, 4},
    null, // Here you can set a float array with the weights for your views
    ConstraintSet.CHAIN_SPREAD
)

set.applyTo(bottomLayout);
Dharman
  • 30,962
  • 25
  • 85
  • 135
Mike Grimm
  • 941
  • 11
  • 17
-2

Try using SequenceLayout. Is simpler and more flexible.