Search code examples
androidimageviewandroid-bitmapaspect-ratio

How to fit a bitmap in a rounded square?


I'm using Android Studio and I would like to be able to pickup am image from the gallery, resize it and make it fit inside a rounded square (of about 300x300px) by maintaining the correct aspect ratio. At the moment, I'm able to resize it and display it as a circle.

 FixBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
 bitmap_to_save = scaleBitmapAndKeepRation(FixBitmap, 320, 320);
               
 RoundedBitmapDrawable roundDrawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap_to_save);
 roundDrawable.setCircular(true);
 p_avatar.setImageDrawable(roundDrawable);

However, I would like to know if it is possible to make the bitmap look like my attached image. Moreover, it would be important for me to resize the image without losing the original aspect ratio.

enter image description here

It is not exactly a well square rounded figure, so I'm not sure that it is possible to do it in Android.

Please, keep in mind that I dynamically change the imageview inside the code depending on the user actions. So this is not a static image, I replace the original content with a new one if the user upload a new image.

EDIT #1 on May, 20

This is my XML code for the imageview "avatar":

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ll_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="loginpackage.social.com.ui.profile.ProfileActivity">

    <include layout="@layout/custom_toolbar_shadow" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fillViewport="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_horizontal"
            android:orientation="vertical"
            android:paddingTop="@dimen/_20sdp">


            <ImageView
                android:id="@+id/avatar"
                android:layout_width="137dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:clickable="true"
                android:paddingBottom="@dimen/_10sdp"
                android:paddingTop="@dimen/_10sdp"
                />


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/_20sdp"
                android:orientation="vertical"
                android:paddingLeft="@dimen/_16sdp"
                android:paddingRight="@dimen/_16sdp">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/profileActivity_name"
                    android:textSize="@dimen/_14sdp" />

                <EditText
                    android:id="@+id/et_fullname"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/_5sdp"
                    android:background="@color/colorWhite"
                    android:hint="@string/signActivity_fullname"
                    android:imeOptions="actionDone"
                    android:inputType="textNoSuggestions"
                    android:maxLines="1"
                    android:padding="@dimen/_10sdp" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/_10sdp"
                    android:text="@string/profileActivity_email"
                    android:textSize="@dimen/_14sdp" />

                <EditText
                    android:id="@+id/et_email"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/_5sdp"
                    android:background="@drawable/editext_back_login"
                    android:hint="@string/mainActivity_email"
                    android:imeOptions="actionNext"
                    android:inputType="textEmailAddress|textNoSuggestions"
                    android:maxLines="1"
                    android:padding="@dimen/_10sdp" />

                <Button
                    android:id="@+id/btn_update"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/_20sdp"
                    android:background="@color/colorSignuoBtn"
                    android:text="@string/profileActivity_update"
                    android:textColor="@color/colorWhite"
                    android:textSize="@dimen/_12sdp"
                    android:visibility="invisible" />

                <TextView
                    android:id="@+id/txt_logout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginBottom="@dimen/_10sdp"
                    android:layout_marginTop="@dimen/_20sdp"
                    android:background="@drawable/button_logout_profile"
                    android:foreground="?attr/selectableItemBackgroundBorderless"
                    android:gravity="center"
                    android:paddingBottom="@dimen/_12sdp"
                    android:paddingTop="@dimen/_12sdp"
                    android:text="@string/profileActivity_logout"
                    android:textSize="@dimen/_12sdp" />
            </LinearLayout>
        </LinearLayout>
    </ScrollView>
</LinearLayout>

EDIT #2

At the moment, I'm using Picasso to round the image and it seems to work well.

The problem is that I would like to keep always the same picture size (350x350px) and the aspect ratio. How is it possible to do it?

 Transformation transformation = new RoundedTransformationBuilder()
                    .borderColor(Color.GREEN)
                    .borderWidthDp(2)
                    .cornerRadiusDp(15)
                    .oval(false)
                    .build();

            Picasso.get().load("http://www.server.com/uploads/avatars/"+Conts.USERINFO.getId()).transform(transformation).memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE).networkPolicy(NetworkPolicy.NO_CACHE) .into(p_avatar);

EDIT #3

 <com.makeramen.roundedimageview.RoundedImageView
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/avatar"
            android:layout_width="160dp"
            android:layout_height="160dp"
            android:src="@drawable/adduserprofile"
            android:scaleType="centerCrop"
            app:riv_border_width="2dip"
            app:riv_border_color="#333333"
            app:riv_mutate_background="true"
            app:riv_oval="false"
            app:riv_corner_radius_bottom_left="20dp"
            app:riv_corner_radius_top_right="20dp"
            />

Why if I set a different value for riv_corner_radius_top_right, then the app crashes? For example, if I set:

 app:riv_corner_radius_bottom_left="20dp"
 app:riv_corner_radius_top_right="10dp"

I get this error:

  E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: loginpackage.social.com, PID: 25495
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{loginpackage.social.com/loginpackage.social.com.ui.profile.ProfileActivity}: android.view.InflateException: Binary XML file line #24: Error inflating class com.makeramen.roundedimageview.RoundedImageView
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2689)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2754)
                      at android.app.ActivityThread.access$900(ActivityThread.java:177)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:145)
                      at android.app.ActivityThread.main(ActivityThread.java:5938)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:372)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
                   Caused by: android.view.InflateException: Binary XML file line #24: Error inflating class com.makeramen.roundedimageview.RoundedImageView
                      at android.view.LayoutInflater.createView(LayoutInflater.java:640)
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:750)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
                      at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:287)
                      at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:139)
                      at loginpackage.social.com.ui.profile.ProfileActivity.onCreate(ProfileActivity.java:93)
                      at android.app.Activity.performCreate(Activity.java:6288)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2642)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2754) 
                      at android.app.ActivityThread.access$900(ActivityThread.java:177) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:145) 
                      at android.app.ActivityThread.main(ActivityThread.java:5938) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:372) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Constructor.newInstance(Native Method)
                      at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
                      at android.view.LayoutInflater.createView(LayoutInflater.java:614)
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:750) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:813) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:511) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:415) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:366) 
                      at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:287) 
                      at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:139) 
                      at loginpackage.social.com.ui.profile.ProfileActivity.onCreate(ProfileActivity.java:93) 
                      at android.app.Activity.performCreate(Activity.java:6288) 
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2642) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2754) 
                      at android.app.ActivityThread.access$900(ActivityThread.java:177) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:145) 
                      at android.app.ActivityThread.main(ActivityThread.java:5938) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:372) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 
                   Caused by: java.lang.IllegalArgumentException: Multiple nonzero corner radii not yet supported.
                      at com.makeramen.roundedimageview.RoundedDrawable.setCornerRadius(RoundedDrawable.java:507)
                      at com.makeramen.roundedimageview.RoundedImageView.updateAttrs(RoundedImageView.java:368)
                      at com.makeramen.roundedimageview.RoundedImageView.updateDrawableAttrs(RoundedImageView.java:318)
                      at com.makeramen.roundedimageview.RoundedImageView.<init>(RoundedImageView.java:163)
                      at com.makeramen.roundedimageview.RoundedImageView.<init>(RoundedImageView.java:86)
                      at java.lang.reflect.Constructor.newInstance(Native Method) 
                      at java.lang.reflect.Constructor.newInstance(Constructor.java:288) 
                      at android.view.LayoutInflater.createView(LayoutInflater.java:614) 
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:750) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:813) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:511) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:415) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:366) 
                      at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:287) 
                      at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:139) 
                      at loginpackage.social.com.ui.profile.ProfileActivity.onCreate(ProfileActivity.java:93) 
                      at android.app.Activity.performCreate(Activity.java:6288) 
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2642) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2754) 
                      at android.app.ActivityThread.access$900(ActivityThread.java:177) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:145) 
                      at android.app.ActivityThread.main(ActivityThread.java:5938) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:372) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 

Solution

  • You should not give your time to manage these types of logics if you are working on projects in company.

    Instead you can just use libraries which have already done great work. See https://github.com/vinc3m1/RoundedImageView

    Your ImageView will be like

    <com.makeramen.roundedimageview.RoundedImageView
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/imageView1"
            android:src="@drawable/photo1"
            android:scaleType="centerCrop"
            app:riv_corner_radius="30dip"
            app:riv_border_width="2dip"
            app:riv_border_color="#333333"
            app:riv_mutate_background="true"
            app:riv_tile_mode="repeat"
            app:riv_oval="true" />
    

    and dependency

    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile 'com.makeramen:roundedimageview:2.3.0'
    }
    

    Update

    You seem new to android, if you don't understand id and src, no worries!

    Basically id is an unique id that you have created and you refer to imageView1 if you do findViewById(R.id.imageView1) in your java code.

    for more info about id : Difference between "@id/" and "@+id/" in Android

    src is the source image file for that image, that is located in your drawables directory.

    About your issue

    You can use different ImageView ScaleType that matches your requirement. I think you use android:scaleType="centerCrop" that fit your image at imageView.

    I also edited scaleType in above answer. If that does not fit your requirement you can use any of these scale type

    Update 2 for setting width and height, you can set layout_width and layout_height attribute. like below.

     <com.makeramen.roundedimageview.RoundedImageView
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:id="@+id/imageView1"
                android:src="@drawable/photo1"
                android:scaleType="centerCrop"
                app:riv_corner_radius="30dip"
                app:riv_border_width="2dip"
                app:riv_border_color="#333333"
                app:riv_mutate_background="true"
                app:riv_tile_mode="repeat"
                app:riv_oval="true" 
                android:layout_width="350dp"
                android:layout_height="350dp"/>
    

    see What is the difference between "px", "dip", "dp" and "sp"? for more detail about sp, dp, px in android.