Android实现刮刮卡效果,zxing第三方库的使用【美

2020-03-17 07:38 来源:未知

二维码呀,以往的品种为主都有的东西,早本来就有人写出来了,小编也是在用外人的基础上写写心得啊什么的,本身包裹叁个还未那日子和本领去搞,所以这篇随笔讲的就是怎么用。

业已好些天未有写小说了,目前径直在钻探怎么样自定义“下拉刷新”控件。笔者日啊,对于本身的话太难了,看了一点天SwipeRefreshLayout的源码,一脸懵逼,本人的demo也是写到二分之一就写不下去了。等改天有时光了再去商讨钻探。明天是礼拜日,白天学了点新知识,早晨出去练了会儿舞(不是广场舞),曾经在写博客,等下就睡了。

前言

新近给和谐挖了多少个坑,筹算填一下。现在来填一下先是个坑:图片模糊。关于图片模糊的艺术有成都百货上千,比如:Open CV 的各类图片管理、Android 协理的高品质密集型任务施行框架 RenderScript、Java 只怕 C/C 的算法达成图片模糊管理。本篇作品将满含以下内容:

  • RenderScript 简单介绍与图片模糊的兑现
  • Java / C 算法完结图片模糊管理
  • 多少个粗略的动态模糊完结
  • 总结

有关 Open CV 小编从前的有的文有个别轻便的牵线,假若只是想模糊图片就引进整个的 Open CV 个人感到依旧有一些“杀鸡用牛刀”的痛感。对了,关于算法达成怎样的……小编只是个代码搜聚者,而不是本人要好完毕的。

始发在此之前先放个图,做成什么心里有些x数

美高梅网投网址 1

动态模糊.gif

假定您看过小编同学的那篇Android:轻便可靠的动态高斯模糊效果 你一定会开掘自家这些结构跟他的有那么一些相同,哇哈哈哈哈哈,你猜对了,笔者去他项目里复制的。当然了,完毕格局不相通,他是用的 RecyclerView 完毕的,笔者那边就本人复写了 Activity 的 onTouch 实现的动态模糊。

入坑前奏

近日项目中须要增加生成条形码的效率,leader只说了一句:一天成功。因为事情未发生前做过二维码(但未有选择zxing),心里想一天应该没难点,就随便张口答应了。接下来以前入坑,首先,条形码今后利用的虽多,但调换的却比相当少,百度谷歌(GoogleState of Qatar搜了刹那间,有zbar,zxing第三方推荐,还应该有的用的苹果自带的扭转效率。首先说说自带的支撑生成条形码,它可以改变,可是只是永葆三种条形码的编码标准,小编用部分扫码应用程式扫,是能出来的,用扫码枪也能出来,况兼速度极快,相当欢乐,然后就在代码中增添了这一个效果。心想,就这么欢欣的消除了。其实是本身想多了。
因为条形码有不菲的编码标准,如:code39,code128,等等十两种。当然大家的产品也要帮忙那样七种,听到后台职员跟自家说,根据重回编码标示举行编码彰显。立即头就大了,那是何等鬼。随后一连百度,然后看到一篇文章:http://blog.sina.com.cn/s/blog_881ed8500102v14b.html 那位小编说zxing能够生成条形码并且作用非常高。又开玩笑了,继续找zxing,一向找到它的老家https://github.com/TheLevelUp/ZXingObjC 快乐的下载了他们的源码,140M左右,下载下来看了看此中的demo。

美高梅网投网址 2

显示屏快速照相 二〇一五-11-05 早晨1.20.42.png

观看里面有多个工程,因为在下没什么见识,真不知道那是如何鬼,怎会有七个工程,以为使用了Cocoa,后来才领会那是引用了另七个工程,作者的连串里总不能够像她们这么用吗,然后又通晓了,能够运用framework来用那一个API。

美高梅网投网址 3二维码

有人问,为啥以往开源的自定义View这么多,我们还要自身困苦去造轮子。有个博主已经说过,笔者觉着说得很好。他说,未来无数的开源库适用性相比广,大家即便去选择它,你会意识,相当多效应大家是用不到的,何况会让程序包增大。不是团结写的代码,维护起来也是十一分困难,万一何时首席营业官让你改一下里边的东西,你就懵逼了。

RenderScript

第一简单的牵线一下 RenderScript 这里是自己读文书档案的翻译……又到了表现真正的辣鸡法语水平的时候了……

RenderScript 是 Android 上的高质量总计密集型任务的框架。尽管串行职业也能收益,不过RenderScript 首要面向并行数据测算。RenderScript 运营时得以超越设备上可用的微处理机如多核CPU和GPU进行互相职业。那让您可以当心于算法,并非调节职业。RenderScript 对于使用进行图像管理,计算水墨画或然Computer视觉等方面特别有用。
要从头采用RenderScript,有七个重大约念应该要领会:

  • 言语本人是为了编写制定高质量总计代码发生的 C99 衍生语言。那篇文章陈诉了哪些运用它去编写叁个计量内核。

  • 支配 API 是用来处理 RenderScript 能源的生命周期和调控内核运营的。那套API有三套语言完成:Java,Android NDK 的 C 和 C99 派生的根本语言自己。

恩,BB这么多,大家只供给有个大约概念就能够了,因为亦不是特意去上学这套框架,大家只是须求选拔那套框架的一丁点图形管理相关的事物而已。千万个言语,最后就一句话:

RenderScript 是 Android 上的高性能计算密集型任务的框架

行,对 RenderScript 有了大约的询问后,能够开头了,官方文书档案里实际有比较详细的流程,先成立什么 context 啦,然后分配内部存款和储蓄器巴拉巴拉的拉,不过作者那又不是在学RenderScript,而是想达成贰个效果与利益,用完就能够把那框架扔一边了,借使您也是这么,无妨直接copy 上面包车型的士代码:

    /**
     * 图片缩放比例
     */
    private static final float BITMAP_SCALE = 0.4f;
    /**
     * 最大模糊度(在0.0到25.0之间)
     */
    private static final float BLUR_RADIUS = 25f;

    public static Bitmap blur(Context context, Bitmap image) {
        // 计算图片缩小后的长宽
        int width = Math.round(image.getWidth() * BITMAP_SCALE);
        int height = Math.round(image.getHeight() * BITMAP_SCALE);

        // 将缩小后的图片作为预渲染的图片
        Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
        // 创建一张渲染后的输出图片
        Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);

        // 初始化 RenderScript 上下文
        RenderScript rs = RenderScript.create(context);
        // 创建一个模糊效果的 RenderScript 的工具对象
        ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

        // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间。
        // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去。
        Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
        // 设置渲染的模糊程度, 25f是最大模糊度
        blur.setRadius(BLUR_RADIUS);
        // 设置blurScript对象的输入内存
        blur.setInput(tmpIn);
        // 将输出数据保存到输出内存中
        blur.forEach(tmpOut);
        // 将数据填充到Allocation中
        tmpOut.copyTo(outputBitmap);
        return outputBitmap;
    }

运作效果:

美高梅网投网址 4

renderscript.png

framework实现:

美高梅网投网址 5

11D17A2C-21A2-4D43-B640-6BA815C01431.png

自家申明的1是.a文件的静态库,2,3是framework文件,叁个是iOS系统下的叁个是osx系统下的。小编那些截图中自己标记的那三个文本其实都以编写翻译过的,所以字体是玫瑰紫红,没编写翻译的时候是戊辰革命的。怎么来编写翻译呢?
率先,看下图,选中iOS那些framework,那么是选用在模拟器下编写翻译还是iOS设备呢?这一个难题亟待潜心:如果采纳模拟器的话,在真机调节和测验中会现身谬误,假若在iOS设备中编写翻译在模拟器调节和测量检验时会现身错误,消除这一个艺术的正是三个都编写翻译,然后把多少个framework包合并。合并的学科在下一篇blog中安详严整。
接下去大家筛选在模拟器中编写翻译。(注:编写翻译成功今后你会发掘produces下的framework的字心得化为赤褐)

美高梅网投网址 6

显示器快速照相 二〇一五-11-05 深夜1.37.26.png

编写翻译成功之后,点击编译好的可怜framework右击在文件中开荒,相会世如下图所示:

美高梅网投网址 7

4B047425-FF4D-449C-A288-37DD74D6E68F.png

自己标明1的是iOS设备编写翻译之后的文本夹,标记2的是模拟器下编写翻译的公文夹。
大家能够看到那儿已经有了zxingobjc.framework这一个文件。大家中标的编译好了那几个包。那么接下去本身就起来应用了。再次提示这里大家是在模拟器意况下编写翻译得到的包。

呃,图有一些大,好像还洞穿了某个音讯,算了不管了,就那样吗。


Java & C

这两种都以使用相通种算法达成的,本质上都是对像素数组实行拍卖运算。本来小编以为C 的措施会快一些,没悟出在自己的mix2上运转反而是Java实现的算法会快一些。唉,真是辣鸡C 还不及Java。 当然了……讲道理,代码小编看了,正是同等的,或然是jni的支出啊。这里怎么要介绍Javah和C 的算法实现啊,因为RenderScript尽管文档上说能够运作在2.3及以上的阳台,不过那几个图形处理的api最低版本是17。所以说,假设您有亟待匹配低版本,照旧得使用下其他达成。

此地只放一下Java的兑今世码,因为反而非常的慢的关联……至于JNI,作者这里偷了个懒,因为在此以前用CMake项目编写翻译生成了so,所以那边直接援用了so。当然了cpp源码也坐落于了连串里,感兴趣的能够温和去编写翻译一下:

    /**
     * StackBlur By Java Bitmap
     *
     * @param bmp    bmp Image
     * @param radius Blur radius
     * @return Image Bitmap
     */
    public static Bitmap blurInJava(Bitmap bmp, int radius) {
        // Stack Blur v1.0 from
        // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
        //
        // Java Author: Mario Klingemann <mario at quasimondo.com>
        // http://incubator.quasimondo.com
        // created Feburary 29, 2004
        // Android port : Yahel Bouaziz <yahel at kayenko.com>
        // http://www.kayenko.com
        // ported april 5th, 2012

        // This is a compromise between Gaussian Blur and Box blur
        // It creates much better looking blurs than Box Blur, but is
        // 7x faster than my Gaussian Blur implementation.
        //
        // I called it Stack Blur because this describes best how this
        // filter works internally: it creates a kind of moving stack
        // of colors whilst scanning through the image. Thereby it
        // just has to add one new block of color to the right side
        // of the stack and remove the leftmost color. The remaining
        // colors on the topmost layer of the stack are either added on
        // or reduced by one, depending on if they are on the right or
        // on the left side of the stack.
        //
        // If you are using this algorithm in your code please add
        // the following line:
        //
        // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
        if (radius < 1) {
            return (null);
        }

        Bitmap bitmap = ratio(bmp, bmp.getWidth() * BITMAP_SCALE, bmp.getHeight() * BITMAP_SCALE);
//        Bitmap bitmap = bmp.copy(Bitmap.Config.ARGB_8888, true);
        // Return this none blur
        if (radius == 1) {
            return bitmap;
        }
        bmp.recycle();

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        int[] pix = new int[w * h];
        // get array
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);

        // run Blur
        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius   radius   1;

        short r[] = new short[wh];
        short g[] = new short[wh];
        short b[] = new short[wh];
        int rSum, gSum, bSum, x, y, i, p, yp, yi, yw;
        int vMin[] = new int[Math.max(w, h)];

        int divSum = (div   1) >> 1;
        divSum *= divSum;

        short dv[] = new short[256 * divSum];
        for (i = 0; i < 256 * divSum; i  ) {
            dv[i] = (short) (i / divSum);
        }

        yw = yi = 0;

        int[][] stack = new int[div][3];
        int stackPointer;
        int stackStart;
        int[] sir;
        int rbs;
        int r1 = radius   1;
        int routSum, goutSum, boutSum;
        int rinSum, ginSum, binSum;

        for (y = 0; y < h; y  ) {
            rinSum = ginSum = binSum = routSum = goutSum = boutSum = rSum = gSum = bSum = 0;
            for (i = -radius; i <= radius; i  ) {
                p = pix[yi   Math.min(wm, Math.max(i, 0))];
                sir = stack[i   radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);

                rbs = r1 - Math.abs(i);
                rSum  = sir[0] * rbs;
                gSum  = sir[1] * rbs;
                bSum  = sir[2] * rbs;
                if (i > 0) {
                    rinSum  = sir[0];
                    ginSum  = sir[1];
                    binSum  = sir[2];
                } else {
                    routSum  = sir[0];
                    goutSum  = sir[1];
                    boutSum  = sir[2];
                }
            }
            stackPointer = radius;

            for (x = 0; x < w; x  ) {

                r[yi] = dv[rSum];
                g[yi] = dv[gSum];
                b[yi] = dv[bSum];

                rSum -= routSum;
                gSum -= goutSum;
                bSum -= boutSum;

                stackStart = stackPointer - radius   div;
                sir = stack[stackStart % div];

                routSum -= sir[0];
                goutSum -= sir[1];
                boutSum -= sir[2];

                if (y == 0) {
                    vMin[x] = Math.min(x   radius   1, wm);
                }
                p = pix[yw   vMin[x]];

                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);

                rinSum  = sir[0];
                ginSum  = sir[1];
                binSum  = sir[2];

                rSum  = rinSum;
                gSum  = ginSum;
                bSum  = binSum;

                stackPointer = (stackPointer   1) % div;
                sir = stack[(stackPointer) % div];

                routSum  = sir[0];
                goutSum  = sir[1];
                boutSum  = sir[2];

                rinSum -= sir[0];
                ginSum -= sir[1];
                binSum -= sir[2];

                yi  ;
            }
            yw  = w;
        }
        for (x = 0; x < w; x  ) {
            rinSum = ginSum = binSum = routSum = goutSum = boutSum = rSum = gSum = bSum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i  ) {
                yi = Math.max(0, yp)   x;

                sir = stack[i   radius];

                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];

                rbs = r1 - Math.abs(i);

                rSum  = r[yi] * rbs;
                gSum  = g[yi] * rbs;
                bSum  = b[yi] * rbs;

                if (i > 0) {
                    rinSum  = sir[0];
                    ginSum  = sir[1];
                    binSum  = sir[2];
                } else {
                    routSum  = sir[0];
                    goutSum  = sir[1];
                    boutSum  = sir[2];
                }

                if (i < hm) {
                    yp  = w;
                }
            }
            yi = x;
            stackPointer = radius;
            for (y = 0; y < h; y  ) {
                // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                pix[yi] = (0xff000000 & pix[yi]) | (dv[rSum] << 16) | (dv[gSum] << 8) | dv[bSum];

                rSum -= routSum;
                gSum -= goutSum;
                bSum -= boutSum;

                stackStart = stackPointer - radius   div;
                sir = stack[stackStart % div];

                routSum -= sir[0];
                goutSum -= sir[1];
                boutSum -= sir[2];

                if (x == 0) {
                    vMin[y] = Math.min(y   r1, hm) * w;
                }
                p = x   vMin[y];

                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];

                rinSum  = sir[0];
                ginSum  = sir[1];
                binSum  = sir[2];

                rSum  = rinSum;
                gSum  = ginSum;
                bSum  = binSum;

                stackPointer = (stackPointer   1) % div;
                sir = stack[stackPointer];

                routSum  = sir[0];
                goutSum  = sir[1];
                boutSum  = sir[2];

                rinSum -= sir[0];
                ginSum -= sir[1];
                binSum -= sir[2];

                yi  = w;
            }
        }

        // set Bitmap
        bitmap.setPixels(pix, 0, w, 0, 0, w, h);

        return (bitmap);
    }

美高梅网投网址 8

image.png

在工程中加多.framework包:

自己自便建了多个工程,第一步将大家刚刚编写翻译后的包拖入工程;

美高梅网投网址 9

4CB5F21C-41FF-4EC6-8AB9-6D622A1FCCD1.png

第二步:如图,点击那些加号;

美高梅网投网址 10

6D1909FC-1254-4A95-A4C2-46DFB8A044D6.png

第三步:添加包

美高梅网投网址 11

A679CF5B-AAB4-45CD-9C09-E361B9B912F2.png

第四步:导入头文件就OK了。如图所示。

美高梅网投网址 12

3406CF88-65B1-4833-9589-5DAA6916C1FA.png

效用大约正是如此的。

美高梅网投网址 13

动态模糊

此地实现的法力图便是发端的那张gif了,首先要领悟某个,动态模糊,不容许每一帧都去调用方法生成一张模糊图,那样作用太低了。这里看了外人的思路,先生成一张模糊图片,之后在原先的布局上放上七个ImageView,一张原图,上边的一张是混淆图,动态更换上面模糊图的透明值就能够兑现动态透明效果。那主张阔以,只生成了一回模糊图片。

此处尾巴部分布局作者本来是想放二个构造在显示屏外,后来发觉这么不管怎么滑动都不可能把布局滑入。恐怕是代码有标题,也恐怕是父容器的难题。于是之后就写了个全屏的布局,但是在分界面运转后将之移动到荧屏外。设置了上下两块可点击将布局滑出的区域,在滑行的时候动态设置模糊图片控件的阿尔法值,那样就落到实处了动态模糊,话相当的少说,上海重机厂要代码:
构造代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@ id/iv_img"
        android:src="@drawable/test"
        android:scaleType="fitXY"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@ id/iv_blur_img"
        android:scaleType="fitXY"
        android:alpha="0"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <LinearLayout
        android:id="@ id/rl_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@ id/tv_tem"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:fontFamily="sans-serif-thin"
            android:gravity="bottom"
            android:text="37°"
            android:textColor="@android:color/white"
            android:textSize="90sp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:layout_marginTop="36dp"
            android:background="#44000000"
            android:orientation="vertical"
            android:paddingLeft="20dp">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="WeatherInfo"
                android:textColor="@android:color/white"
                android:textSize="24sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="10dp"
                android:text="Show more info"
                android:textColor="@android:color/white" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:layout_marginTop="36dp"
            android:background="#44000000"
            android:orientation="vertical"
            android:paddingLeft="20dp">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="WeatherInfo"
                android:textColor="@android:color/white"
                android:textSize="24sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="10dp"
                android:text="Show more info"
                android:textColor="@android:color/white" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:layout_marginTop="36dp"
            android:background="#44000000"
            android:orientation="vertical"
            android:paddingLeft="20dp">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="WeatherInfo"
                android:textColor="@android:color/white"
                android:textSize="24sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="10dp"
                android:text="Show more info"
                android:textColor="@android:color/white" />
        </LinearLayout>

    </LinearLayout>

</RelativeLayout>

Activity代码:

package com.xiasuhuei321.blur;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;

import com.xiasuhuei321.gank_kotlin.ImageProcess;

/**
 * Created by xiasuhuei321 on 2017/10/15.
 * author:luo
 * e-mail:xiasuhuei321@163.com
 */

public class DynamicBlurActivity extends AppCompatActivity {

    private ImageView blurImg;
    private int height;
    private View container;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
        //获得当前窗体对象
        Window window = this.getWindow();
        //设置当前窗体为全屏显示
        window.setFlags(flag, flag);
        setContentView(R.layout.activity_dynamic_blur);
        initView();
        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        height = wm.getDefaultDisplay().getHeight();
    }

    private void initView() {
        blurImg = (ImageView) findViewById(R.id.iv_blur_img);
        blurImg.setImageBitmap(ImageProcess.blur(this,
                BitmapFactory.decodeResource(getResources(), R.drawable.test)));
        container = findViewById(R.id.rl_container);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                container.setTranslationY(height   100);
            }
        }, 100);
    }

    float y;
    boolean scrollFlag = false;
    float sumY = 0;
    boolean isShow = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                y = event.getY();
                if (y > height * 0.9) {
                    scrollFlag = true;
                } else if (y < height * 0.1) {
                    if (!isShow) return false;
                    scrollFlag = true;
                }
                break;

            case MotionEvent.ACTION_MOVE:
                sumY = event.getY() - y;
                if (scrollFlag) {
                    container.setTranslationY(event.getY());
                    if (!isShow) blur(sumY);
                    else reverseBlur(sumY);
                }
                Log.e("DynamicBlurActivity", "滚动sumY值:"   sumY   " scrollFlag:"   scrollFlag);

                break;

            case MotionEvent.ACTION_UP:
                if(scrollFlag) {
                    if (Math.abs(sumY) > height * 0.5) {
                        if (isShow) hide();
                        else show();
                    } else {
                        if (isShow) show();
                        else hide();
                    }
                    sumY = 0;
                }
                scrollFlag = false;
                break;
        }

        return true;
    }

    private void hide() {
        container.setTranslationY(height   100);
        blur(0);
        isShow = false;
    }

    private void show() {
        container.setTranslationY(0);
        blur(1000);
        isShow = true;
    }

    private void blur(float sumY) {
        float absSum = Math.abs(sumY);
        float alpha = absSum / 1000;
        if (alpha > 1) alpha = 1;
        blurImg.setAlpha(alpha);
    }

    private void reverseBlur(float sumY) {
        float absSum = Math.abs(sumY);
        float alpha = absSum / 1000;
        if (alpha > 1) alpha = 1;
        blurImg.setAlpha(1 - alpha);
    }
}

直白托文件贯彻导入

这是倒包的措施来落实利用zxing,还应该有一种方式相比暴力以作者之见。正是直接拖文件。当从github上下载之后您会发觉如图所示的文本夹,我们所供给的文本都在这里地了,只要把那些文件拖到打大家的品种中就能够动用了,那个文件2.8M,万幸能肩负。模拟器的framework2.7M,而iOS设备到达了4.7M稍稍选用不了啊。所以作者或然选取了拖文件的主意。可是要小心拖入项目中事后会出几十三个谬误:如图所示

美高梅网投网址 14

FF41A6A3-93E4-46FF-ACB0-A39AB3EA714A.png

看代码里的不当你就能够意识这些错误正是紧缺头文件<UIKit/UIKit.h>招致的谬误,还或然有微量的多少个头文件贫乏<Foundation/Foundation.h>这么些系统库
。二个二个导入就能够了。

接下去讲讲怎么贯彻的:

美高梅网投网址,早前向来想怎么促成二个刮刮卡作用,然而才能简单,所以就直接拖着。今日凌晨闲着没事,就不管敲了敲代码,一运维,发掘存功了,小编擦!那时也是很好奇,并从未认为很难的萧规曹随,但是从前确实觉获得挺难的。不管怎么说,既然做出来了,就教大家怎么来完成那样的意义吗。

总结

在刚从前的时候小编格外的轻生,接纳的图片是1080 * 一九一七的,在管理的时候一看内存,俺 * 飙到了200多M,况兼管理那张图片成本了6.6秒左右的日子。小编打字与印刷了一下这图片转造成Bitmap的width和height 分别是

美高梅网投网址 15

长宽

那只假如 A凯雷德GB_8888 那么一张图就是61M,加上管理必要一个像素数组,得,另一个61M。剩下在管理像素的时候各样申请的内存飙到200M也未为不可以见到。本来笔者想是还是不是足以应用雷同张 Bitmap,在最终setPixels的时候就不用再提请二回内部存款和储蓄器了,可是发掘这么十一分,直接报错了。因为从能源文件获得的 Bitmap 的 isMutable属性是false,不得以一贯在原本的 Bitmap 上 setPixels 。所以本来还须要拷贝一份Bitmap,可是拷贝之后方可将调用 bitmap.recycle(卡塔尔方法,将之赶紧回笼了。

金科玉律,像本身这么头铁硬怼并糟糕,飙到200M市道上相当多部手提式有线电话机都会OOM……越来越好的法子是对缩略图举办模糊处理。Android里有个缩略图工具,就几个主意,还非常好用的,小编那边就用的缩略图工具得到缩略图:

    public static Bitmap ratio(Bitmap bmp, float pixelW, float pixelH) {
        return ThumbnailUtils.extractThumbnail(bmp, (int) pixelW, (int) pixelH);
    }

在开展管理前先获得缩略图,然后再去管理成效确实会高超多。

最后,放上项目地址:https://github.com/ForgetAll/Blur

总结

第一,自己反省,为何如此轻便的贰个事物会煎熬成那样吗?只好证美赞臣(Meadjohnson卡塔尔(قطر‎个标题,那就是还未勤奋好学研讨,经验太少。爬坑的进程寒心,也告慰。笔者那是写给像笔者相近未有出坑的同伴。个人文字协会手艺糟糕请见谅,还恐怕有便是有荒谬的地点希望能够指正。

率先是下包,用的是ZXing

先看一下运行效果:

然后是构造文件,那些十分轻巧

美高梅网投网址 16

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:andro xmlns:tools="http://schemas.android.com/tools" android: android:layout_width="match_parent" android:layout_height="match_parent" android:background="#1c1c1c" android:orientation="vertical"> <include layout="@layout/head" android:/> <SurfaceView //这个就是主要的啦 android: android:background="@drawable/saomiao" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@ id/head"/> <RelativeLayout //这个本来不必要的,为了那天线没办法 android: android:layout_width="match_parent" android:layout_height="180dp" android:layout_marginTop="170dp" android:layout_marginRight="70dp" android:layout_marginLeft="70dp"> <com.***.**.view.*****//这个就是那条线 android: android:layout_width="match_parent" android:layout_height="2dp" android:layout_marginTop="33dp" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"/> </RelativeLayout> <TextView android:layout_width="match_parent" android:layout_height="180dp" android:textColor="@color/white" android:layout_gravity="bottom" android:gravity="center|top" android:padding="20dp" android:text="将医生二维码放入框内,即可自动扫描" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"/></RelativeLayout>

不了然干什么发不了动图,想看动图的能够去自个儿的Github上见到,Github地址会在文末给出。当然,纵然你是个热血青少年,想亲自心得下这些控件的试用效果,那您能够扫描下方二维码,直接把德姆o下载到手提式有线电话机上运维就好了。走过路过不要错失。猛烈推荐大家下载德姆o,里面还蕴藏了超级多自身之前写的案例,况兼笔者会一向更新下去。放心下载呢,里面未有鸡汤文,长老保险,都是技能干货~~~

此处比很多坑,SurfaceView 要是再嵌套一层layout的话,里面包车型大巴画面会变形,还会有无法全屏(具体如何来头,临时没空去找,大神能够辅导一下)。至于特别背景框,叫UI截个图妥妥的绝不本身话前边的线。还会有特别ScanLineView 是别人给本人的,它的动长久度略坑,所以勉重申成这么正巧。其实最棒的办法正是改里面包车型大巴代码,可是时间缺乏大概算了,将就着用呢。

美高梅网投网址 17

接下去是activity的代码了,没有任何贴,二维码那块都在那了,其实少之又少东西的

实际的落到实处思路是如此的:我们必要三个背景和四个前途,背景正是蒙蔽在刮刮卡背后的事物,可能是图片,也说不许是百万大奖,前程就是浅豆沙色的掩盖层了。然后还必要一支画笔,画笔在前程上边会形成轨道,大家让轨道透明就好了,那样就会见到上面的事物了。

 @Override public void onCreate(Bundle icicle) { super.onCreate;// setContentView(R.layout.activity_scan); title.setText("扫描医生二维码"); qrScanManager = new QRScanManager; //主要是这玩意而已 layout_contain = (RelativeLayout) findViewById(R.id.layout_contain); qrScanManager.initWithSurfaceView(this, R.id.surfaceview); qrScanManager.setBeepResource(R.raw.beep); Rect rect = initCrop(); qrScanManager.setCropRect; ScanLineView scanline = (ScanLineView) findViewById(R.id.scanline); // 动画效果 TranslateAnimation animation = new TranslateAnimation( Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 1.0f); animation.setDuration; animation.setRepeatCount; animation.setRepeatMode(Animation.RESTART); scanline.startAnimation(animation); } private Rect initCrop() { int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layout_contain.getLayoutParams(); int x = params.leftMargin; int y = params.topMargin; int width = screenWidth - 2 * x; int height = width; params.height = height; layout_contain.setLayoutParams; return new Rect(x, y, width   x, height   y); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); qrScanManager.onResume(); } @Override protected void onPause() { qrScanManager.onPause(); super.onPause(); } @Override protected void onDestroy() { qrScanManager.onDestroy(); super.onDestroy(); } @Override public void onScanResult(String content) { Toast.makeText(this, "结果:"   code[1], Toast.LENGTH_SHORT).show(); }

废话十分的少说,最早写代码。首先,我们自定义三个GuaGuaKa类,世襲自View,并促成其布局方法,看代码:

关于那几个ScanLineView 其实假设不要求的话去掉它,代码就大约多了,要的人笔者放上代码吧

public class GuaGuaKa extends View {

    private Paint pathPaint;

    private Path path;

    private Bitmap cacheBitmap;
    private Canvas cacheCanvas;

    private Bitmap backBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.demo);

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

    public GuaGuaKa(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setBackgroundColor(Color.WHITE);

        pathPaint = new Paint();
        pathPaint.setAntiAlias(true);
        pathPaint.setDither(true);
        pathPaint.setColor(Color.BLACK);
        pathPaint.setStyle(Paint.Style.STROKE);
        pathPaint.setStrokeWidth(50);
        pathPaint.setStrokeCap(Paint.Cap.ROUND);
        pathPaint.setStrokeJoin(Paint.Join.ROUND);

        path = new Path();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        cacheBitmap = Bitmap.createBitmap(getWidth() - getPaddingLeft() - getPaddingRight(), getHeight() - getPaddingTop() - getPaddingBottom(), Bitmap.Config.ARGB_8888);
        cacheCanvas = new Canvas(cacheBitmap);
    }
}
public class ScanLineView extends View { Paint paint = new Paint(); private float density;// 屏幕密度 private float width, height;// 控件的宽度高度 public ScanLineView(Context context) { super; init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ScanLineView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } public ScanLineView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public ScanLineView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { density = getResources().getDisplayMetrics().density; // 去锯齿 paint.setAntiAlias; paint.setColor(Color.parseColor("#53d555")); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { width =  (250 * density); } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { height =  (250 * density); } // Log.e("tag", " ------ width:" width  " height:" height); setMeasuredDimension this.width,  this.height); Shader mShader = new LinearGradient( width/2.0f,height,width/2.0f, 0, new int[] { Color.BLUE, Color.TRANSPARENT}, null, Shader.TileMode.CLAMP); paint.setShader; } @Override protected void onDraw(Canvas canvas) { super.onDraw; // 为Paint设置渐变器 // 绘制矩形 canvas.drawRect(0, 0, width, height, paint); }}

在布局方法里面,小编对paint的品质进行了初叶化。假如对Paint的用法还不是很纯熟的同校,可以参见的其它一篇文章《Paint特效大全,看这一篇就够了!》。
在onLayout方法里面,小编对bitmap和canvas实行了起先化。笔者想问一下学子们,为何自身不直接在布局方法里最初化?想知道的同班能够接二连三往下看。
按常理来讲,bitmap和canvas的起头化是截然能够投身构造方法里的,作者也真心诚意希望得以那样做,不然这里一块代码,这里一块代码,现在代码多了,找起来还不便于。
卓绝很足够,现实很骨感!不掌握大家只顾到未有,cacheBitmap在开始化的时候必要传入getWidth( 卡塔尔国,那几个法子的重回值正是全部GuaGuaKa控件的宽窄,而那个值必需在onMeasure方法试行完事后才具有结果的,在onMeasure未有实践从前都以再次来到0。为啥笔者会知道这些结论呢?因为本身学过View的绘图机制啊。假诺你听不懂,就应当去上学一下View的绘图机制了。
第二步,大家要求处理手指的滑行事件,重写onTouchEvent方法就好了。前提是,你必需求学过Android Touch事件分发机制,没学过的校友,上边包车型大巴代码基本上是看不懂的。是否感觉很操蛋,一个简简单单的自定义View,居然要学习那么多android运营机制。
来,看一下代码

啊,就是其一自定义View了,其实代码比少之又少,东西也没多少

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            pointerX = event.getX();
            pointerY = event.getY();
            path.moveTo(pointerX, pointerY);
            break;
        case MotionEvent.ACTION_MOVE:
            path.lineTo(event.getX(), event.getY());
            pointerX = event.getX();
            pointerY = event.getY();
            break;
    }
    invalidate();
    return true;
}

举目四望的正是如此轻易就化解了···

当手指第三次按下的时候,记录下x坐标和y坐标,并让path移动到这几个坐标。然后在手指运动进度中一再地改成path的不二等秘书技,然后不断地去重绘,那样技艺达到实时展现的效果。有个别博客绘制path用的是path.quadTo(卡塔尔(قطر‎,笔者这里用的是lineTo,其实是有出入的。但大家这边不商量,行吧。即使本人这里不探究,不过不知晓的校友们依旧有必不可缺去上学一下quadTo和lineTo的分别的。

然后是生成二维码,这么些更简便易行,三个工具类消除

既然调用invalidate了,那系统肯定会去实行onDraw方法,我很愕然,onDraw方法会去实施怎么着代码?
一向看代码:

 /** * 生成一个二维码图像 * * @param url * 传入的字符串,通常是一个URL * @param QR_WIDTH * 宽度 * @param QR_HEIGHT * 高度 * @return */ public static final Bitmap create2DCoderBitmap(String url, int QR_WIDTH, int QR_HEIGHT) { try { // 判断URL合法性 if (url == null || "".equals || url.length { return null; } Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); // 图像数据转换,使用了矩阵转换 BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints); int[] pixels = new int[QR_WIDTH * QR_HEIGHT]; // 下面这里按照二维码的算法,逐个生成二维码的图片, // 两个for循环是图片横列扫描的结果 for (int y = 0; y < QR_HEIGHT; y  ) { for (int x = 0; x < QR_WIDTH; x  ) { if (bitMatrix.get { pixels[y * QR_WIDTH   x] = 0xff000000; } else { pixels[y * QR_WIDTH   x] = 0xffffffff; } } } // 生成二维码图片的格式,使用ARGB_8888 Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888); bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT); // 显示到一个ImageView上面 // sweepIV.setImageBitmap; return bitmap; } catch (WriterException e) { Log.i("log", "生成二维码错误"   e.getMessage; return null; } }
@Override
protected void onDraw(Canvas canvas) {
    //画背景
    canvas.drawBitmap(backBitmap, 0, 0, null);
    //利用PorterDuff.Mode画线条,重叠模式为DST_OUT
    //灰色背景和path的重叠
    cacheCanvas.drawColor(Color.GRAY);
    pathPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    cacheCanvas.drawPath(path, pathPaint);
    //画前景
    canvas.drawBitmap(cacheBitmap, 0, 0, null);
}

生成二维码,三个bitmap消除Bitmap bitmap = QRCodeUtil.create2DCoderBitmap(qrCodeBean.getQRCodeUrl(), 250, 250);

讲明写得很掌握,先画背景,再画前途。背景正是一张图片,前途就是彩虹色隐瞒层和path轨迹的结合体,结合准绳是DST_OUT,给大家看一张图,你们就知晓DST_OUT的效果是何等了。

有了bitmap,然后爱放哪放哪,妥妥的就这么轻松消除了。

美高梅网投网址 18

说说题外话:前段时间少写了不菲篇文章了,说是项目多了,忙然而来,其实还应该有原因便是投机懒,天气冷了,人也越变越懒了,本来那篇作品早几天就想写的了,拖啊拖啊的就到了后天。

说实话,小编刚初步以为应该用Xor格局,怎么都想不通为啥要用DstOut形式。到即日还未有想领悟,擦。。。。。。

话说,这两天逛着逛着简书,开采爱上了看 堂主姓蔡 此人写的好玩的事,大多是鬼故事,都还不易的指南。

一个刮刮卡就完事了,看起来很简单,代码量超级少,其实供给写出来这么的效应的确要求一定的根基,你供给学会android事件分发机制,View的绘图机制,还大概有paint的特效使用,Path的行使,Canvas的选用,还要学会Bitmap相关的文化,太他妈难了!!!小编也是一步步学过来的,过程很劳苦,可是当您把东西做出来今后,你会很有成就感。

再有,明早备选剁手

终极吧,你们依然须要去和睦推行一下的,把代码写出来,然后简短深入分析一下缘故。实在懒的人方可去本身的Github上拷贝一下代码,那篇博客的代码不是很完整,入眼解说思路,完整的代码在那间:https://github.com/Elder-Wu/Notes
若果以为自个儿写得好,能够点个赞,然后关切一下的哦~其余,作者的Wechat公众号也开始播放了,每一日都会享受一篇非凡的技术小说,应接我们来踩点。(公众号:代码也是人)

美高梅网投网址 19

技术沟通群:471395156(迎接我们入坑)

TAG标签:
版权声明:本文由美高梅网投平台发布于美高梅网投网址,转载请注明出处:Android实现刮刮卡效果,zxing第三方库的使用【美