Android中ImageCropper矩形、圆形 裁剪框的实现方法

前言

支持圆形裁剪框,裁剪后生成圆形图案。

代码基于开源项目修改,github上项目链接:https://github.com/shengge/android-crop (本地下载)

还是贴下效果图:

说一下圆形裁剪实现部分:

1.UI方面,自定义CircleHighlightView继承至HighlightView(原有的矩形裁剪框实现),直接看draw方法实现

@Override
 protected void draw(Canvas canvas) {
 canvas.save();
 Path path = new Path();
 outlinePaint.setStrokeWidth( outlineWidth);
 if(!hasFocus()) {//没焦点是,直接画一个黑色的矩形框
  outlinePaint.setColor( Color.BLACK);
  canvas.drawRect( drawRect, outlinePaint);
 }
 else {
  Rect viewDrawingRect = new Rect();
  viewContext.getDrawingRect( viewDrawingRect);

  //已裁剪框drawRect,算出圆的半径
  float radius = (drawRect.right - drawRect.left) / 2;
  //添加一个圆形
  path.addCircle( drawRect.left + radius, drawRect.top + radius, radius, Direction.CW);
  outlinePaint.setColor( highlightColor);

  //裁剪画布,path之外的区域,以outsidePaint填充
  canvas.clipPath( path, Region.Op.DIFFERENCE);
  canvas.drawRect( viewDrawingRect, outsidePaint);

  canvas.restore();
  //绘制圆上高亮线,这里outlinePaint定义的Paint.Style.STROKE:表示只绘制几何图形的轮廓。
  canvas.drawPath( path, outlinePaint);

  //当modifyMode为grow时,绘制handles,也就是那四个小圆
  if(handleMode == HandleMode.Always || (handleMode == HandleMode.Changing && modifyMode == ModifyMode.Grow)) {
  drawHandles( canvas);
  }
 }
 }

这里就实现了画圆形裁剪框的操作。

2. 响应和处理用户触摸事件

1). 判断触摸点坐标与圆的位置

/**
 * 根据x,y坐标,计算其与圆的关系(圆上、圆内、圆外)
 * @param x
 * @param y
 * @return
 */
 private int getHitOnCircle(float x, float y) {
 Rect r = computeLayout();
 int retval = GROW_NONE;
 final float hysteresis = 20F;
 int radius = (r.right - r.left) / 2;

 int centerX = r.left + radius;
 int centerY = r.top + radius;

 //判断触摸位置是否在圆上
 float ret = (x - centerX) * (x - centerX) + (y - centerY) * (y - centerY);
 double rRadius = Math.sqrt( ret);
 double gap = Math.abs( rRadius - radius);

 if(gap <= hysteresis) {// 圆上。这里由于是继承至HighlightView(绘制矩形框的)来处理,所以模拟返回了左右上下,而非纯圆上,亲测可用。你也可以自定义。
  if(x < centerX) {// left
  retval |= GROW_LEFT_EDGE;
  }
  else {
  retval |= GROW_RIGHT_EDGE;
  }

  if(y < centerY) {// up
  retval |= GROW_TOP_EDGE;
  }
  else {
  retval |= GROW_BOTTOM_EDGE;
  }
 }
 else if(rRadius > radius) {// outside
  retval = GROW_NONE;
 }
 else if(rRadius < radius) {// inside,圆内就执行move
  retval = MOVE;
 }

 return retval;
 }

由于是继承至HighLightView(矩形框)来实现的,如果点(x,y)位置圆上,还需判断其它那个象限,对应矩形的上下左右位置。

2).  移动裁剪框

若上一步判断,触摸点在圆内,就会返回MOVE,并处理移动过程。

// Grows the cropping rectangle by (dx, dy) in image space
 void moveBy(float dx, float dy) {
 Rect invalRect = new Rect(drawRect);
 //移动
 cropRect.offset(dx, dy);

 // Put the cropping rectangle inside image rectangle
 cropRect.offset(
  Math.max(0, imageRect.left - cropRect.left),
  Math.max(0, imageRect.top - cropRect.top));

 cropRect.offset(
  Math.min(0, imageRect.right - cropRect.right),
  Math.min(0, imageRect.bottom - cropRect.bottom));

 drawRect = computeLayout();
 invalRect.union(drawRect);
 invalRect.inset(-(int) handleRadius, -(int) handleRadius);
 viewContext.invalidate(invalRect);
 }

移动裁剪框并保证其它image图片显示范围内。

3). 缩放裁剪框

此过程和上一步类似,将cropRect矩阵进行等比缩放即可,这里就细说了,详见代码:HighLightView.growBy(float dx, float dy)

3.将裁剪图片保存为圆形

/**
 * @param bitmap src图片
 * @return
 */
 public static Bitmap getCircleBitmap(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());

 paint.setAntiAlias( true);
 paint.setFilterBitmap( true);
 paint.setDither( true);
 canvas.drawARGB( 0, 0, 0, 0);
 paint.setColor( color);
 //在画布上绘制一个圆
 canvas.drawCircle( bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
 paint.setXfermode( new PorterDuffXfermode( Mode.SRC_IN));
 canvas.drawBitmap( bitmap, rect, rect, paint);
 return output;
 }

注意:将bitmap保存为file时,格式请选择png,不然会出现黑色背景。

鉴于水平有限,从小语文就没学好,描述比较凌乱,需要深入理解的请阅读源代码。

附:另外一个很好开源项目 https://github.com/edmodo/cropper (本地下载)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Android使用CircleImageView实现圆形头像的方法

    有时我们在应用中会用到圆形头像,下面是利用CircleImageView实现圆形头像的演示,下面效果和代码,效果如图 实现起来也比较简单,先在项目中建一个circleimageview包用来存放CircleImageView类,待会直接把CircleImageView类复制到包里就可以使用了 然后,再建一个attrs.xml,其代码相当简单,定义了圆形边框宽度和颜色 <?xml version="1.0" encoding="utf-8"?> <r

  • Android实现本地上传图片并设置为圆形头像

    先从本地把图片上传到服务器,然后根据URL把头像处理成圆形头像. 因为上传图片用到bmob的平台,所以要到bmob(http://www.bmob.cn)申请密钥. 效果图: 核心代码: 复制代码 代码如下: public class MainActivity extends Activity {         private ImageView iv;         private String appKey="";                //填写你的Applicatio

  • android图片处理之让图片变成圆形

    这几天做项目,有些地方的图片需要用到圆形图片,所以百度了一下,在github上找到一个开源项目,处理很简单,效果如下: 使用起来特别简单,一共三步,具体如下: 1.创建一个Java类CircleImageView把下面的代码复制过去,报错的导包 package de.hdodenhof.circleimageview; import edu.njupt.zhb.main.R; import android.content.Context; import android.content.res.T

  • Android自定义控件之圆形/圆角的实现代码

    一.问题在哪里? 问题来源于app开发中一个很常见的场景--用户头像要展示成圆的:  二.怎么搞? 机智的我,第一想法就是,切一张中间圆形透明.四周与底色相同.尺寸与头像相同的蒙板图片,盖在头像上不就完事了嘛,哈哈哈! 在背景纯色的前提下,这的确能简单解决问题,但是如果背景没有这么简单呢? 在这种不规则背景下,有两个问题: 1).背景图常常是适应手机宽度缩放,而头像的尺寸又是固定宽高DP的,所以固定的蒙板图片是没法保证在不同机型上都和背景图案吻合的. 2).在这种非纯色背景下,哪天想调整一下头像

  • Android实现圆形图片的两种方式

    在项目中,我们经常会用到圆形图片,但是android本身又没有提供,那我只能我们自己来完成. 第一种方式,自定义CircleImageView: public class CircleImageView extends ImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Con

  • Android裁剪图片为圆形图片的实现原理与代码

    以前在eoe论坛中找过裁剪图片为圆形图片的方法,但是效果都不是很理想,这几天因为公司业务的要求,需要对头像进行裁剪以圆形的方式显示,这个方法是根据传入的图片的高度(height)和宽度(width)决定的,如果是 width <= height时,则会裁剪高度,裁剪的区域是宽度不变高度从顶部到宽度width的长度:如果 width > height,则会裁剪宽度,裁剪的区域是高度不变,宽度是取的图片宽度的中心区域,不过不同的业务需求,对裁剪图片要求不一样,可以根据业务的需求来调整裁剪的区域.

  • Android实现圆角矩形和圆形ImageView的方式

    Android中实现圆角矩形和圆形有很多种方式,其中最常见的方法有ImageLoader设置Option和自定义View. 1.ImageLoader加载图片 public static DisplayImageOptions getRoundOptions() { DisplayImageOptions options = new DisplayImageOptions.Builder() // 是否设置为圆角,弧度为多少,当弧度为90时显示的是一个圆 .displayer(new Round

  • Android中ImageCropper矩形、圆形 裁剪框的实现方法

    前言 支持圆形裁剪框,裁剪后生成圆形图案. 代码基于开源项目修改,github上项目链接:https://github.com/shengge/android-crop (本地下载) 还是贴下效果图: 说一下圆形裁剪实现部分: 1.UI方面,自定义CircleHighlightView继承至HighlightView(原有的矩形裁剪框实现),直接看draw方法实现 @Override protected void draw(Canvas canvas) { canvas.save(); Path

  • Android自定义View实现照片裁剪框与照片裁剪功能

    本文所需要实现的就是这样一种有逼格的效果: 右上角加了个图片框,按下确定可以裁剪正方形区域里的图片并显示在右上角. 实现思路: 1:首先需要自定义一个ZoomImageView来显示我们需要的图片,这个View需要让图片能够以合适的位置展现在当前布局的图片展示区域内(合适的位置值的是:如果图片长度大于屏幕,则压缩图片长度至屏幕宽度,高度等比压缩并居中显示,如果图片高度大于屏幕,则压缩图片高度至屏幕高度,长度等比压缩并居中显示.): 2:然后需要实现这个拖动的框框,该框框实现的功能有四点:拖动.扩

  • 浅析Android中常见三种弹框在项目中的应用

    一丶概述 弹框在Android项目中经常出现,常见的实现方法有三种:Dialog 弹框,Window弹框,Activity伪弹框.本文就说一说三种弹框的实现及在项目中的运用. 二丶演示图         图一为常见的三种弹框(文末上链接),图二为项目中用到的Activity伪弹框 三丶正文 1.Dialog弹框 先看一篇一篇文章: android 8种对话框(Dialog)使用方法汇总 Dialog是系统自带的弹框,然而常常因为UI不好看而遭嫌弃,常需要自定义 public class MyDi

  • Android中 TeaScreenPopupWindow多类型筛选弹框功能的实例代码

    Github地址 YangsBryant/TeaScreenPopupWindow (Github排版比较好,建议进入这里查看详情,如果觉得好,点个star吧!) 引入module allprojects { repositories { google() jcenter() maven { url 'https://www.jitpack.io' } } } implementation 'com.github.YangsBryant:TeaScreenPopupWindow:1.0.2' 主

  • Android中使用RecylerView实现聊天框效果

    从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活.在上篇文章给大家介绍了Android RecylerView入门教程,大家可以点击查看详情. 效果图如下:(其中,聊天框背景图用9-patch图,可以内容自适应调节.利用AndroidStudio自带的功能制作就行了,图片->右键->create 9-patch file. 其中要注意的是: 1.将9-patch图保存到drawable目录下才管用

  • Android中使用TextView实现图文混排的方法

    向TextView或EditText中添加图像比直接添加文本复杂一点点,需要用到<img>标签. <img>只有一个src属性,该属性原则上应该指向一个图像地址或可以找到某个图像资源的唯一标识.但要注意的是,系统并不会直接根据src属性所指的值自动获取和显示图像,这一切都需要我们去做.说白了,src属性指的是什么只有开发者自己知道.开发者需要告诉系统src属性到底指的是什么,然后系统才会知道怎么做. 解析src属性值需要ImageGetter对象的getDrawable方法来完成.

  • Android中捕捉menu按键点击事件的方法

    本文实例讲述了Android中捕捉menu按键点击事件的方法.分享给大家供大家参考.具体如下: @Override public boolean onCreateOptionsMenu(Menu menu) { /* * add()方法的四个参数,依次是: 1.组别,如果不分组的话就写Menu.NONE, * 2.Id,这个很重要,Android根据这个Id来确定不同的菜单 3.顺序,那个菜单现在在前面由这个参数的大小决定 * 4.文本,菜单的显示文本 */ menu.add(Menu.NONE

  • Android中EditText 设置 imeOptions 无效问题的解决方法

    有时候我们需要在EditText  输出完之后 需要在键盘出现 右下角变成"Go"或"前往 搜索时:通常我们需要设置Android:imeOptions属性.Android:imeOptions的值有actionGo. actionSend .actionSearch.actionDone等 但是今天我发现设置了无效  那是因为我设置了 android:maxLines="1" 解决方法 就是去掉 android:maxLines="1"

  • Android中选项菜单(OptionMenu)的创建方法

    使用OptionMenu 只要重写两个方法 public boolean onCreateOptionsMenu(Menu menu):菜单的初始化 public boolean onOptionsItemSelected(MenuItem item):菜单响应事件 除此之外,还有三个方法可以重写 public void onOptionsMenuClosed(Menu menu):菜单关闭时调用 public boolean onPrepareOptionsMenu(Menu menu):选项

  • Android中invalidate()和postInvalidate() 的区别及使用方法

    Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用. Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用. invalidate()是用来刷新View的,必须是在UI线程中进行工作.比如在修改某个view的显示时,调用inval

随机推荐