0

I am learning android and doing a simple calculator. I am building the calculator inputs button programmatically by iterating a list of operator labels like such

final String[] inputLabels = {"9", "8", "7", "/", "6" ...}

It will be 4 rows and 4 columns like this

// please do not mind me about the design
9 8 7 /
6 5 4 x
1 2 3 -
0 AC = +

Those inputs will be under ConstraintLayout, because I want to learn using it. But before going into my logic of how constrainting those inputs from my 1D array, I want to test if simple code such as creating 2 buttons and constraint them works, which it does not and that is the main problem I want to solve here.

I already tried googling it and they all seems very simple, it is strange that I could not achieve such simple thing and I tried to google my problem but I found nothing(sorry If those problem exists and I didnt found it)

These below are what I tried to follows:

Here is the main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="calculatedValue"
            type="java.lang.String"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/mainLayout"
        tools:context=".MainActivity">

        <include
            layout="@layout/calculate_value_display"
            bind:calculatedValue="@{calculatedValue}" />

        <fragment
            android:name="com.example.calculator.CalculatorInputs"
            android:id="@+id/calculatorInputs"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </LinearLayout>
</layout>

The calculator_inputs.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".CalculatorInputs"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.constraint.ConstraintLayout
        android:id="@+id/calculatorInputs"
        android:paddingLeft="10sp"
        android:paddingRight="10sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </android.support.constraint.ConstraintLayout>
</FrameLayout>

The MainActivity.java is just what it is when the project created and here is the CalculatorInputs.java

package com.example.calculator;

import android.os.Bundle;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import java.util.ArrayList;

public final class CalculatorInputs extends Fragment {
  private final String[] inputLabels = {"7", "8", "9", "/", "4", "5", "6", "x", "1", "2", "3", "-", "0", "AC", "=", "+"};

  private final ConstraintLayout.LayoutParams buttonConstraintLayout =
      new ConstraintLayout.LayoutParams(220, 150);

  private final float buttonTextSize = 20.f;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View rootView = inflater.inflate(R.layout.calculator_inputs, container, false);

    return rootView;
  }

  @Override
  public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final ConstraintLayout layout = (ConstraintLayout) view.findViewById(R.id.calulatorInputs);

    ConstraintLayout.LayoutParams layoutParams;

    final ArrayList<Button> buttons = new ArrayList<Button>(this.inputLabels.length);

    while (buttons.size() < this.inputLabels.length) {
      buttons.add(null);
    }

    int buttonIndex = 0;

    //////////////////////////////////////////////////////////////////
    /////////////////////////// BEGIN HERE ////////////////////////////
    //////////////////////////////////////////////////////////////////

    final ConstraintSet constraintSet = new ConstraintSet();
    constraintSet.clone(layout);

    final Button button1 = this.createButton("X");
    final Button button2 = this.createButton("Y");

    layout.addView(button1);

    constraintSet.connect(
      button1.getId(),
      ConstraintSet.RIGHT,
      ConstraintSet.PARENT_ID,
      ConstraintSet.RIGHT
    );

    constraintSet.connect(
      button1.getId(),
      ConstraintSet.TOP,
      ConstraintSet.PARENT_ID,
      ConstraintSet.TOP
    );

    constraintSet.applyTo(layout);

    layout.addView(button2);

    constraintSet.connect(
      button2.getId(),
      ConstraintSet.RIGHT,
      ConstraintSet.PARENT_ID,
      ConstraintSet.RIGHT
    );

    constraintSet.connect(
      button2.getId(),
      ConstraintSet.TOP,
      ConstraintSet.PARENT_ID,
      ConstraintSet.TOP
    );

    ///////////////////////////////////////////////////////////////////
    /////////////////////////// END HERE /////////////////////////////
    //////////////////////////////////////////////////////////////////
  }

  Button createButton(final String buttonLabel) {
    final Button button = new Button(this.getActivity());

    button.setLayoutParams(this.buttonConstraintLayout);
    button.setText(buttonLabel);
    button.setTextSize(this.buttonTextSize);
    button.setId(View.generateViewId());

    return button;
  }
}

So below are the expected output and the reality:

shadowlegend
  • 373
  • 2
  • 7
  • 21

2 Answers2

0

You should execute constraintSet.clone(layout) after layout.addView(button1). BTW,you can use Layout Inspector to check your layout running on the device,it shows a View Tree and you can find where is your buttons gone.

Update:Change your button.setLayoutParams(this.buttonConstraintLayout); to button.setLayoutParams(new ConstraintLayout.LayoutParams(220, 150)); in createButton,do not share the View's LayoutParams object.

JiajiaGu
  • 1,279
  • 14
  • 10
  • Thanks @JiajiaGu. You helped me learned another step to debug the UI in android. So I inspect the layout using the layout inspector, i found out that both of my button have 0 width and height and also their position are the same, which means they are still overlapping. Strange when I do not set constraint on them, they have expected width and height, just they are overlapping each other since it is being put inside `ConstraintLayout` – shadowlegend Apr 24 '19 at 12:52
0

The problem here is that I shared the LayoutParams for every button creation, that is why it didnt work.

Inside the createButton method, it works if I changed to this

  Button createButton(final String buttonLabel) {
    final Button button = new Button(this.getActivity());

    button.setLayoutParams(new ConstraintLayout.LayoutParams(220, 150);
    button.setText(buttonLabel);
    button.setTextSize(this.buttonTextSize);
    button.setId(View.generateViewId());

    return button;
  }
shadowlegend
  • 373
  • 2
  • 7
  • 21