如何创建圆形的 Facebook 个人资料图片
How to create circular facebook profile picture
我在使用这个库将我的一张图片动态地变成一个圆圈时遇到了问题。这是我的尝试:
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);
}
}
布局:
<?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" />
我知道当我调用 profilePictureView.setProfileId(profile.getId());
时我的 profilePictureView
显示正确 在我的布局上,它显示正确。但是,当我尝试调用 circularProfilePicture 时,我只得到一张 "empty" 照片。图像的位图似乎没有 recognized/set 正确。图像不像 profilePictureView
那样显示。知道为什么会发生这种情况吗?
试试这个库:https://github.com/hdodenhof/CircleImageView。我尝试了多种选择,而这个是幸运的赢家。
我通过使用 PICASSO library
实现了这一点。
无需使用 CircularImageView
这是我的代码:
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";
}
}
希望对你有用。
在使用了不同的图片库(包括Picasso)后,我用完了一个名为Fresco的Facebook。代码更少,速度更快,一切正常。
壁画支持:
- 渐进式 JPEG 流式传输
- 动画 GIF 和 WebP 的显示
- 图像加载和显示的广泛定制
医生也说了
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.
搜索时也支持圆角,见here。
布局示例:
<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"/>
注意:不要忘记在某处调用 Fresco.initialize(this);
(通常在您的应用程序 class 中)。
我还应该注意到,Fresco 当前使用 ProGuard 添加 2.6Mb 到您的应用程序。如果您想要更少的功能,您可以选择使用其他库,例如 Glide。
我不禁注意到大多数答案要求您使用 2 个库,1 个用于加载图像,2 个用于显示图像。作为开发人员,您的目标应该始终是使用最少数量的库完成您的任务,这里是一个只需要 1 个库的解决方案。我将在这里使用 Glide,因为它会根据您需要的大小精确缓存图像。我没有用过 Fresco,所以不能评论它,但是 HERE's 关于 Picasso vs. Glide
步骤 1
创建布局
<?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>
这就是我的布局的样子,注意我使用了一个简单的 ImageView 而不是花哨的库。请随意调整它以满足您的需求。
步骤 2
编写自定义转换以将方形图像转换为圆形图像。 Glide 使用一种叫做 Transformations 的东西来让你根据你的需要来操作图像。阅读 THIS post for what transformations are and read THIS post 以尝试一些自定义转换。在我们的例子中,我们的转换 class 看起来像这样。
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()";
}
}
步骤 3
使用 Glide 将图片加载到此布局中。 Admin 是一个包含姓名、电子邮件、个人资料图片 url 等详细信息的对象,mDrawer 是对 NavigationView 的引用。注意Glide是如何使用步骤2中定义的变换来实现圆形图像效果的。
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);
}
步骤 4
坐下来欣赏表演。我也在从 Facebook 加载数据,如果您仍然遇到任何问题,请告诉我 :)
试试这个
<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>
输出
我在使用这个库将我的一张图片动态地变成一个圆圈时遇到了问题。这是我的尝试:
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);
}
}
布局:
<?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" />
我知道当我调用 profilePictureView.setProfileId(profile.getId());
时我的 profilePictureView
显示正确 在我的布局上,它显示正确。但是,当我尝试调用 circularProfilePicture 时,我只得到一张 "empty" 照片。图像的位图似乎没有 recognized/set 正确。图像不像 profilePictureView
那样显示。知道为什么会发生这种情况吗?
试试这个库:https://github.com/hdodenhof/CircleImageView。我尝试了多种选择,而这个是幸运的赢家。
我通过使用 PICASSO library
实现了这一点。
无需使用 CircularImageView
这是我的代码:
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";
}
}
希望对你有用。
在使用了不同的图片库(包括Picasso)后,我用完了一个名为Fresco的Facebook。代码更少,速度更快,一切正常。
壁画支持:
- 渐进式 JPEG 流式传输
- 动画 GIF 和 WebP 的显示
- 图像加载和显示的广泛定制
医生也说了
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.
搜索时也支持圆角,见here。
布局示例:
<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"/>
注意:不要忘记在某处调用 Fresco.initialize(this);
(通常在您的应用程序 class 中)。
我还应该注意到,Fresco 当前使用 ProGuard 添加 2.6Mb 到您的应用程序。如果您想要更少的功能,您可以选择使用其他库,例如 Glide。
我不禁注意到大多数答案要求您使用 2 个库,1 个用于加载图像,2 个用于显示图像。作为开发人员,您的目标应该始终是使用最少数量的库完成您的任务,这里是一个只需要 1 个库的解决方案。我将在这里使用 Glide,因为它会根据您需要的大小精确缓存图像。我没有用过 Fresco,所以不能评论它,但是 HERE's 关于 Picasso vs. Glide
步骤 1
创建布局
<?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>
这就是我的布局的样子,注意我使用了一个简单的 ImageView 而不是花哨的库。请随意调整它以满足您的需求。
步骤 2
编写自定义转换以将方形图像转换为圆形图像。 Glide 使用一种叫做 Transformations 的东西来让你根据你的需要来操作图像。阅读 THIS post for what transformations are and read THIS post 以尝试一些自定义转换。在我们的例子中,我们的转换 class 看起来像这样。
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()";
}
}
步骤 3 使用 Glide 将图片加载到此布局中。 Admin 是一个包含姓名、电子邮件、个人资料图片 url 等详细信息的对象,mDrawer 是对 NavigationView 的引用。注意Glide是如何使用步骤2中定义的变换来实现圆形图像效果的。
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);
}
步骤 4
坐下来欣赏表演。我也在从 Facebook 加载数据,如果您仍然遇到任何问题,请告诉我 :)
试试这个
<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>
输出