推荐学习资料
- 脑图
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
ClipImageActivity.goToClipActivity(this, uri, new ActivityResultHelper.Callback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
}
});
从上面的效果图我们可以看到,裁剪功能主要包括两大块
-
裁剪框
-
图片的缩放,移动,裁剪等
因此,为了方便日后的修改,我们将裁剪框的功能单独提取出来,图片缩放功能提出出来。即裁剪框单独一个 View。
下面,让我们一起来看看裁剪框功能的实现。
裁剪框主要有两层,第一层,裁剪框的实现(包括圆形,长方形,九宫格形状),第二层,在裁剪区域上面盖上一层蒙层。
蒙层
蒙层的实现我们是通过 Xfermode 实现的
xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
//通过Xfermode的DST_OUT来产生中间的透明裁剪区域,一定要另起一个Layer(层)
canvas.saveLayer(0, 0, this.getWidth(), this.getHeight(), null, Canvas.ALL_SAVE_FLAG);
//设置背景
canvas.drawColor(Color.parseColor(“#a8000000”));
paint.setXfermode(xfermode);
圆形裁剪框的实现
绘制圆形裁剪框很容易实现,主要确定圆心和半径即可
//中间的透明的圆
canvas.drawCircle(this.getWidth() / 2, this.getHeight() / 2, clipRadiusWidth, paint);
//白色的圆边框
canvas.drawCircle(this.getWidth() / 2, this.getHeight() / 2, clipRadiusWidth, borderPaint);
正方形裁剪框的实现
绘制长方形的话主要要确定四个点的坐标 left ,top, right, botom。
很简单
left = mHorizontalPadding;
top = this.getHeight() / 2 - clipWidth / 2;
right = this.getWidth() - mHorizontalPadding;
botom = this.getHeight() / 2 + clipWidth / 2;
//绘制中间白色的矩形蒙层
canvas.drawRect(mHorizontalPadding, this.getHeight() / 2 - clipWidth / 2,
this.getWidth() - mHorizontalPadding, this.getHeight() / 2 + clipWidth / 2, paint);
//绘制白色的矩形边框
canvas.drawRect(mHorizontalPadding, this.getHeight() / 2 - clipWidth / 2,
this.getWidth() - mHorizontalPadding, this.getHeight() / 2 + clipWidth / 2, borderPaint);
九宫格的
九宫格的绘制稍微繁琐一点,分三个步骤
-
绘制长方形边框
-
绘制九宫格引导线
-
绘制裁剪边框的是个直角
我们来看一下绘制九宫格引导线的
-
绘制竖直方向两条线
-
绘制水平方向两条线
private void drawGuidelines(@NonNull Canvas canvas, Rect clipRect) {
final float left = clipRect.left;
final float top = clipRect.top;
final float right = clipRect.right;
final float bottom = clipRect.bottom;
final float oneThirdCropWidth = (right - left) / 3;
final float x1 = left + oneThirdCropWidth;
//引导线竖直方向第一条线
canvas.drawLine(x1, top, x1, bottom, mGuidelinePaint);
final float x2 = right - oneThirdCropWidth;
//引导线竖直方向第二条线
canvas.drawLine(x2, top, x2, bottom, mGuidelinePaint);
final float oneThirdCropHeight = (bottom - top) / 3;
final float y1 = top + oneThirdCropHeight;
//引导线水平方向第一条线
canvas.drawLine(left, y1, right, y1, mGuidelinePaint);
final float y2 = bottom - oneThirdCropHeight;
//引导线水平方向第二条线
can
绘制四个直角的
private void drawCorners(@NonNull Canvas canvas, Rect clipRect) {
final float left = clipRect.left;
final float top = clipRect.top;
final float right = clipRect.right;
final float bottom = clipRect.bottom;
//简单的数学计算
final float lateralOffset = (mCornerThickness - mBorderThickness) / 2f;
final float startOffset = mCornerThickness - (mBorderThickness / 2f);
//左上角左面的短线
canvas.drawLine(left - lateralOffset, top - startOffset, left - lateralOffset, top + mCornerLength, mCornerPaint);
//左上角上面的短线
canvas.drawLine(left - startOffset, top - lateralOffset, left + mCornerLength, top - lateralOffset, mCornerPaint);
//右上角右面的短线
canvas.drawLine(right + lateralOffset, top - startOffset, right + lateralOffset, top + mCornerLength, mCornerPaint);
//右上角上面的短线
canvas.drawLine(right + startOffset, top - lateralOffset, right - mCornerLength, top - lateralOffset, mCornerPaint);
//左下角左面的短线
canvas.drawLine(left - lateralOffset, bottom + startOffset, left - lateralOffset, bottom - mCornerLength, mCornerPaint);
//左下角底部的短线
canvas.drawLine(left - startOffset, bottom + lateralOffset, left + mCornerLength, bottom + lateralOffset, mCornerPaint);
//右下角左面的短线
canvas.drawLine(right + lateralOffset, bottom + startOffset, right + lateralOffset, bottom - mCornerLength, mCornerPaint);
//右下角底部的短线
canvas.drawLine(right + startOffset, bottom + lateralOffset, right - mCornerLength, bottom + lateralOffset, mCornerPaint);
}
图片裁剪框的实现到此讲解完毕,更多细节请参考 ClipView
实现原理简述
这里我们是通过 ClipViewLayout 实现的,它是 RelativeLayout 的子类,里面含有 ImageView 和 ClipView(裁剪框)。我们通过监听 ClipViewLayout 的 onTouchEvent 事件,设置 imageView 的图片矩阵。
我们先来了解一下,主要有三种模式,NONE,DRAG, ZOOM。NONE 表示初始模式,DRAG 表示拖拽模式,ZOOM 表示缩放模式
private static final int NONE = 0;
//动作标志:拖动
private static final int DRAG = 1;
//动作标志:缩放
private static final int ZOOM = 2;
当我们多个手指按下的时候,加入两个手指之间的距离超过 10,此时我们认为进入 ZOOM 模式。DRAG 模式的话当我们手指按下的时候进入。NONE 模式,当我们手机抬起的时候,进入复位模式。
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, “onTouchEvent: ACTION_DOWN”);
mSavedMatrix.set(mMatrix);
//设置开始点位置
mStart.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
//开始放下时候两手指间的距离
mOldDist = spacing(event);
if (mOldDist > 10f) {
mSavedMatrix.set(mMatrix);
midPoint(mMid, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
接下来我们一起来看一下,我们 action_move 的时候,我们是怎样进行移动和缩放的。
移动的话相对比较简单,首先它会计算出我们这一次 event 事件相对我们 action_down 时候 event 事件的偏移量 dx, dy。接着调用 mMatrix.postTranslate(dx, dy),进行矩阵的移动。最后,再检测是否超出边界。
case MotionEvent.ACTION_MOVE:
Log.d(TAG, “onTouchEvent: mode =” + mode);
if (mode == DRAG) { //拖动
mMatrix.set(mSavedMatrix);
float dx = event.getX() - mStart.x;
float dy = event.getY() - mStart.y;
mVerticalPadding = mClipView.getClipRect().top;
mMatrix.postTranslate(dx, dy);
//检查边界
checkBorder();
}
mImageView.setImageMatrix(mMatrix);
写在最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
构技术进阶脑图、Android开发面试专题资料**,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-6EC1BwIh-1715730490005)]
【算法合集】
[外链图片转存中…(img-4yqrUFmK-1715730490005)]
【延伸Android必备知识点】
[外链图片转存中…(img-31evWVWX-1715730490006)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!