public class BitmapSubscriptView extends View {
public BitmapSubscriptView(Context context) {
this(context, null);
}
public BitmapSubscriptView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BitmapSubscriptView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BitmapSubscriptView);
init(typedArray);
}
}
public static final int TOP_RIGHT = 0;
public static final int BOTTOM_RIGHT = 1;
public static final int BOTTOM_CENTER = 2;
public static final int BOTTOM_LEFT = 3;
public static final int TOP_LEFT = 4;
public static final int TOP_CENTER = 5;
/**
* 默认类型
*/
@IntDef({TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_CENTER, BOTTOM_LEFT, TOP_LEFT,TOP_CENTER})
@Retention(RetentionPolicy.SOURCE)
private @interface SubscriptOrientation {
}
//文字画笔
private TextPaint textPaint;
/**
* 获取文字画笔
*/
public Paint getTextPaint(){
return textPaint;
}
//文字颜色
private int textColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorWhite);
/**
* 设置角标中文字的颜色
* @param textColor 文字颜色
*/
public void setTextColor(int textColor){
this.textColor = textColor;
textPaint.setColor(textColor);
invalidate();
}
//文字
private String subscriptText = "0";
/**
* 设置角标中的文字
* @param subscriptText 角标数字
*/
public void setSubscriptText(String subscriptText){
this.subscriptText = subscriptText;
invalidate();
}
//角标画笔
private Paint subscriptPaint;
/**
* 获取角标画笔
*/
public Paint getSubscriptPaint(){
return subscriptPaint;
}
//角标颜色
private int subscriptColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorAccent);
/**
* 设置角标填充颜色
* @param subscriptColor 角标颜色
*/
public void setSubscriptColor(int subscriptColor){
this.subscriptColor = subscriptColor;
subscriptPaint.setColor(subscriptColor);
invalidate();
}
//角标半径
private float subscriptRadius ;
/**
* 设置角标半径
* @param subscriptRadius 半径
*/
public void setSubscriptRadius(float subscriptRadius){
if (blankBitmap != null){
blankBitmap = null;
}
this.subscriptRadius = subscriptRadius;
invalidate();
}
//角标X轴偏移量
private float angularOffsetX = 0 ;
/**
* 设置角标X轴偏移量
* @param angularOffsetX 正数:向右;负数:向左
*/
public void setAngularOffsetX(float angularOffsetX){
this.angularOffsetX = angularOffsetX;
invalidate();
}
//角标Y轴偏移量
private float angularOffsetY = 0 ;
/**
* 设置角标Y轴偏移量
* @param angularOffsetY 正数:向下;负数:向上
*/
public void setAngularOffsetY(float angularOffsetY){
this.angularOffsetY = angularOffsetY;
invalidate();
}
//角标位置
private int subscriptOrientation;
/**
* 设置角标位置
* @param subscriptOrientation 右上,右下,中下,左下,左上,左中
*/
public void setSubscriptOrientation(@SubscriptOrientation int subscriptOrientation){
this.subscriptOrientation = subscriptOrientation;
invalidate();
}
//空白位图
private Bitmap blankBitmap;
//位图
private Bitmap bitmap;
/**
* 设置位图
* @param id id
* @param isRGB 是否使用RGB_565压缩图片
*/
public void setBitmap(@DrawableRes int id,boolean isRGB){
if (blankBitmap != null){
blankBitmap = null;
}
bitmap = getBitmapResources(getResources(), id, isRGB);
invalidate();
}
/**
* 设置位图
* @param bitmap bitmap
*/
public void setBitmap(Bitmap bitmap) {
if (blankBitmap != null){
blankBitmap = null;
}
this.bitmap = bitmap;
invalidate();
}
//屏幕宽高
private int width;
private int height;
private void init(TypedArray typedArray) {
subscriptOrientation = typedArray.getInt(R.styleable.BitmapSubscriptView_subscript_orientation,0);
angularOffsetX = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_x,angularOffsetX);
angularOffsetY = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_y,angularOffsetY);
subscriptRadius = typedArray.getDimension(R.styleable.BitmapSubscriptView_subscript_radius,0);
subscriptColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_color,subscriptColor);
subscriptText = typedArray.getString(R.styleable.BitmapSubscriptView_subscript_text);
textColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_text_color,textColor);
int id = typedArray.getResourceId(R.styleable.BitmapSubscriptView_subscript_bitmap,R.drawable.ic_launcher);
bitmap = getBitmapResources(getResources(),id,false);
typedArray.recycle();
if (subscriptText == null){
subscriptText = "0";
}
subscriptPaint = new Paint();
subscriptPaint.setColor(subscriptColor);
subscriptPaint.setStyle(Paint.Style.FILL);
subscriptPaint.setAntiAlias(true);
textPaint = new TextPaint();
textPaint.setColor(textColor);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setAntiAlias(true);
screenWidth();
}
/**
* 读取资源文件夹下图片
*
* @param res getResources
* @param id 文件id
* @param isRGB 是否使用RGB_565压缩图片
* @return bitmap
*/
public Bitmap getBitmapResources(Resources res, int id, boolean isRGB) {
TypedValue value = new TypedValue();
InputStream is = res.openRawResource(id, value);
if (isRGB) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
return BitmapFactory.decodeStream(new BufferedInputStream(is), null, options);
}
return BitmapFactory.decodeStream(new BufferedInputStream(is));
}
/**
* 获取屏幕宽高
*/
private void screenWidth() {
WindowManager wm = (WindowManager) getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
if (wm != null) {
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//最短边距
int length = Math.min(getWidth(),getHeight());
//如果没有设置角标半径,或者角标直径大于等于最短边距,那么subscriptRadius = 最短边距的6分之1
if (subscriptRadius == 0){
subscriptRadius = length/6f;
}else if (2*subscriptRadius >= length){
subscriptRadius = length/6f;
}
if (blankBitmap == null){
//新图绘制区域高宽
float width = getWidth() - 2*subscriptRadius;
float height = getHeight() - 2*subscriptRadius;
//缩放比例
float scale = Math.min(width/bitmap.getWidth(),height/bitmap.getHeight());
//新图大小
int a = (int) (bitmap.getWidth()*scale);
int b = (int) (bitmap.getHeight()*scale);
//创建空白位图
blankBitmap = Bitmap.createBitmap(a, b,Bitmap.Config.ARGB_8888);
Canvas blankCanvas = new Canvas(blankBitmap);
//将传入的图片绘制到空白位图上
Matrix matrix = new Matrix();
matrix.setScale(scale,scale);
blankCanvas.drawBitmap(bitmap, matrix,subscriptPaint);
}
// 新图X坐标 =(控件宽 - 新图宽)/ 2
float x = (getWidth() - blankBitmap.getWidth())/2f;
float y = (getHeight() - blankBitmap.getHeight())/2f;
//绘制新图
canvas.drawBitmap(blankBitmap,x,y,subscriptPaint);
// 角标X坐标 = (控件宽 + 新图宽)/2
float subscriptX;
float subscriptY;
switch (subscriptOrientation){
case BOTTOM_RIGHT:
subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
break;
case BOTTOM_CENTER:
subscriptX = getWidth()/2f + angularOffsetX;
subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
break;
case BOTTOM_LEFT:
subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
break;
case TOP_LEFT:
subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
break;
case TOP_CENTER:
subscriptX = getWidth()/2f + angularOffsetX;
subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
break;
default:
subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
break;
}
//绘制角标
canvas.drawCircle(subscriptX , subscriptY , subscriptRadius ,subscriptPaint);
textPaint.setTextSize(subscriptRadius/2);
//绘制角标中的数字
canvas.drawText(subscriptText,subscriptX, subscriptY - textPaint.ascent()/2f ,textPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);
//限制控件大小不能大于屏幕宽高
setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? Math.min(measureWidth, width) : Math.min(bitmap.getWidth(), width)
, (measureHeightMode == MeasureSpec.EXACTLY) ? Math.min(measureHeight, height) : Math.min(bitmap.getHeight(), height));
}
//设置图片
bitmapSubscriptView.setBitmap(R.drawable.test,false)
bitmapSubscriptView.setBitmap(bitmap)
//设置角标颜色和半径
bitmapSubscriptView.setSubscriptColor(R.color.colorAccent)
bitmapSubscriptView.setSubscriptRadius(10f)
//设置角标方位和偏移量
bitmapSubscriptView.setSubscriptOrientation(BitmapSubscriptView.TOP_LEFT)
bitmapSubscriptView.setAngularOffsetX(100f)
bitmapSubscriptView.setAngularOffsetY(100f)
//设置角标文字和颜色
bitmapSubscriptView.setSubscriptText("1")
bitmapSubscriptView.setTextColor(R.color.colorWhite)
app:subscript_bitmap="@drawable/test"
app:subscript_radius="40dp"
app:subscript_orientation="bottom_right"
app:subscript_color="@color/colorAccent"
app:subscript_text="1"
app:subscript_text_color="@color/colorWhite"
app:angular_offset_x="-10dp"
app:angular_offset_y="10dp"
public class BitmapSubscriptView extends View {
public static final int TOP_RIGHT = 0;
public static final int BOTTOM_RIGHT = 1;
public static final int BOTTOM_CENTER = 2;
public static final int BOTTOM_LEFT = 3;
public static final int TOP_LEFT = 4;
public static final int TOP_CENTER = 5;
/**
* 默认类型
*/
@IntDef({TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_CENTER, BOTTOM_LEFT, TOP_LEFT,TOP_CENTER})
@Retention(RetentionPolicy.SOURCE)
private @interface SubscriptOrientation {
}
public BitmapSubscriptView(Context context) {
this(context, null);
}
public BitmapSubscriptView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BitmapSubscriptView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BitmapSubscriptView);
init(typedArray);
}
//文字画笔
private TextPaint textPaint;
/**
* 获取文字画笔
*/
public Paint getTextPaint(){
return textPaint;
}
//文字颜色
private int textColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorWhite);
/**
* 设置角标中文字的颜色
* @param textColor 文字颜色
*/
public void setTextColor(int textColor){
this.textColor = textColor;
textPaint.setColor(textColor);
invalidate();
}
//文字
private String subscriptText = "0";
/**
* 设置角标中的文字
* @param subscriptText 角标数字
*/
public void setSubscriptText(String subscriptText){
this.subscriptText = subscriptText;
invalidate();
}
//角标画笔
private Paint subscriptPaint;
/**
* 获取角标画笔
*/
public Paint getSubscriptPaint(){
return subscriptPaint;
}
//角标颜色
private int subscriptColor = ContextCompat.getColor(getContext().getApplicationContext(), R.color.colorAccent);
/**
* 设置角标填充颜色
* @param subscriptColor 角标颜色
*/
public void setSubscriptColor(int subscriptColor){
this.subscriptColor = subscriptColor;
subscriptPaint.setColor(subscriptColor);
invalidate();
}
//角标半径
private float subscriptRadius ;
/**
* 设置角标半径
* @param subscriptRadius 半径
*/
public void setSubscriptRadius(float subscriptRadius){
this.subscriptRadius = subscriptRadius;
invalidate();
}
//角标X轴偏移量
private float angularOffsetX = 0 ;
/**
* 设置角标X轴偏移量
* @param angularOffsetX 正数:向右;负数:向左
*/
public void setAngularOffsetX(float angularOffsetX){
this.angularOffsetX = angularOffsetX;
invalidate();
}
//角标Y轴偏移量
private float angularOffsetY = 0 ;
/**
* 设置角标Y轴偏移量
* @param angularOffsetY 正数:向下;负数:向上
*/
public void setAngularOffsetY(float angularOffsetY){
this.angularOffsetY = angularOffsetY;
invalidate();
}
//角标位置
private int subscriptOrientation;
/**
* 设置角标位置
* @param subscriptOrientation 右上,右下,中下,左下,左上,左中
*/
public void setSubscriptOrientation(@SubscriptOrientation int subscriptOrientation){
this.subscriptOrientation = subscriptOrientation;
invalidate();
}
//空白位图
private Bitmap blankBitmap;
//位图
private Bitmap bitmap;
/**
* 设置位图
* @param id id
* @param isRGB 是否使用RGB_565压缩图片
*/
public void setBitmap(@DrawableRes int id,boolean isRGB){
bitmap = getBitmapResources(getResources(), id, isRGB);
invalidate();
}
/**
* 设置位图
* @param bitmap bitmap
*/
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
invalidate();
}
//屏幕宽高
private int width;
private int height;
private void init(TypedArray typedArray) {
subscriptOrientation = typedArray.getInt(R.styleable.BitmapSubscriptView_subscript_orientation,0);
angularOffsetX = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_x,angularOffsetX);
angularOffsetY = typedArray.getDimension(R.styleable.BitmapSubscriptView_angular_offset_y,angularOffsetY);
subscriptRadius = typedArray.getDimension(R.styleable.BitmapSubscriptView_subscript_radius,0);
subscriptColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_color,subscriptColor);
subscriptText = typedArray.getString(R.styleable.BitmapSubscriptView_subscript_text);
textColor = typedArray.getColor(R.styleable.BitmapSubscriptView_subscript_text_color,textColor);
int id = typedArray.getResourceId(R.styleable.BitmapSubscriptView_subscript_bitmap,R.drawable.ic_launcher);
bitmap = getBitmapResources(getResources(),id,false);
typedArray.recycle();
if (subscriptText == null){
subscriptText = "0";
}
subscriptPaint = new Paint();
subscriptPaint.setColor(subscriptColor);
subscriptPaint.setStyle(Paint.Style.FILL);
subscriptPaint.setAntiAlias(true);
textPaint = new TextPaint();
textPaint.setColor(textColor);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setAntiAlias(true);
screenWidth();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//最短边距
int length = Math.min(getWidth(),getHeight());
//如果没有设置角标半径,或者角标直径大于等于最短边距,那么subscriptRadius = 最短边距的6分之1
if (subscriptRadius == 0){
subscriptRadius = length/6f;
}else if (2*subscriptRadius >= length){
subscriptRadius = length/6f;
}
if (blankBitmap == null){
//新图绘制区域高宽
float width = getWidth() - 2*subscriptRadius;
float height = getHeight() - 2*subscriptRadius;
//缩放比例
float scale = Math.min(width/bitmap.getWidth(),height/bitmap.getHeight());
//新图大小
int a = (int) (bitmap.getWidth()*scale);
int b = (int) (bitmap.getHeight()*scale);
//创建空白位图
blankBitmap = Bitmap.createBitmap(a, b,Bitmap.Config.ARGB_8888);
Canvas blankCanvas = new Canvas(blankBitmap);
//将传入的图片绘制到空白位图上
Matrix matrix = new Matrix();
matrix.setScale(scale,scale);
blankCanvas.drawBitmap(bitmap, matrix,subscriptPaint);
}
// 新图X坐标 =(控件宽 - 新图宽)/ 2
float x = (getWidth() - blankBitmap.getWidth())/2f;
float y = (getHeight() - blankBitmap.getHeight())/2f;
//绘制新图
canvas.drawBitmap(blankBitmap,x,y,subscriptPaint);
// 角标X坐标 = (控件宽 + 新图宽)/2
float subscriptX;
float subscriptY;
switch (subscriptOrientation){
case BOTTOM_RIGHT:
subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
break;
case BOTTOM_CENTER:
subscriptX = getWidth()/2f + angularOffsetX;
subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
break;
case BOTTOM_LEFT:
subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() + blankBitmap.getHeight())/2f + angularOffsetY;
break;
case TOP_LEFT:
subscriptX = (getWidth() - blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
break;
case TOP_CENTER:
subscriptX = getWidth()/2f + angularOffsetX;
subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
break;
default:
subscriptX = (getWidth() + blankBitmap.getWidth())/2f + angularOffsetX;
subscriptY = (getHeight() - blankBitmap.getHeight())/2f + angularOffsetY;
break;
}
//绘制角标
canvas.drawCircle(subscriptX , subscriptY , subscriptRadius ,subscriptPaint);
textPaint.setTextSize(subscriptRadius/2);
//绘制角标中的数字
canvas.drawText(subscriptText,subscriptX, subscriptY - textPaint.ascent()/2f ,textPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);
//限制控件大小不能大于屏幕宽高
setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? Math.min(measureWidth, width) : Math.min(bitmap.getWidth(), width)
, (measureHeightMode == MeasureSpec.EXACTLY) ? Math.min(measureHeight, height) : Math.min(bitmap.getHeight(), height));
}
/**
* 读取资源文件夹下图片
*
* @param res getResources
* @param id 文件id
* @param isRGB 是否使用RGB_565压缩图片
* @return bitmap
*/
public Bitmap getBitmapResources(Resources res, int id, boolean isRGB) {
TypedValue value = new TypedValue();
InputStream is = res.openRawResource(id, value);
if (isRGB) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
return BitmapFactory.decodeStream(new BufferedInputStream(is), null, options);
}
return BitmapFactory.decodeStream(new BufferedInputStream(is));
}
/**
* 获取屏幕宽高
*/
private void screenWidth() {
WindowManager wm = (WindowManager) getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
if (wm != null) {
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
}
}
}