Android 心形图片心形ImageView、带边框的的心形图片和圆形图片(1)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

TypedArray mArray = mContext.obtainStyledAttributes(attrs,

R.styleable.heartimageview);

// 得到边框厚度,否则返回0

border_size = mArray.getDimensionPixelSize(

R.styleable.heartimageview_border_size, 0);

// 得到内边框颜色,否则返回默认颜色

in_border_color = mArray.getColor(

R.styleable.heartimageview_in_border_color, defColor);

// 得到外边框颜色,否则返回默认颜色

out_border_color = mArray.getColor(

R.styleable.heartimageview_out_border_color, defColor);

// 得到形状的类型

shape_type = mArray.getString(R.styleable.heartimageview_shape_type);

mArray.recycle();// 回收mArray

}

@Override

protected void onDraw(Canvas canvas) {

// TODO Auto-generated method stub

// super.onDraw(canvas); 必须去掉该行或注释掉,否则会出现两张图片

// 得到传入的图片

Drawable drawable = getDrawable();

if (drawable == null) {

return;

}

if (getWidth() == 0 || getHeight() == 0) {

return;

}

this.measure(0, 0);

if (drawable.getClass() == NinePatchDrawable.class) {// 如果该传入图片是.9格式的图片

return;

}

// 将图片转为位图

Bitmap mBitmap = ((BitmapDrawable) drawable).getBitmap();

Bitmap cpBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);

// 得到画布宽高

width = getWidth();

height = getHeight();

//

int radius = 0;//

radius = (width < height ? width : height) / 2;

//

Bitmap shapeBitmap = drawShapeBitmap(cpBitmap, radius);

canvas.drawBitmap(shapeBitmap, width / 2 - radius, height / 2 - radius,

null);

}

/**

  • 画出指定形状的图片

  • @param radius

  • @return

*/

private Bitmap drawShapeBitmap(Bitmap bmp, int radius) {

// TODO Auto-generated method stub

Bitmap squareBitmap;// 根据传入的位图截取合适的正方形位图

Bitmap scaledBitmap;// 根据diameter对截取的正方形位图进行缩放

Log.i(“HeartImageView”, “radius:” + radius);

int diameter = radius * 2;

// 位图的宽高

int w = bmp.getWidth();

int h = bmp.getHeight();

// 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片

squareBitmap = bmp;

// 对squareBitmap进行缩放为diameter边长的正方形位图

if (w != diameter

|| h != diameter) {

if (w < diameter || h < diameter) {

//位图宽高没有ImageView的宽高大 需要放大

float scale; //缩放倍数

scale = 1f * diameter / (Math.min(w, h));

Matrix matrix = new Matrix();

matrix.postScale(scale,scale);

squareBitmap = Bitmap.createBitmap(squareBitmap,0,0,w,h,matrix,false);

if (w != h) {

//从矩形图中截取正中间的正方形部分。

scaledBitmap = centerSquareScaleBitmap(squareBitmap, diameter);

} else {

scaledBitmap = squareBitmap;

}

} else {

//从矩形图中截取正中间的正方形部分。

scaledBitmap = centerSquareScaleBitmap(squareBitmap, diameter);

}

} else {

scaledBitmap = squareBitmap;

}

Bitmap outputbmp = Bitmap.createBitmap(scaledBitmap.getWidth(),

scaledBitmap.getHeight(), Config.ARGB_8888);

Canvas canvas = new Canvas(outputbmp);// 创建一个相同大小的画布

Paint paint = new Paint();// 定义画笔

paint.setAntiAlias(true);// 设置抗锯齿

paint.setFilterBitmap(true);

paint.setDither(true);

canvas.drawARGB(0, 0, 0, 0);

//设置边框

Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

borderPaint.setColor(out_border_color);

borderPaint.setStyle(Paint.Style.STROKE);

borderPaint.setStrokeWidth(border_size);

Path path = new Path();

//右心形

path.moveTo(diameter / 2f, diameter / 7f);

path.cubicTo((diameter /6f) * 5 , 0 - ( diameter / 5f), (diameter / 5f) * 7 , (diameter / 5f) * 2 , diameter / 2f, diameter- border_size );

//左心形

path.moveTo(diameter / 2f, diameter / 7f);

path.cubicTo(diameter / 6f , 0 - ( diameter / 5f), 0 - (diameter / 5f) * 2, (diameter / 5f) * 2, diameter / 2f, diameter - border_size );

canvas.drawPath(path, paint);

// 设置Xfermode的Mode

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

canvas.drawBitmap(scaledBitmap, 0, 0, paint);

canvas.drawPath(path, borderPaint);

bmp = null;

squareBitmap = null;

scaledBitmap = null;

return outputbmp;

}

/**

  • @param bitmap 原图

  • @param edgeLength 希望得到的正方形部分的边长

  • @return 缩放截取正中部分后的位图。

*/

public static Bitmap centerSquareScaleBitmap(Bitmap bitmap, int edgeLength)

{

if(null == bitmap || edgeLength <= 0)

{

return null;

}

Bitmap result = bitmap;

int widthOrg = bitmap.getWidth();

int heightOrg = bitmap.getHeight();

if(widthOrg > edgeLength && heightOrg > edgeLength)

{

//压缩到一个最小长度是edgeLength的bitmap

int longerEdge = (int)(edgeLength * Math.max(widthOrg, heightOrg) / Math.min(widthOrg, heightOrg));

int scaledWidth = widthOrg > heightOrg ? longerEdge : edgeLength;

int scaledHeight = widthOrg > heightOrg ? edgeLength : longerEdge;

Bitmap scaledBitmap;

try{

scaledBitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true);

}

catch(Exception e){

return null;

}

//从图中截取正中间的正方形部分。

int xTopLeft = (scaledWidth - edgeLength) / 2;

int yTopLeft = (scaledHeight - edgeLength) / 2;

try{

result = Bitmap.createBitmap(scaledBitmap, xTopLeft, yTopLeft, edgeLength, edgeLength);

scaledBitmap.recycle();

}

catch(Exception e){

return null;

}

}

return result;

}

}

CircleImageView.java

public class CircleImageView extends ImageView {

private static final ImageView.ScaleType SCALE_TYPE = ImageView.ScaleType.CENTER_CROP;

private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;

private static final int COLORDRAWABLE_DIMENSION = 2;

private static final int DEFAULT_BORDER_WIDTH = 0;

private static final int DEFAULT_BORDER_COLOR = Color.BLACK;

private static final int DEFAULT_CIRCLE_BACKGROUND_COLOR = Color.TRANSPARENT;

private static final int DEFAULT_IMAGE_ALPHA = 255;

private static final boolean DEFAULT_BORDER_OVERLAY = false;

private final RectF mDrawableRect = new RectF();

private final RectF mBorderRect = new RectF();

private final Matrix mShaderMatrix = new Matrix();

private final Paint mBitmapPaint = new Paint();

private final Paint mBorderPaint = new Paint();

private final Paint mCircleBackgroundPaint = new Paint();

private int mBorderColor = DEFAULT_BORDER_COLOR;

private int mBorderWidth = DEFAULT_BORDER_WIDTH;

private int mCircleBackgroundColor = DEFAULT_CIRCLE_BACKGROUND_COLOR;

private int mImageAlpha = DEFAULT_IMAGE_ALPHA;

private Bitmap mBitmap;

private Canvas mBitmapCanvas;

private float mDrawableRadius;

private float mBorderRadius;

private ColorFilter mColorFilter;

private boolean mInitialized;

private boolean mRebuildShader;

private boolean mDrawableDirty;

private boolean mBorderOverlay;

private boolean mDisableCircularTransformation;

public CircleImageView(Context context) {

super(context);

init();

}

public CircleImageView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public CircleImageView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);

mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH);

mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR);

mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY);

mCircleBackgroundColor = a.getColor(R.styleable.CircleImageView_civ_circle_background_color, DEFAULT_CIRCLE_BACKGROUND_COLOR);

a.recycle();

init();

}

private void init() {

mInitialized = true;

super.setScaleType(SCALE_TYPE);

mBitmapPaint.setAntiAlias(true);

mBitmapPaint.setDither(true);

mBitmapPaint.setFilterBitmap(true);

mBitmapPaint.setAlpha(mImageAlpha);

mBitmapPaint.setColorFilter(mColorFilter);

mBorderPaint.setStyle(Paint.Style.STROKE);

mBorderPaint.setAntiAlias(true);

mBorderPaint.setColor(mBorderColor);

mBorderPaint.setStrokeWidth(mBorderWidth);

mCircleBackgroundPaint.setStyle(Paint.Style.FILL);

mCircleBackgroundPaint.setAntiAlias(true);

mCircleBackgroundPaint.setColor(mCircleBackgroundColor);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

setOutlineProvider(new OutlineProvider());

}

}

@Override

public void setScaleType(ImageView.ScaleType scaleType) {

if (scaleType != SCALE_TYPE) {

throw new IllegalArgumentException(String.format(“ScaleType %s not supported.”, scaleType));

}

}

@Override

public void setAdjustViewBounds(boolean adjustViewBounds) {

if (adjustViewBounds) {

throw new IllegalArgumentException(“adjustViewBounds not supported.”);

}

}

@SuppressLint(“CanvasSize”)

@Override

protected void onDraw(Canvas canvas) {

if (mDisableCircularTransformation) {

super.onDraw(canvas);

return;

}

if (mCircleBackgroundColor != Color.TRANSPARENT) {

canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mCircleBackgroundPaint);

}

if (mBitmap != null) {

if (mDrawableDirty && mBitmapCanvas != null) {

mDrawableDirty = false;

Drawable drawable = getDrawable();

drawable.setBounds(0, 0, mBitmapCanvas.getWidth(), mBitmapCanvas.getHeight());

drawable.draw(mBitmapCanvas);

}

if (mRebuildShader) {

mRebuildShader = false;

BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

bitmapShader.setLocalMatrix(mShaderMatrix);

mBitmapPaint.setShader(bitmapShader);

}

canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);

}

if (mBorderWidth > 0) {

canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);

}

}

@Override

public void invalidateDrawable(@NonNull Drawable dr) {

mDrawableDirty = true;

invalidate();

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

updateDimensions();

invalidate();

}

@Override

public void setPadding(int left, int top, int right, int bottom) {

super.setPadding(left, top, right, bottom);

updateDimensions();

invalidate();

}

@Override

public void setPaddingRelative(int start, int top, int end, int bottom) {

super.setPaddingRelative(start, top, end, bottom);

updateDimensions();

invalidate();

}

public int getBorderColor() {

return mBorderColor;

}

public void setBorderColor(@ColorInt int borderColor) {

if (borderColor == mBorderColor) {

return;

}

mBorderColor = borderColor;

mBorderPaint.setColor(borderColor);

invalidate();

}

public int getCircleBackgroundColor() {

return mCircleBackgroundColor;

}

public void setCircleBackgroundColor(@ColorInt int circleBackgroundColor) {

if (circleBackgroundColor == mCircleBackgroundColor) {

return;

}

mCircleBackgroundColor = circleBackgroundColor;

mCircleBackgroundPaint.setColor(circleBackgroundColor);

invalidate();

}

/**

  • @deprecated Use {@link #setCircleBackgroundColor(int)} instead

*/

@Deprecated

public void setCircleBackgroundColorResource(@ColorRes int circleBackgroundRes) {

setCircleBackgroundColor(getContext().getResources().getColor(circleBackgroundRes));

}

public int getBorderWidth() {

return mBorderWidth;

}

public void setBorderWidth(int borderWidth) {

if (borderWidth == mBorderWidth) {

return;

}

mBorderWidth = borderWidth;

mBorderPaint.setStrokeWidth(borderWidth);

updateDimensions();

invalidate();

}

public boolean isBorderOverlay() {

return mBorderOverlay;

}

public void setBorderOverlay(boolean borderOverlay) {

if (borderOverlay == mBorderOverlay) {

return;

}

mBorderOverlay = borderOverlay;

updateDimensions();

invalidate();

}

public boolean isDisableCircularTransformation() {

return mDisableCircularTransformation;

}

public void setDisableCircularTransformation(boolean disableCircularTransformation) {

if (disableCircularTransformation == mDisableCircularTransformation) {

return;

}

mDisableCircularTransformation = disableCircularTransformation;

if (disableCircularTransformation) {

mBitmap = null;

mBitmapCanvas = null;

mBitmapPaint.setShader(null);

} else {

initializeBitmap();

}

invalidate();

}

@Override

public void setImageBitmap(Bitmap bm) {

super.setImageBitmap(bm);

initializeBitmap();

invalidate();

}

@Override

public void setImageDrawable(Drawable drawable) {

作者2013年从java开发,转做Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。

参与过不少面试,也当面试官 面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!

我整理了一份阿里P7级别的最系统的Android开发主流技术,特别适合有3-5年以上经验的小伙伴深入学习提升。

主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你想深入系统学习Android开发,成为一名合格的高级工程师,可以收藏一下这些Android进阶技术选型

我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。

Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言

高级UI与自定义view;
自定义view,Android开发的基本功。

性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。

NDK开发;
未来的方向,高薪必会。

前沿技术;
组件化,热升级,热修复,框架设计

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多,CodeChina上可见;

当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。

不出半年,你就能看出变化!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

外链图片转存中…(img-L7l5FOEw-1713678295892)]

Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言

[外链图片转存中…(img-UyAHyw5M-1713678295893)]

高级UI与自定义view;
自定义view,Android开发的基本功。

[外链图片转存中…(img-5BxvetHU-1713678295893)]

性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。

[外链图片转存中…(img-9TTUH2fn-1713678295893)]

NDK开发;
未来的方向,高薪必会。

[外链图片转存中…(img-Y2BFJQeh-1713678295894)]

前沿技术;
组件化,热升级,热修复,框架设计

[外链图片转存中…(img-xUcchKVH-1713678295894)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多,CodeChina上可见;

当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。

不出半年,你就能看出变化!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-1gQPB33i-1713678295894)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言 第一部分 准备篇 第1章 Android开发简介 1.1 Android基本概念 1.1.1 Android简介 1.1.2 Android的系统构架 1.1.3 Android应用程序框架 1.2 OMS介绍 1.2.1 OPhone介绍 1.2.2 Widget介绍 1.3 小结 第2章 Android开发环境搭建 2.1 Android开发准备工作 2.2 开发包及其工具的安装和 配置 2.2.1 安装JDK和配置Java开发 环境 2.2.2 Eclipse的安装与汉化 2.2.3 SDK和ADT的安装和 配置 2.3 创建第一个Android项目——HeUoAndroid 2.3.1 创建HelloAndroid项目 2.3.2 运行HelloAndroid及模拟器的使用 2.3.3 调试HelloAndroid 2.4 小结 第二部分 基础篇 第3章 Android程序设计基础 3.1 Android程序框架 3.1.1 Android项目目录结构 3.1.2 Android应用解析 3.2 Android的生命周期 3.3 Android程序U设计 3.4 小结 第4章 用户界面开发 4.1 用户界面开发详解 4.1.1 用户界面简介 4.1.2 事件处理 4.2 常用控件应用 4.2.1 文本框(Textiew) 4.2.2 列表(ListView) 4.2.3 提示(T0ast) 4.2.4 编辑框(EditText) 4.2.5 单项选择(RadioGroup、RadioButton 4.2.6 多项选择(CheckBox) 4.2.7 下拉列表(Spinner) 4.2.8 自动提示(AutoComplete.TextⅥew) 4.2.9 日期和时间(DatePicker、TimePicker) 4.2.10 按钮(Button) 4.2.1l 菜单(Menu) 4.2.12 对话框(Dialog) 4.2.13 图片视图(ImageView) 4.2.14 图标的按钮(ImageButton) 4.2.15 拖动效果(Gallery) 4.2.16 切换图片(hmgeSwilcher) 4.2.17 网格视图(GridView) 4.2.18 卷轴视图(ScrollView) 4.2.19 进度条(ProgressBar) 4.2.20 拖动条(SeekBar) 4.2.21 状态栏提示(Notification、NotificationManager) 4.2.22 对话框中的进度条(ProgressDialog) 4.3 界面布局 4.3.1 垂直线性布局 4.3.2 水平线性布局 4.3.3.相对布局(RelativeLayout) 4.3.4 表单布局(TableLayout) 4.3.5 切换卡(TabWidget) 4,4 小结 第5章 Android游戏开发 5.1 Android游戏开发框架 5.1.1 View类开发框架 5.1.2 SurfaceView类开发框架 5.2 Graphics类开发 5.5.1 Paint和Color类介绍 5.2.2 Canvas类介绍 5.2.3 几何图形绘制 5.2.4 字符串绘制 5.2.5 图像绘制 5.2.6 图像旋转 5.2.7 图像缩放 5.2.8 图像像素操作 5.2.9 Shader类介绍 5.2.10 双缓冲技术 5.2.11 全屏显示 5.2.12 获得屏幕属性 5.3 动画实现 5.3.1 Tween动画 5.3.2 Frame动画 5.3.3 GIF动画播放 5.4 小结 第6章 Android数据存储 6.1 Android数据存储初探 6.2 数据存储之Shared Preferences 6.3 数据存储之Files 6.4 数据存储之Network 6.5 Android数据库编程 6.5.1 SQLite简介 6.5.2 SQLite编程详解 6.5.3 SQLiteOpenHelper应用 6.6 数据共享(ContentProviders) 6.7 小结 第7 章多媒体开发 7.1 多媒体开发详解 7.1.1 Open Core 7.1.2 MediaPlayer 7.1.3 MediaRecorder 7.2 播放音乐 7.3 播放视频 7.4 录制歌曲 7.5 相机设置 7.6 闹钟设置 7.7 铃声设置 7.8 小结 第8章 网络与通信 8.1 网络通信基础 8.1.1 无线网络技术 8.1.2 Android网络基础 8.2 HTTP通信 8.2.1 HttpURLConnection接口 8.2.2 HttpClient接口 8.2.3 实时更新 8.3 Socket通信 8.3.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值