Aiming for Moonshot
Aiming for Moonshot

Reputation: 51

Strange consequence when use Constraint Layout in Android Studio

I'm in the beginning of Android Development. Recently, to practice layout designing I'm trying to build a simulation of simple calculator. I created and placed the views (Buttons, EditTexts) in the Design tab. Then I got stuck in "This view is not constrained" error so I searched on StackOverflow and finally found the solution is to right-click on the widget -> Constraint Layout -> Infer Constraints. But when I did it, those views in my program changed badly and I couldn't modify them to original places and sizes. How can I solve the error without change the views's locations and sizes?

This is my calculator before use Constraint Layout:

before_constraint:

enter image description here

And this is my calculator after use it:

after_constraint:

enter image description here

And this is my source code:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.huy9515gmail.helloworld.MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp">


<Button
    android:id="@+id/button10"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="0"
    tools:layout_editor_absoluteX="87dp"
    tools:layout_editor_absoluteY="186dp" />

<Button
    android:id="@+id/button7"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="7"
    tools:layout_editor_absoluteX="34dp"
    tools:layout_editor_absoluteY="141dp" />

<Button
    android:id="@+id/button8"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="8"
    tools:layout_editor_absoluteX="87dp"
    tools:layout_editor_absoluteY="141dp" />

<Button
    android:id="@+id/button9"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="9"
    tools:layout_editor_absoluteX="140dp"
    tools:layout_editor_absoluteY="141dp" />

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="My First Calculator"
    tools:layout_editor_absoluteX="134dp"
    tools:layout_editor_absoluteY="16dp" />

<Button
    android:id="@+id/button"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="2"
    tools:layout_editor_absoluteX="87dp"
    tools:layout_editor_absoluteY="51dp" />

<Button
    android:id="@+id/button3"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="3"
    tools:layout_editor_absoluteX="140dp"
    tools:layout_editor_absoluteY="51dp" />

<Button
    android:id="@+id/button4"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="/"
    tools:layout_editor_absoluteX="281dp"
    tools:layout_editor_absoluteY="96dp" />

<Button
    android:id="@+id/button14"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="x"
    tools:layout_editor_absoluteX="228dp"
    tools:layout_editor_absoluteY="96dp" />

<Button
    android:id="@+id/button13"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="-"
    tools:layout_editor_absoluteX="281dp"
    tools:layout_editor_absoluteY="51dp" />

<Button
    android:id="@+id/button12"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="+"
    tools:layout_editor_absoluteX="228dp"
    tools:layout_editor_absoluteY="51dp" />

<Button
    android:id="@+id/button11"
    android:layout_width="106dp"
    android:layout_height="40dp"
    android:text="Delete"
    tools:layout_editor_absoluteX="228dp"
    tools:layout_editor_absoluteY="210dp" />

<Button
    android:id="@+id/button16"
    android:layout_width="106dp"
    android:layout_height="40dp"
    android:text="Calculate"
    tools:layout_editor_absoluteX="228dp"
    tools:layout_editor_absoluteY="170dp" />

<Button
    android:id="@+id/button15"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="1"
    tools:layout_editor_absoluteX="34dp"
    tools:layout_editor_absoluteY="51dp" />

<Button
    android:id="@+id/button2"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="4"
    tools:layout_editor_absoluteX="34dp"
    tools:layout_editor_absoluteY="96dp" />

<Button
    android:id="@+id/button5"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="5"
    tools:layout_editor_absoluteX="87dp"
    tools:layout_editor_absoluteY="96dp" />

<Button
    android:id="@+id/button6"
    android:layout_width="53dp"
    android:layout_height="45dp"
    android:text="6"
    tools:layout_editor_absoluteX="140dp"
    tools:layout_editor_absoluteY="96dp" />

<EditText
    android:id="@+id/editText"
    android:layout_width="310dp"
    android:layout_height="98dp"
    android:ems="10"
    android:inputType="textPersonName"
    tools:layout_editor_absoluteX="37dp"
    tools:layout_editor_absoluteY="327dp" />

Upvotes: 0

Views: 1974

Answers (2)

Martin Marconcini
Martin Marconcini

Reputation: 27226

The hardcoded values came when you did “infer constraints”. I suggest you delete all your layout and start over, understanding how Constraint Layout works. If you see a "This view is not constrained” error, what Android Studio is telling you is: The view needs more constraints.

Remember the core rule for (both) AutoLayout on iOS and ConstraintLayout on Android: Every view needs to know where to position itself (both horizontally and vertically) and it also needs to know what its size will be, again, both width and height.

So, think about your layout… I’ll give you an example.

Starting from the top, you want that “Label” to be centered with the text “Welcome to my Calculator”.

Good, now the engine needs to know 4 things:

  1. Where in the X axis do I put this Label?
  2. Where in the Y axis do I put this label?
  3. What is the width of this label?
  4. What is the height of this label?

There are ways to let the engine infer some of these (as we shall see), but for the most part, you need these four, per view (regardless of whether they are inferred or explicit).

So let’s start with your “Title” there.

The TextView will be centered, but I’m sure you want it to span all the width it can find (and compress in case it needs to). Since ConstraintLayout doesn’t have a match_parent (for obvious reasons: a.k.a.: the idea is that you have to set the constraints), we have to be able to do it differently…

For the X axis (Horizontal), we want the textView to be pinned to the start of the parent (aka: the root in this case), and to the end of the parent as well (effectively using all the screen, minus any margins you decide to add on either side).

So far, two constraints. For the above to work, ConstraintLayout says you have to use the “special” value of 0dp in the width. This tells the engine that the width will be “Any value I don’t know yet that I will know after I calculate all the constraints”.

Good. Now we have solved #1 and #3.

For #2 and #4 you can do a similar thing… or you can enjoy the fact that some views, have inferred values. E.g.: text views don’t need a height, they will auto-size based upon the font size, number of characters, etc., but you still need to tell it where in the Y axis this text view will go.

In your case, I’d just align the text view’s top with your parent.top. Notice you don’t need to tell the layout to pin the bottom of your text to anything, since it will have height = wrap_content.

And so forth…

Now head over the official docs and start reading more about the things you can do (chains, for example, may come in handy here).

Upvotes: 2

Cheticamp
Cheticamp

Reputation: 62821

None of your views are constrained, although they all have design-time positions. Take a look at this documentation regarding run-time constraints. This is also a good introduction.

The design-time positions are the things that look like this:

tools:layout_editor_absoluteY="81dp"
tools:layout_editor_absoluteX="0dp"

This code will position your view in the designer. Run-time constraints look like this:

app:layout_constraintBottom_toBottomOf=”@+id/constraintLayout”
app:layout_constraintEnd_toStartOf=”@+id/imageView” 
app:layout_constraintStart_toStartOf=”@+id/constraintLayout”

and will position your view at runtime (and in the designer.)

Unfortunately, when you inferred constraints some bad things happened. The designer made its best guess but it was not what was wanted.

I suggest that you take your layout view-by-view, delete the design-time constraints and add in the run-time constraints until your layout is looking like you want.

Upvotes: 0

Related Questions