package net.naonedbus.widget;
import net.naonedbus.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
public class ContactView extends View {
private static final float TEXT_PADDING = 8f;
private static final float SUBTITLE_PADDING = 2f;
private Typeface mTypeface;
private TextPaint mTitlePaint;
private TextPaint mSubtitlePaint;
private Paint mAvatarPaint;
private String mTitle;
private String mSubtitle;
private String mUrl;
private Drawable mAvatarDrawable;
private Bitmap mAvatarBitmap;
private int mTextPadding;
private int mSubtitlePadding;
private int mAvatarSize;
private final RectF mTitleBounds = new RectF();
private final RectF mSubtitleBounds = new RectF();
private final Rect mAvatarBounds = new Rect();
public ContactView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
public ContactView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ContactView(final Context context) {
this(context, null);
}
private void init(final Context context, final AttributeSet attrs, final int defStyle) {
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
mTextPadding = Math.round(TEXT_PADDING * metrics.density);
mSubtitlePadding = Math.round(SUBTITLE_PADDING * metrics.density);
mTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
if (mTypeface != null)
mTitlePaint.setTypeface(mTypeface);
mSubtitlePaint = new TextPaint(mTitlePaint);
mAvatarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
final TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.ContactView, defStyle, 0);
final int titleStyle = values.getResourceId(R.styleable.ContactView_titleTextStyle, 0);
final int subtitleStyle = values.getResourceId(R.styleable.ContactView_subtitleTextStyle, 0);
final int[] textSizeAttr = new int[] { android.R.attr.textSize, android.R.attr.textColor };
TypedArray a = context.obtainStyledAttributes(attrs, textSizeAttr, 0, titleStyle);
final int titleTextSize = a.getDimensionPixelSize(0, -1);
final int titleTextColor = a.getColor(1, -1);
a.recycle();
a = context.obtainStyledAttributes(attrs, textSizeAttr, 0, subtitleStyle);
final int subtitleTextSize = a.getDimensionPixelSize(0, -1);
final int subtitleTextColor = a.getColor(1, -1);
a.recycle();
mTitlePaint.setTextSize(titleTextSize);
mSubtitlePaint.setTextSize(subtitleTextSize);
mTitlePaint.setColor(titleTextColor);
mSubtitlePaint.setColor(subtitleTextColor);
mTitle = values.getString(R.styleable.ContactView_android_title);
mSubtitle = values.getString(R.styleable.ContactView_subtitle);
mAvatarSize = values.getDimensionPixelSize(R.styleable.ContactView_avatarSize, 0);
mUrl = values.getString(R.styleable.ContactView_url);
mAvatarBounds.set(0, 0, mAvatarSize, mAvatarSize);
mAvatarBounds.offset(getPaddingLeft(), getPaddingTop());
getTextBound(mTitle, mTitlePaint, mTitleBounds);
getTextBound(mSubtitle, mSubtitlePaint, mSubtitleBounds);
setAvatarDrawable(values.getDrawable(R.styleable.ContactView_android_icon));
values.recycle();
}
public void setTitle(final String title) {
mTitle = title;
getTextBound(title, mTitlePaint, mTitleBounds);
requestLayout();
}
public void setSubtitle(final String subtitle) {
mSubtitle = subtitle;
getTextBound(subtitle, mSubtitlePaint, mSubtitleBounds);
requestLayout();
}
public void setAvatarDrawable(final Drawable avatarDrawable) {
mAvatarDrawable = avatarDrawable;
mAvatarBitmap = drawableToBitmap(mAvatarDrawable);
requestLayout();
}
public String getUrl() {
return mUrl;
}
private void getTextBound(final String text, final Paint paint, final RectF out) {
out.setEmpty();
if (text != null) {
out.right = paint.measureText(text);
out.bottom = paint.descent() - paint.ascent();
}
}
@Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
final int textY = (int) ((h - (mTitleBounds.height() + mSubtitleBounds.height())) / 2);
mAvatarBounds.offsetTo(getPaddingLeft(), getPaddingTop());
mTitleBounds.offsetTo(mAvatarBounds.right + mTextPadding * 2f, textY);
mSubtitleBounds.offsetTo(mAvatarBounds.right + mTextPadding * 2f, mTitleBounds.bottom + mSubtitlePadding);
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height;
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST) {
height = heightSize;
} else {
final int textHeight = Math.round(mTitleBounds.height() + mSubtitleBounds.height() + mSubtitlePadding);
final int avatarHeight = mAvatarBounds.height();
final int desiredHeight = Math.max(textHeight, avatarHeight) + getPaddingTop() + getPaddingBottom();
height = desiredHeight;
}
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(widthSize, height);
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
drawBitmap(mAvatarBitmap, mAvatarBounds, canvas);
drawText(mTitle, mTitleBounds, canvas, mTitlePaint, Alignment.ALIGN_NORMAL);
drawText(mSubtitle, mSubtitleBounds, canvas, mSubtitlePaint, Alignment.ALIGN_NORMAL);
}
private void drawText(final String text, final RectF bounds, final Canvas canvas, final TextPaint textPaint,
final Layout.Alignment alignment) {
if (text == null || bounds.width() <= 0)
return;
final CharSequence ellipsizedText = TextUtils.ellipsize(text, textPaint, bounds.width(),
TextUtils.TruncateAt.END);
final StaticLayout sl = new StaticLayout(ellipsizedText, textPaint, Math.round(bounds.width()), alignment, 1f,
0f, false);
canvas.save();
canvas.translate(bounds.left, bounds.centerY() + textPaint.ascent() + textPaint.descent());
sl.draw(canvas);
canvas.restore();
}
private void drawBitmap(final Bitmap bitmap, final Rect bounds, final Canvas canvas) {
final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mAvatarPaint.setShader(shader);
mAvatarPaint.setAntiAlias(true);
mAvatarPaint.setDither(true);
canvas.save();
canvas.translate(bounds.left, bounds.top);
canvas.drawCircle(mAvatarSize / 2, mAvatarSize / 2, bounds.width() / 2, mAvatarPaint);
canvas.restore();
}
public Bitmap drawableToBitmap(final Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
final Bitmap result = ((BitmapDrawable) drawable).getBitmap();
return Bitmap.createScaledBitmap(result, mAvatarSize, mAvatarSize, true);
}
final Bitmap bitmap = Bitmap.createBitmap(mAvatarSize, mAvatarSize, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(bitmap, 0, 0, mAvatarPaint);
return bitmap;
}
}