Search code examples
androidimageviewprogrammatically-createdconstraintset

clone and applyTo from ConstraintSet making app crashing


I'm trying to create some constraints for a programmatically created ImageView, but when I run the app, it crashes (Unfortunately, pruebaConstraint has stopped. message). As the title says, the crash ocurs when I add the line cs.clone(constraintLayout) o cs.applyTo(constraintLayout). I've tried several variations but nothing is working. I'm stuck here and don't know what else to do. I guess it has to do with objects created in the XML file.

activity_main.xml:

<?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:id="@+id/parentLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.constraint.Guideline
        android:id="@+id/h1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.2" />

    <android.support.constraint.Guideline
        android:id="@+id/h2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent=".8" />

    <android.support.constraint.Guideline
        android:id="@+id/v2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent=".9" />

    <android.support.constraint.Guideline
        android:id="@+id/v1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="0dp"
        app:layout_constraintGuide_percent=".1" />


</android.support.constraint.ConstraintLayout>

MainActivity.java:

package com.example.zzz.pruebaconstraint;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.constraint.Guideline;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    public ConstraintLayout constraintLayout;
    public ConstraintSet cs;
    public Guideline h1,h2,v1,v2;
    public TextView tv;
    public ImageView infinito;
    public Bitmap dibujo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        constraintLayout = findViewById(R.id.parentLayout);
        h1 = findViewById(R.id.h1);
        h2 = findViewById(R.id.h2);
        v1 = findViewById(R.id.v1);
        v2 = findViewById(R.id.v2);

        dibujo = BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_infinitum_foreground);
        infinito = new ImageView(getApplicationContext());
        infinito.setImageBitmap(dibujo);
        constraintLayout.addView(infinito);

        cs = new ConstraintSet();
        cs.clone(constraintLayout);




        cs.connect(infinito.getId(), ConstraintSet.BOTTOM, h2.getId(), ConstraintSet.TOP);
        cs.connect(infinito.getId(), ConstraintSet.END, v2.getId(), ConstraintSet.START);
        cs.connect(infinito.getId(), ConstraintSet.START, v1.getId(), ConstraintSet.START);
        cs.connect(infinito.getId(), ConstraintSet.TOP, h1.getId(), ConstraintSet.TOP);

        cs.applyTo(constraintLayout);    
    }
}

As I understand, I need to clone the layout (in this case parentLayout) in order to add the constraints set to the ImageView infinito.

By the way, the ImageView object infinito is rendered (appears in the screen in its default position) when created through code and constraints are not yet created.

UPDATE: If I create the ImageView object in the XML file,

cs.clone(constraintLayout);

and

cs.applyTo(constraintLayout);

work correctly and the ImageView is set in the position constraints dictate.


Solution

  • Ok, maybe someone will find this useful. The problem was related to the ID of the View object (in this case an ImageView). I thought when you initialize the object, the id was automatically set to a valid value, but is set to -1 (View.NO_ID constant), which is an invalid value.

    The thing is that I added the instruction:

    infinito.setId(View.generateViewId());
    

    after:

    infinito = new ImageView(getApplicationContext());
    

    so the object is having an appropiate ID and now the app is running without stopping abruptly.

    PS: In terms of performance, what is better? or is it the same?

    infinito.setId(View.generateViewId());
    

    or

    int id = View.generateViewId();
    infinito.setId(id);
    

    Besides, why is the id not set when calling the constructor?

    Cheers.