How to resize background image in Android programmatically?

2

I am placing a background image in an Activity obtained from the drawable folder, this is the code I implemented for that action:

ConstraintLayout constraintLayout = (ConstraintLayout)findViewById(R.id.principal);
// Obtener la imagen desde Drawable
Drawable image  = ContextCompat.getDrawable(getApplicationContext(), R.drawable.alert);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    // Colocar la imagen de fondo de pantalla
    constraintLayout.setBackground(image);
}

But when you run it in the emulator you see the big image:

Image View

What I want is to resize the image so that it is centered and with a width and height programmatically defined something like that.

What you want to get

  

Any way to resize the image?

EDITING

This is a solution taking into account what is recommended by @Andrespengineer and making use of the class ConstraintSet in this way I could achieve what was committed maybe not the most viable but at the moment it works.

XML file:

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

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Activity code:

int recurso = getResources().getIdentifier("alert", "drawable", getPackageName());

ImageView imageView = new ImageView(this);
imageView.setId(R.id.image);
imageView.setImageResource(recurso);

ConstraintLayout constraintLayout = findViewById(R.id.principal);

ConstraintLayout.LayoutParams imageConstraint = new ConstraintLayout.LayoutParams(
        ConstraintLayout.LayoutParams.MATCH_PARENT,
        ConstraintLayout.LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(imageConstraint);
constraintLayout.addView(imageView);

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

constraintSet.connect(imageView.getId(), ConstraintSet.TOP, constraintLayout.getId(), ConstraintSet.TOP, 400);
constraintSet.connect(imageView.getId(), ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, 400);
constraintSet.connect(imageView.getId(), ConstraintSet.RIGHT, constraintLayout.getId(), ConstraintSet.RIGHT, 400);
constraintSet.connect(imageView.getId(), ConstraintSet.BOTTOM, constraintLayout.getId(), ConstraintSet.BOTTOM, 400);

constraintSet.applyTo(constraintLayout);
    
asked by A. Palacio 27.04.2018 в 21:10
source

1 answer

3

If you want to add the background property as a background to a Views you should make sure the image is have the same dimensions as the view. Otherwise it will lose its scale and it will look very narrow or enlarged causing it to lose its pixels depending on its size.

My recommendation is to create a ImageView that has the same dimensions as the parent view. ImageView is made to define the image resources so it has properties that manipulate those images in relation to the view. What you need is to define in your layout a ImageView that suits your parent view. Defining a Z order (superimpose Views) more deeply than all the elements in your view.

A layout that contains a container child of type LinearLayout does not let you superimpose elements since its order is linear. Therefore, you could not establish an ImageView with the same dimensions if there are more children.

The trick is to use Layouts containers as RelativeLayout or FrameLayout which if you are allowed to add children that define a Z order (overlay Views). For example:

Progressively the Views have a method called .bringToFront(); this makes the Z order the child is sent to the front of everyone. If you try to do this in a Layout that is not container type. It will simply make your child establish an order of the Layout type. For example the Linear, sends it to the front of the others of the Order X and Order Y if its orientation is horizontal or vertical, respectively (because it is linear).

Having said that, your solution should be as follows:

In the axml of your Layout. Define a FrameLayout so that your view content says, Your Constraintlayout must be inside the FrameLayout. With corresponding width and height properties. Note that match_parent matches the size of the parent. wrap_content to the size defined by your children.

If it's the first child, add in your layout to avoid error in the xmlns space: xmlns:android="http://schemas.android.com/apk/res/android"

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/flContainer"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <ImageView
        android:id="@+id/ivBackground"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:scaleType="centerInside"
        android:src="@drawable/alert"/>
     . . .
          <!-- Aqui debe ir el ConstraintLayout -->
     . . .

</FrameLayout>

If you want to do it Programmatically create a ImageView the size of your father:

You initialize the container:

FrameLayout flContainer = (FrameLayout) findViewById(R.id.flContainer);

ImageView ivBackground = new ImageView(this); // this hace referencia al contexto

FrameLayout.LayoutParams fllp = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT);

fllp.gravity = Gravity.CENTER; // Centrar la vista
ivBackground.setScaleType(ImageView.ScaleType.CENTER_INSIDE); // Esto hara que la imagen se centre en el imageview que lo contiene, sin perder su escala
ivBackground.setLayoutParams(fllp);

The parameters or LayoutParams must be the same type as the one that the view will contain. In this case, who contains that view is the FrameLayout. Then to the container you want to add your dynamically created view if you inherit from ViewGroup you do:

flContainer.addView ... this method has variants that allow you to define the position of the View, the parameters (equal to other parameters of another view, etc ...) or order in the container. In this case, the first child must be the ImageView, so you must add it in that position.

flContainer.addView(ivBackground, 0); // Esto hara que el Constraint quede encima de la imagen del background.

You can see more types of scale from ImageView in this link . For example, if your image is very small by making wrap_content , you can define a fixed size in dp in axml and make fitXY but keep in mind that you will lose quality if the size is larger than your image. Good luck.

To set the image once the resource has been added dynamically:

ivBackground.setImageResource(R.drawable.alert);
    
answered by 27.04.2018 / 23:21
source