美文网首页AndroidUIAndroid开发程序员
Android中使用SVG矢量图打造多边形图形框架

Android中使用SVG矢量图打造多边形图形框架

作者: 飞渡浮舟 | 来源:发表于2016-11-22 15:27 被阅读607次

    Android中使用SVG矢量图打造多边形图形框架#

    最后要实现的最终效果如下图:


    1.准备工作

    (1) 因为项目中需要用到SVG矢量图,所以我们就需要一个将SVG图像转换为Bitmap的工具类:

    CSDN资源下载[jar包]:http://www.123.com

    Github源码下载:https://github.com/pents90/svg-android

    如果下载的jar包直接在项目中引用就行,如果是源码只需要将源码放在项目中的包下即可,看看我AndroidStudio项目中源码文件:

    (2) 准备SVG矢量图片,不清楚SVG图片的童鞋可以到W3CSchool上面去了解下; 如果找不到SVG矢量图的素材可以在 SVG在线编辑 上自己编辑一个SVG图片。###

    准备好的SVG图片可以放在 res/raw 中(没有就手动创建),也可以放在项目的asset中(没有手动创建)

    目录 对应获取SVG图片的方法
    raw SVGParser.getSVGFromInputStream()
    asset SVGParser.getSVGFromAsset()

    2.SVG加载到Android中

    现在开始正式撸代码 首先在项目中创建一个工具类:SvgBitmapUtils

    在类中创建静态方法getSvgBitmap

        /**
         * 主要是用来加载SVG矢量图片,最后转换成我们属性的Bitmap格式
         * @param context
         * @param width SVG图片的宽
         * @param height SVG图片的高
         * @param resId SVG图片的ID
         * @return Bitmap
         */
        public static Bitmap getSvgBitmap(Context context , int width,int height ,int resId){
            //1.创建一个空的图片
            Bitmap bitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
            //2.拿到空图片的画布:目前来讲相当于一张白纸
            Canvas canvas = new Canvas(bitmap);
            //创建一直画笔
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setDither(true);//防止画笔抖动
            paint.setColor(Color.BLACK);//画笔颜色为黑色'
    
            //当传入的id是一个正常的ID
            if (resId>0){
                // 3.通过SVGParser来加载一个SVG图片
                // 加载raw目录下的SVG文件
                SVG svg = SVGParser.getSVGFromInputStream(context.getResources().openRawResource(resId),width,height);
                // 4.将通过svg对象的getPicture()方法得到一个Picture对象,然后将Picture画在画布上
                canvas.drawPicture(svg.getPicture());
            }else {
                //如果没有找到SVG图片就画一个矩形
                canvas.drawRect(new Rect(0,0,width,height),paint);
            }
    
            return bitmap;
        }
    
    

    接下来是Svg图片与妹子的合并,所以首先准备一张妹子图,因为我们合并和得到一张正方形的合并图片,所以要先根据给定的妹子图得到合并后图片的宽(size),很明显就是妹子图片的宽或高中最小的一边的长度:

    int size = Math.min(fg.getWidth(),fg.getHeight());

    然后根据这个宽(size)从妹子的原图中切出一张正方形图片,从原图中切出一个正方形图片需要知道切图的起始位置(<font color="#ff3456">相对与图片的左上角的位置:x,y</font>)

        //2.确定截取正方形左上角的坐标
        int x = (fg.getWidth()-size)/2;
        int y = (fg.getHeight()-size)/2;
    

    有了开始的Svg矢量图和现在切出来的妹子图;就可以开始合并图片,可是要怎么样才能合并出上面的那样的效果;

    先来看看官方给出图片合并模式 来自ApiDemos/Graphics/XferModes):

    从上图可以看到PorterDuff.Mode为枚举类,一共有16个枚举值:

    枚举值 对应效果
    1.PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。
    2.PorterDuff.Mode.SRC 显示上层绘制图片。
    3.PorterDuff.Mode.DST 显示下层绘制图片。
    4.PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。。
    5.PorterDuff.Mode.DST_OVER 上下层都显示。下层居上显示。。
    6.PorterDuff.Mode.SRC_IN 取两层绘制交集。显示上层。。
    7.PorterDuff.Mode.DST_IN 取两层绘制交集。显示下层。。
    8.PorterDuff.Mode.SRC_OUT 取上层绘制非交集部分。。
    9.PorterDuff.Mode.DST_OUT 取下层绘制非交集部分。。
    10.PorterDuff.Mode.SRC_ATOP 取下层非交集部分与上层交集部分。
    11.PorterDuff.Mode.DST_ATOP 取上层非交集部分与下层交集部分。
    12.PorterDuff.Mode.XOR 所异或:去除两图层交集部分。
    13.PorterDuff.Mode.DARKEN 取两图层全部区域,交集部分颜色加深。
    14.PorterDuff.Mode.LIGHTEN 取两图层全部,点亮交集部分颜色。
    15.PorterDuff.Mode.MULTIPLY 取两图层交集部分叠加后颜色。
    16.PorterDuff.Mode.SCREEN 取两图层全部区域,交集部分变为透明色。

    根据我们的效果需要,很明显选择:

    [10.PorterDuff.Mode.SRC_ATOP ] 取下层非交集部分与上层交集部分。;

    现在我只需要把SVG图片放下面,然后把妹子放上面,就能得到最终效果!

    SVG跟妹子合并方法,也是我们最后在界面中使用的方法getSvgShapBitmap()

       /**
         * SVG跟妹子图片进行合并
         * @param context
         * @param fg 原图
         * @param resId 矢量图的(SVG)ID
         * @return Bitmap
         */
        public static Bitmap getSvgShapBitmap(Context context,Bitmap fg,int resId){
            //1.确定截取原图正方形的边长 (以原图中宽高最小的为边长)
            int size = Math.min(fg.getWidth(),fg.getHeight());
            //2.确定截取正方形左上角的坐标
            int x = (fg.getWidth()-size)/2;
            int y = (fg.getHeight()-size)/2;
            //裁剪妹子图片
            Bitmap girl = Bitmap.createBitmap(fg,x,y,size,size);
    
            //3.获得和正方形同样大小的SVG图片
            Bitmap svg = getSvgBitmap(context,fg.getWidth(),fg.getHeight(),resId);
            //创建画笔
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setDither(true);//防止抖动
    
            //4.SVG做底部图片,妹子放上面,采用SRC_ATOP模式重叠
            Bitmap bitmap = Bitmap.createBitmap(size,size, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            canvas.drawBitmap(svg,new Matrix(),paint);
            //设置图片重合模式
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
            canvas.drawBitmap(girl,new Matrix(),paint);
            return bitmap;
        }
    
    

    3.界面使用,直接显示到ImageView##

    MainActivity中的代码:

        public class MainActivity extends AppCompatActivity {
        private  Bitmap bitmap;
        private ImageView ivImage;
        private Button btnImage;
    
        ////加载多边形SVG
        private static int[] resIds = new int[]{
                R.raw.ba,
                R.raw.fengye,
                R.raw.linxin,
                R.raw.liu,
                R.raw.meihua,
                R.raw.pingguo,
                R.raw.qi,
                R.raw.qizi,
                R.raw.tuzi,
                R.raw.wujiaoxing,
                R.raw.yezi,
        };
        
        int flag = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ivImage = (ImageView) this.findViewById(R.id.iv_image);
            btnImage = (Button) this.findViewById(R.id.btn_image);
            
            bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.girl);//
            //为了效果先显示原图
            ivImage.setImageBitmap(bitmap);
            
            btnImage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    flag = flag % (resIds.length);
                    //得到合并后的图片
                    Bitmap svgShapBitmap = SvgBitmapUtils.getSvgShapBitmap(MainActivity.this, bitmap, resIds[flag]);
                    ivImage.setImageBitmap(svgShapBitmap);
                    flag++;
                }
            });
        }
    

    代码简单,就不多说了,下面还是贴上XML代码吧

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
        android:layout_width="match_parent" android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:background="@color/colorAccent"
        tools:context="zhengliang.com.svg_polygon_frame.MainActivity">
        <ImageView
            android:layout_width="250dp"
            android:layout_height="250dp"
            android:scaleType="centerCrop"
            android:layout_centerInParent="true"
            android:id="@+id/iv_image"/>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:id="@+id/btn_image"
            android:background="#22FFFFFF"
            android:text="加载妹子"/>
    </RelativeLayout>
    
    

    大工告成,最后小提示(SVG图片的path路径尽量使用封闭路径,不然会出现奇葩效果!!)

    印象丶亮仔###

    svg-android.jar下载

    源码下载

    博客地址:http://blog.csdn.net/qq_23179075/article/details/53285852

    相关文章

      网友评论

      • 2ffa37dac608:楼主,博客里面的动态图是怎么做的?
        飞渡浮舟: @Xcrafter LICEcap
        2ffa37dac608:gif录制软件叫什么?
        飞渡浮舟: @Xcrafter 我是点击一下切换一张SVG图,动图是gif录制软件
      • yuger:你的鼠标放在"妹"字上面,然后我看成了"婊"...
        yuger:@印象丶亮仔 主要是鼠标的那个位置,简直一个像素都不差
        飞渡浮舟: @yuger 厉害呢,我的哥

      本文标题:Android中使用SVG矢量图打造多边形图形框架

      本文链接:https://www.haomeiwen.com/subject/exoppttx.html