3

I'm having trouble using this library to make one of my images into a circle dynamically. Here is my attempt:

private void drawerSetup() {
    Profile profile = Profile.getCurrentProfile();
    ProfilePictureView profilePictureView = (ProfilePictureView) findViewById(R.id.profile_image);
    CircularImageView circularProfilePicture = (CircularImageView)    findViewById(R.id.profile_image_circle);
    if(profilePictureView != null) {
        profilePictureView.setProfileId(profile.getId());
        ImageView imageView = ((ImageView)profilePictureView.getChildAt(0));
        Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
        circularProfilePicture.setImageBitmap(bitmap);
    }
}

Layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    xmlns:facebook="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/tools"
    android:background="@drawable/side_nav_bar"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:orientation="vertical"
    android:gravity="bottom"
    app:showIn="@layout/activity_news_feed">

<com.facebook.login.widget.ProfilePictureView
    android:id="@+id/profile_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    facebook:com_facebook_preset_size="normal"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:paddingBottom="8dp"
    android:layout_centerInParent="true" />

<com.mikhaellopez.circularimageview.CircularImageView
    android:layout_width="100dp"
    android:layout_height="100dp"
    app:border_color="#EEEEEE"
    app:border_width="2dp"
    app:shadow="true"
    app:shadow_radius="10"
    android:id="@+id/profile_image_circle"
    app:shadow_color="#000000"
    android:layout_alignBottom="@+id/profile_image"
    android:layout_toLeftOf="@+id/profile_image"
    android:layout_toStartOf="@+id/profile_image" />

I know that my profilePictureView is displaying correctly when i call profilePictureView.setProfileId(profile.getId()); On my layout, it displays correctly. However, when I try to call the circularProfilePicture, I simply get an "empty" photo. It doesn't seem like the bitmap for the image isn't being recognized/set correctly. The image doesn't display as the profilePictureView does. Any ideas why this might happen?

user1871869
  • 3,079
  • 10
  • 46
  • 95
  • which lib you used ? Always put much information as possible. Also, did you look into logcat ? is there any exception raising ? – Murtaza Khursheed Hussain Nov 17 '15 at 10:56
  • http://stackoverflow.com/questions/23464707/display-fb-profile-pic-in-circular-image-view-in-application – IntelliJ Amiya Nov 17 '15 at 11:08
  • Its look like it is waiting for Image response. try to get image after a delay. – Murtaza Khursheed Hussain Nov 17 '15 at 11:24
  • @MurtazaKhursheedHussain there was no exception (not that I am aware of) and I was using https://github.com/lopspower/CircularImageView library. How would I set such a delay? – user1871869 Nov 17 '15 at 17:44
  • Whenever you use `profilePictureView` to the users picture, it actually sends an Async HTTP request to get the data, on the next line you are getting the bitmap set by the `profilePictureView` which was set empty by default. That's why you are not getting image in your `CircularView`. Library is working as expected, I tried myself. – Murtaza Khursheed Hussain Nov 18 '15 at 04:39
  • In order to introduce a little delay before getting the image in `CircularView` use either the `Handler` `postDelayed` method or [Timer](https://developer.android.com/reference/java/util/Timer.html#schedule(java.util.TimerTask, long, long)) In order to introduce a little delay before getting the image in `CircularView` use either the `Handler` `postDelayed` method or `Timer` class for introducing delay class for introducing delay – Murtaza Khursheed Hussain Nov 18 '15 at 04:41

5 Answers5

8

After using different image library (including Picasso), I finished to use Facebook one named Fresco. It's much faster with less code, everyting works as it should.

Fresco support:

  • streaming of progressive JPEGs
  • display of animated GIFs and WebPs
  • extensive customization of image loading and display

The doc says too that

In Android 4.x and lower, Fresco puts images in a special region of Android memory. This lets your application run faster - and suffer the dreaded OutOfMemoryError much less often.

It also support rounded corner as you are searching, see here.

Layout example:

        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/avatarImageView"
            android:layout_width="50dp"
            android:layout_height="50dp"
            fresco:placeholderImageScaleType="centerCrop"
            fresco:placeholderImage="@drawable/photo_placeholder"
            fresco:roundAsCircle="true"/>

Note: don't forget to call Fresco.initialize(this); somewhere (normally in your Application class).

I should also notice that Fresco currently add 2.6Mb to your application using ProGuard. You may choose to use another library such as Glide if you want less functionality.

Community
  • 1
  • 1
Hugo Gresse
  • 14,772
  • 8
  • 69
  • 103
  • This worked perfectly. Thank you. I just have one question: the image takes a while to actually display due to network latency. Is there any way I can put some sort of loading screen and not display the activity the image is in until the image is finished loading? I can't seem to figure it out since I'm not sure if I have to edit the `setUri` function itself or if I can put the loading screen code somewhere in the activity. – user1871869 Nov 19 '15 at 08:22
  • Secondly, I noticed if I set the layout_width and height to be larger than 50 dp, like 100 dp each, my picture is blurry. Any idea on how to fix that? – user1871869 Nov 19 '15 at 08:43
  • the picture will be blurry because of the size of the image. Image are in px, like 50x50px. If you want to displayed it with large size, you will see more pixels. About improving the image loading, you can either listen for the http://frescolib.org/docs/listening-download-events.html and display what you want at the end. To do this, ou will need to configure the Fresco cache and use an image pipeline see http://frescolib.org/docs/configure-image-pipeline.html – Hugo Gresse Nov 19 '15 at 10:08
  • see sample for Fresco initialize with configuration https://gist.github.com/HugoGresse/b196f6156d7d6e84d710 – Hugo Gresse Nov 19 '15 at 10:14
  • Ah thank you for all your help. This works perfectly. Thanks! Just last question regarding the blurriness: is there any part of the API that actually allows me to scale or to make the image larger without having it seem so blurry? Right now I want my layout width/height to be 100 dp but my image is extremely blurry. I've been looking at this: http://frescolib.org/docs/scaling.html#_ but it seems like it just talks about focusing the image. – user1871869 Nov 20 '15 at 09:37
  • I've found this http://frescolib.org/docs/resizing-rotating.html#_ but cannot you use a bigger input? You are using some api to get user informations. If so, it's possible that the api (facebook does) have different image size. In this case, use a bigger one. You won't have the effect you want anyway if the image is too small – Hugo Gresse Nov 20 '15 at 11:15
4

I can't help but notice most answers asking you to use 2 libraries, 1 for loading the Image and 2nd for displaying it. Your goal as a developer should always be to get your task done with the minimum number of libraries and here is a solution that only needs 1 library. I will use Glide here since it caches the images exactly for the size you need. I haven't used Fresco so cannot comment on it but HERE's something on Picasso vs. Glide

Step 1

Create your layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image_profile"
        android:layout_width="@dimen/profile_picture_size"
        android:layout_height="@dimen/profile_picture_size"
        android:background="@drawable/image_circle"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:src="@drawable/com_facebook_profile_picture_blank_square" />

    <TextView
        android:id="@+id/text_username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="@string/placeholder_name"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
        android:textColor="@color/colorTextPrimary" />
</LinearLayout>


</RelativeLayout>

This is what my Layout looks like, notice I used a plain simple ImageView instead of a fancy library. Feel free to adjust it to match your needs.

Navigation Drawer header

Step 2

Write a custom transform to convert a square image into a Circle Image. Glide uses something called Transformations to let you manipulate images according to what you need. Read THIS post for what transformations are and read THIS post to play with some custom transformations. In our case our transformation class looks like this.

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapResource;

public class CropCircleTransform implements Transformation<Bitmap> {

private BitmapPool mBitmapPool;

public CropCircleTransform(Context context) {
    this(Glide.get(context).getBitmapPool());
}

public CropCircleTransform(BitmapPool pool) {
    this.mBitmapPool = pool;
}

@Override
public Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) {
    Bitmap source = resource.get();
    int size = Math.min(source.getWidth(), source.getHeight());

    int width = (source.getWidth() - size) / 2;
    int height = (source.getHeight() - size) / 2;

    Bitmap bitmap = mBitmapPool.get(size, size, Bitmap.Config.ARGB_8888);
    if (bitmap == null) {
        bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    BitmapShader shader =
            new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
    if (width != 0 || height != 0) {
        // source isn't square, move viewport to center
        Matrix matrix = new Matrix();
        matrix.setTranslate(-width, -height);
        shader.setLocalMatrix(matrix);
    }
    paint.setShader(shader);
    paint.setAntiAlias(true);

    float r = size / 2f;
    canvas.drawCircle(r, r, r, paint);

    return BitmapResource.obtain(bitmap, mBitmapPool);
}

@Override public String getId() {
    return "CropCircleTransform()";
}
}

Step 3 Load the picture into this layout using Glide. Admin is an object that contains details such as name, email, profile picture url etc, mDrawer is a reference to the NavigationView. Notice how Glide uses the transformation defined in step 2 to achieve the circular image effect.

public void addHeaderToDrawer(@NonNull Admin admin) {
    View headerView = mDrawer.inflateHeaderView(R.layout.nav_header_main);
    TextView textUserName = (TextView) headerView.findViewById(R.id.text_username);
    ImageView imageProfile = (ImageView) headerView.findViewById(R.id.image_profile);
    textUserName.setText(admin.getName());
    Glide.with(mContext)
            .load(admin.getUrl())
            .asBitmap()
            .transform(new CropCircleTransform(mContext))
            .into(imageProfile);
}

Step 4

Sit back and enjoy the show. I am also loading the data from Facebook, let me know if you are still facing any issues :) enter image description here

PirateApp
  • 4,149
  • 2
  • 34
  • 51
1

I achieve this through using PICASSO library. No need to use CircularImageView Here is my code:

Target target = new Target() {

        @Override
        public void onPrepareLoad(Drawable arg0) {
            // Toast.makeText(FragmentChatView.this, "message",
            // Toast.LENGTH_LONG).show();
        }

        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom arg1) {
            bitmap = Bitmap.createScaledBitmap(bitmap, 40, 40, false);
            final Drawable drawImage = new BitmapDrawable(BaseActivity.this
                    .getBaseContext().getResources(), bitmap);
            // ((MaterialNavigationDrawer<Fragment>)
            // FragmentChatView.this).getToolbar().setLogo(drawImage);
            if (iv_logo != null)
                iv_logo.setImageDrawable(drawImage);
        }

        @Override
        public void onBitmapFailed(Drawable arg0) {

        }
    };

    public class CircleTransform implements Transformation {
        @Override
        public Bitmap transform(Bitmap source) {
            int size = Math.min(source.getWidth(), source.getHeight());

            int x = (source.getWidth() - size) / 2;
            int y = (source.getHeight() - size) / 2;

            Bitmap squaredBitmap = Bitmap
                    .createBitmap(source, x, y, size, size);
            if (squaredBitmap != source) {
                source.recycle();
            }

            Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());

            Canvas canvas = new Canvas(bitmap);
            Paint paint = new Paint();
            BitmapShader shader = new BitmapShader(squaredBitmap,
                    BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
            paint.setShader(shader);
            paint.setAntiAlias(true);

            float r = size / 2f;
            canvas.drawCircle(r, r, r, paint);

            squaredBitmap.recycle();
            return bitmap;
        }

        @Override
        public String key() {
            return "circle";
        }
    }

Hope it will work for you.

HassanUsman
  • 1,485
  • 1
  • 17
  • 34
1

try this

           <ImageView
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:background="@drawable/shape"
            android:src="@drawable/User"
            android:id="@+id/imageView2" />

shape.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<gradient
    android:angle="0"
    android:centerColor="#ffffff"
    android:centerX="35%"
    android:endColor="#ffffff"
    android:startColor="#ffffff"
    android:type="linear" />
<padding
    android:bottom="20dp"
    android:left="20dp"
    android:right="20dp"
    android:top="20dp" />
<size
    android:width="150dp"
    android:height="150dp" />
<stroke
    android:width="5dp"
    android:color="@color/allThemeBlue" />

</shape>

out put

enter image description here

A.G.THAMAYS
  • 2,798
  • 24
  • 31
0

Try this library: https://github.com/hdodenhof/CircleImageView. I've tried several alternatives, and this one was the lucky winner.

InstarHic
  • 1
  • 2
  • I just tried it and I get the same result. Do you have any example code or see anything I'm doing wrong that is having the picture not display? The "blank" photo shows (generic facebook image), but just not the actual photo. – user1871869 Nov 15 '15 at 03:15