我从Facebook的ProfilePictureView中获取了代码并进行了一些修改:
以下是代码:
package com.myapp.mypackage.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.facebook.FacebookException;
import com.facebook.LoggingBehavior;
import com.facebook.android.R;
import com.facebook.internal.ImageDownloader;
import com.facebook.internal.ImageRequest;
import com.facebook.internal.ImageResponse;
import com.facebook.internal.Logger;
import com.facebook.internal.Utility;
import java.net.URISyntaxException;
public class ProfilePictureView extends FrameLayout {
public interface OnErrorListener {
void onError(FacebookException error);
}
public static final String TAG = ProfilePictureView.class.getSimpleName();
public static final int CUSTOM = -1;
public static final int SMALL = -2;
public static final int NORMAL = -3;
public static final int LARGE = -4;
private static final int MIN_SIZE = 1;
private static final boolean IS_CROPPED_DEFAULT_VALUE = true;
private static final String SUPER_STATE_KEY = "ProfilePictureView_superState";
private static final String PROFILE_ID_KEY = "ProfilePictureView_profileId";
private static final String PRESET_SIZE_KEY = "ProfilePictureView_presetSize";
private static final String IS_CROPPED_KEY = "ProfilePictureView_isCropped";
private static final String BITMAP_KEY = "ProfilePictureView_bitmap";
private static final String BITMAP_WIDTH_KEY = "ProfilePictureView_width";
private static final String BITMAP_HEIGHT_KEY = "ProfilePictureView_height";
private static final String PENDING_REFRESH_KEY = "ProfilePictureView_refresh";
private String profileId;
private int queryHeight = ImageRequest.UNSPECIFIED_DIMENSION;
private int queryWidth = ImageRequest.UNSPECIFIED_DIMENSION;
private boolean isCropped = IS_CROPPED_DEFAULT_VALUE;
private Bitmap imageContents;
private ImageView image;
private int presetSizeType = CUSTOM;
private ImageRequest lastRequest;
private OnErrorListener onErrorListener;
private Bitmap customizedDefaultProfilePicture = null;
public ProfilePictureView(Context context) {
super(context);
initialize(context);
}
public ProfilePictureView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
parseAttributes(attrs);
}
public ProfilePictureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize(context);
parseAttributes(attrs);
}
public final int getPresetSize() {
return presetSizeType;
}
public final void setPresetSize(int sizeType) {
switch (sizeType) {
case SMALL:
case NORMAL:
case LARGE:
case CUSTOM:
this.presetSizeType = sizeType;
break;
default:
throw new IllegalArgumentException("Must use a predefined preset size");
}
requestLayout();
}
public final boolean isCropped() {
return isCropped;
}
public final void setCropped(boolean showCroppedVersion) {
isCropped = showCroppedVersion;
refreshImage(false);
}
public final String getProfileId() {
return profileId;
}
public final void setProfileId(String profileId) {
boolean force = false;
if (Utility.isNullOrEmpty(this.profileId) || !this.profileId.equalsIgnoreCase(profileId)) {
setBlankProfilePicture();
force = true;
}
this.profileId = profileId;
refreshImage(force);
}
public final OnErrorListener getOnErrorListener() {
return onErrorListener;
}
public final void setOnErrorListener(OnErrorListener onErrorListener) {
this.onErrorListener = onErrorListener;
}
public final void setDefaultProfilePicture(Bitmap inputBitmap) {
customizedDefaultProfilePicture = inputBitmap;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
ViewGroup.LayoutParams params = getLayoutParams();
boolean customMeasure = false;
int newHeight = MeasureSpec.getSize(heightMeasureSpec);
int newWidth = MeasureSpec.getSize(widthMeasureSpec);
if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY &&
params.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
newHeight = getPresetSizeInPixels(true);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
customMeasure = true;
}
if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY &&
params.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
newWidth = getPresetSizeInPixels(true);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);
customMeasure = true;
}
if (customMeasure) {
setMeasuredDimension(newWidth, newHeight);
measureChildren(widthMeasureSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
refreshImage(false);
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
Bundle instanceState = new Bundle();
instanceState.putParcelable(SUPER_STATE_KEY, superState);
instanceState.putString(PROFILE_ID_KEY, profileId);
instanceState.putInt(PRESET_SIZE_KEY, presetSizeType);
instanceState.putBoolean(IS_CROPPED_KEY, isCropped);
instanceState.putParcelable(BITMAP_KEY, imageContents);
instanceState.putInt(BITMAP_WIDTH_KEY, queryWidth);
instanceState.putInt(BITMAP_HEIGHT_KEY, queryHeight);
instanceState.putBoolean(PENDING_REFRESH_KEY, lastRequest != null);
return instanceState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state.getClass() != Bundle.class) {
super.onRestoreInstanceState(state);
} else {
Bundle instanceState = (Bundle) state;
super.onRestoreInstanceState(instanceState.getParcelable(SUPER_STATE_KEY));
profileId = instanceState.getString(PROFILE_ID_KEY);
presetSizeType = instanceState.getInt(PRESET_SIZE_KEY);
isCropped = instanceState.getBoolean(IS_CROPPED_KEY);
queryWidth = instanceState.getInt(BITMAP_WIDTH_KEY);
queryHeight = instanceState.getInt(BITMAP_HEIGHT_KEY);
setImageBitmap((Bitmap) instanceState.getParcelable(BITMAP_KEY));
if (instanceState.getBoolean(PENDING_REFRESH_KEY)) {
refreshImage(true);
}
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
lastRequest = null;
}
private void initialize(Context context) {
removeAllViews();
image = new ImageView(context);
LayoutParams imageLayout = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
image.setLayoutParams(imageLayout);
image.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
addView(image);
}
private void parseAttributes(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.com_facebook_profile_picture_view);
setPresetSize(a.getInt(R.styleable.com_facebook_profile_picture_view_preset_size, CUSTOM));
isCropped = a.getBoolean(R.styleable.com_facebook_profile_picture_view_is_cropped, IS_CROPPED_DEFAULT_VALUE);
a.recycle();
}
private void refreshImage(boolean force) {
boolean changed = updateImageQueryParameters();
if (profileId == null || profileId.length() == 0 ||
((queryWidth == ImageRequest.UNSPECIFIED_DIMENSION) &&
(queryHeight == ImageRequest.UNSPECIFIED_DIMENSION))) {
setBlankProfilePicture();
} else if (changed || force) {
sendImageRequest(true);
}
}
private void setBlankProfilePicture() {
if (customizedDefaultProfilePicture == null) {
int blankImageResource = isCropped() ?
R.drawable.com_facebook_profile_picture_blank_square :
R.drawable.com_facebook_profile_picture_blank_portrait;
setImageBitmap(BitmapFactory.decodeResource(getResources(), blankImageResource));
} else {
updateImageQueryParameters();
Bitmap scaledBitmap = Bitmap.createScaledBitmap(customizedDefaultProfilePicture, queryWidth, queryHeight, false);
setImageBitmap(scaledBitmap);
}
}
private void setImageBitmap(Bitmap imageBitmap) {
if (image != null && imageBitmap != null) {
imageContents = imageBitmap;
image.setImageBitmap(ProfilePictureView.getRoundedBitmap(imageBitmap));
}
}
private void sendImageRequest(boolean allowCachedResponse) {
try {
ImageRequest.Builder requestBuilder = new ImageRequest.Builder(
getContext(),
ImageRequest.getProfilePictureUrl(profileId, queryWidth, queryHeight));
ImageRequest request = requestBuilder.setAllowCachedRedirects(allowCachedResponse)
.setCallerTag(this)
.setCallback(
new ImageRequest.Callback() {
@Override
public void onCompleted(ImageResponse response) {
processResponse(response);
}
}
)
.build();
if (lastRequest != null) {
ImageDownloader.cancelRequest(lastRequest);
}
lastRequest = request;
ImageDownloader.downloadAsync(request);
} catch (URISyntaxException e) {
Logger.log(LoggingBehavior.REQUESTS, Log.ERROR, TAG, e.toString());
}
}
private void processResponse(ImageResponse response) {
if (response.getRequest() == lastRequest) {
lastRequest = null;
Bitmap responseImage = response.getBitmap();
Exception error = response.getError();
if (error != null) {
OnErrorListener listener = onErrorListener;
if (listener != null) {
listener.onError(new FacebookException(
"Error in downloading profile picture for profileId: " + getProfileId(), error));
} else {
Logger.log(LoggingBehavior.REQUESTS, Log.ERROR, TAG, error.toString());
}
} else if (responseImage != null) {
setImageBitmap(responseImage);
if (response.isCachedRedirect()) {
sendImageRequest(false);
}
}
}
}
private boolean updateImageQueryParameters() {
int newHeightPx = getHeight();
int newWidthPx = getWidth();
if (newWidthPx < MIN_SIZE || newHeightPx < MIN_SIZE) {
return false;
}
int presetSize = getPresetSizeInPixels(false);
if (presetSize != ImageRequest.UNSPECIFIED_DIMENSION) {
newWidthPx = presetSize;
newHeightPx = presetSize;
}
if (newWidthPx <= newHeightPx) {
newHeightPx = isCropped() ? newWidthPx : ImageRequest.UNSPECIFIED_DIMENSION;
} else {
newWidthPx = isCropped() ? newHeightPx : ImageRequest.UNSPECIFIED_DIMENSION;
}
boolean changed = (newWidthPx != queryWidth) || (newHeightPx != queryHeight);
queryWidth = newWidthPx;
queryHeight = newHeightPx;
return changed;
}
private int getPresetSizeInPixels(boolean forcePreset) {
int dimensionId;
switch (presetSizeType) {
case SMALL:
dimensionId = R.dimen.com_facebook_profilepictureview_preset_size_small;
break;
case NORMAL:
dimensionId = R.dimen.com_facebook_profilepictureview_preset_size_normal;
break;
case LARGE:
dimensionId = R.dimen.com_facebook_profilepictureview_preset_size_large;
break;
case CUSTOM:
if (!forcePreset) {
return ImageRequest.UNSPECIFIED_DIMENSION;
} else {
dimensionId = R.dimen.com_facebook_profilepictureview_preset_size_normal;
break;
}
default:
return ImageRequest.UNSPECIFIED_DIMENSION;
}
return getResources().getDimensionPixelSize(dimensionId);
}
public static Bitmap getRoundedBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
在底部,您可以看到一个新方法:getRoundedBitmap。