• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android开发技巧——定制仿微信图片裁剪控件

Android开发技巧——定制仿微信图片裁剪控件

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android开发控件,android开发技巧,android gui控件开发,android开发小技巧,android开发等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android开发技巧——定制仿微信图片裁剪控件


拍照——裁剪,或者是选择图片——裁剪,是我们设置头像或上传图片时经常需要的一组操作。上篇讲了Camera的使用,这篇讲一下我对图片裁剪的实现。

背景

下面的需求都来自产品。 裁剪图片要像微信那样,拖动和放大的是图片,裁剪框不动。 裁剪框外的内容要有半透明黑色遮罩。 裁剪框下面要显示一行提示文字(这点我至今还是持保留意见的)。

在Android中,裁剪图片的控件库还是挺多的,特别是github上比较流行的几个,都已经进化到比较稳定的阶段,但比较遗憾的是它们的裁剪过程是拖动或缩放裁剪框,于是只好自己再找,看有没有现成或半成品的轮子,可以不必从零开始。

大神的实现过程

首先先了解一下上面的高仿微信裁剪控件的实现过程。说起来也不难,主要是下面几点:
1,重写ImageView,并监听手势事件,包括双点,两点缩放,拖动,使它成为一个实现缩放拖动图片功能的控件。
2,定义一个Matrix成员变量,对于维护该图片的缩放、平移等矩阵数据。
3,拖动或缩放时,图片与裁剪框的相交面积一定与裁剪框相等。即图片不能拖离裁剪框。
3,在设置图片时,先根据图片的大小进行初始化的缩放平移操作,使得上面第三条的条件下图片尽可能的小。
4,每次接收到相对应的手势事件,都进行对应的矩阵计算,并将计算结果通过ImageView的setImageMatrix方法应用到图片上。
5,裁剪框是一个单独的控件,与ImageView同样大,叠加到它上面显示出来。
6,用一个XXXLayout把裁剪框和缩放封装起来。
7,裁剪时,先创建一个空的Bitmap并用其创建一个Canvas,把缩放平移后的图片画到这个Bitmap上,并创建在裁剪框内的Bitmap(通过调用Bitmap.createBitmap方法)。

我的定制内容

我拿到的代码是鸿洋大神版本之后再被改动的,代码上有点乱(虽然功能上是实现的裁剪)。在原有的功能上,我希望进行的改动有:

合并裁剪框的内容到ImageView中 裁剪框可以是任意长宽比的矩形 裁剪框的左右外边距可以设置 遮罩层颜色可以设置 裁剪框下有提示文字(自己的产品需求) 后面产品又加入了一条裁剪图片的最大大小

属性定义

在上面的功能需求中,我定义了以下属性:

<code class="language-xml hljs "><declare-styleable name="ClipImageView">
    <attr name="civHeight" format="integer">
    <attr name="civWidth" format="integer">
    <attr name="civTipText" format="string">
    <attr name="civTipTextSize" format="dimension">
    <attr name="civMaskColor" format="color">
    <attr name="civClipPadding" format="dimension">
</attr></attr></attr></attr></attr></attr></declare-styleable></code>

其中:

civHeight和civWidth是裁剪框的宽高比例。 civTipText提示文字的内容 civTipTextSize提示文字的大小 civMaskColor遮罩层的颜色值 civClipPadding裁剪内边距。由于裁剪框是在控件内部的,最终我选择使用padding来说明裁剪框与我们控件边缘的距离。

成员变量

成员变量我进行了一些改动,把原本用于定义裁剪框的水平边距变量及其他没什么用的变量等给去掉了,并加入了自己的一些成员变量,最终如下:

    private final int mMaskColor;//遮罩层颜色

    private final Paint mPaint;//画笔
    private final int mWidth;//裁剪框宽的大小(从属性上读到的整型值)
    private final int mHeight;//裁剪框高的大小(同上)
    private final String mTipText;//提示文字
    private final int mClipPadding;//裁剪框相对于控件的内边距

    private float mScaleMax = 4.0f;//图片最大缩放大小
    private float mScaleMin = 2.0f;//图片最小缩放大小

    /**
     * 初始化时的缩放比例
     */
    private float mInitScale = 1.0f;

    /**
     * 用于存放矩阵
     */
    private final float[] mMatrixValues = new float[9];

    /**
     * 缩放的手势检查
     */
    private ScaleGestureDetector mScaleGestureDetector = null;
    private final Matrix mScaleMatrix = new Matrix();

    /**
     * 用于双击
     */
    private GestureDetector mGestureDetector;
    private boolean isAutoScale;

    private float mLastX;
    private float mLastY;

    private boolean isCanDrag;
    private int lastPointerCount;

    private Rect mClipBorder = new Rect();//裁剪框
    private int mMaxOutputWidth = 0;//裁剪后的图片的最大输出宽度

构造方法

构造方法里主要是多了一些我们自定义属性的读取:


    public ClipImageView(Context context) {
        this(context, null);
    }

    public ClipImageView(Context context, AttributeSet attrs) {
        super(context, attrs);

        setScaleType(ScaleType.MATRIX);
        mGestureDetector = new GestureDetector(context,
                new SimpleOnGestureListener() {
                    @Override
                    public boolean onDoubleTap(MotionEvent e) {
                        if (isAutoScale)
                            return true;

                        float x = e.getX();
                        float y = e.getY();
                        if (getScale() < mScaleMin) {
                            ClipImageView.this.postDelayed(new AutoScaleRunnable(mScaleMin, x, y), 16);
                        } else {
                            ClipImageView.this.postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16);
                        }
                        isAutoScale = true;

                        return true;
                    }
                });
        mScaleGestureDetector = new ScaleGestureDetector(context, this);
        this.setOnTouchListener(this);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.WHITE);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ClipImageView);
        mWidth = ta.getInteger(R.styleable.ClipImageView_civWidth, 1);
        mHeight = ta.getInteger(R.styleable.ClipImageView_civHeight, 1);
        mClipPadding = ta.getDimensionPixelSize(R.styleable.ClipImageView_civClipPadding, 0);
        mTipText = ta.getString(R.styleable.ClipImageView_civTipText);
        mMaskColor = ta.getColor(R.styleable.ClipImageView_civMaskColor, 0xB2000000);
        final int textSize = ta.getDimensionPixelSize(R.styleable.ClipImageView_civTipTextSize, 24);
        mPaint.setTextSize(textSize);
        ta.recycle();

        mPaint.setDither(true);
    }

定义裁剪框

裁剪框的位置

裁剪框是在控件正中间的,首先我们从属性中读取到的是宽高的比例,以及左右边距,但是在构造方法中,由于控件还没有绘制出来,无法获取到控件的宽高,所以并不能计算裁剪框的大小和位置。所以我重写了onLayout方法,在这里计算裁剪框的位置:

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        final int width = getWidth();
        final int height = getHeight();
        mClipBorder.left = mClipPadding;
        mClipBorder.right = width - mClipPadding;
        final int borderHeight = mClipBorder.width() * mHeight / mWidth;
        mClipBorder.top = (height - borderHeight) / 2;
        mClipBorder.bottom = mClipBorder.top + borderHeight;
    }

绘制裁剪框

这里我顺便把绘制提示文字的代码也一并给出,都是在同一个方法里的。很简单,重写onDraw方法即可。绘制裁剪框有两种方法,一是绘制一个满屏的遮罩层,然后从中间抠出一个长方形出来,但是我用的时候发现抠不出来,所以我采用的是下面这一种:
这里写图片描述
先画上下两个矩形,再画左右两个矩形,中间所围起来的没有画的部分就是我们的裁剪框。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android开发:控件之WebView
  • Android开发技巧——定制仿微信图片裁剪控件

相关文章

  • 2017-05-26APP级别处理未捕获异常,APP级别处理捕获
  • 2017-05-26android开发之路11(用SharedPreferences存储数据),sharedpreferences
  • 2017-05-26Android屏幕适配方案
  • 2017-05-26连点处理,禁止按钮在短时间内被多次点击,按钮短时间内
  • 2017-05-26一个特别适合新手练习的Android小项目——每日一妹纸
  • 2017-05-26【原创】Android ExpandableListView使用,expandablelistview
  • 2017-05-26Android学习资料整理
  • 2017-05-26Android防止过快点击造成多次事件
  • 2017-05-26解决Android Graphical Layout 界面效果不显示,androidgraphical
  • 2017-05-26最新Android系统版本与API等级对应关系表,androidapi

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Linux内核系列—6.操作系统开发之内存分页机制,linux分页
    • win通过dos配置注册列表
    • 8.3.2 绘图类实战示例
    • 我的android学习经历11,android学习经历11
    • linux命令之tcpdump
    • View的layout机制,Viewlayout机制
    • 关于Android项目隐藏标题栏的方法总结,android标题栏
    • eclipse搭建android开发环境详细步骤,eclipseandroid
    • 自定义加载loading view动画组件的使用。,loadingview
    • 手势检测GestureDetector,gesturedetector

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有