zoukankan      html  css  js  c++  java
  • Android DIY之路 (一) 指定区域多图片合成 放大 缩小 镜像 旋转 等(转)

    惯例先看效果图

    合成图片

    // 注意做类似这种模板功能时候 方位由后台数据提供,这里我们用假数据 4个点 或者xy 加区域来做示例 
    //一开始我们公司用的是透明盖住 操作图片 但发现 局限性较大。后来直接限定区域。将操作图片层级移到模板图上面 随意叠加 
    1. 背景图上绘制操作区域,(操作区域可以不止一个,比如美图秀秀的模板) 
    2. 操作区域内加上 编辑素材图的容器与编辑区域相同 
    3. 添加可编辑的view(这里方便观看用的ImageView) 
    4. 合成将你想要的View范围截屏(也可以去掉你不想要的那部分)

    合成将你想要的View范围截屏文件

    知道这个 可以简化你自己做图生成图片的 省略 很多复杂方法 所以先放出来 后面DIY也是用的最多的方法。 
    flRoot.setClipChildren(false);//是否限制子View在其范围内*(注意这个属性必须放在拖动布局的爷爷布局才能生效) 
    还有这个方法。使其显示View的全局哪怕被遮挡。方便用户在编辑图片的时候更清晰 
    1. 
    View view = 你想要合成的当前显示的view 
     Bitmap bitmap = Bitmap.createBitmap(view .getWidth(), view .getHeight(),  Bitmap.Config.ARGB_8888); 
    Canvas canvas = new Canvas(bitmap); 
    canvas.drawColor(Color.WHITE); 
    view .draw(canvas); 
    如果本例中我是ivTemps 那么整个图片就局部截屏下来了。就类似局部截屏。当然这个bitmap可以继续操作。又或者你可以把4个按钮隐藏掉后 再局部截屏 
    2. 

    bitmap存文件 
    public static String saveBitmap(Context context, Bitmap bitmap) { 
    File file = null; 
    try { 
    file = new File(getCacheDir(), getFileName());/这是你的文件存的路径 自己定义吧 
    FileOutputStream os = new FileOutputStream(file); 
    bitmap = small(bitmap,0.5f); 
    mmmmmm = Bitmap.createBitmap(bitmap).copy(Bitmap.Config.ARGB_8888, true); 
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); 
    os.flush(); 
    os.close(); 
    } catch (FileNotFoundException e) { 
    e.printStackTrace(); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    }
    
        return file.getPath();
    }

    背景图上绘制操作区域

    <com.rex.refreshapp.ImagesTemplates
            android:id="@+id/ivTemps"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
    
            />

    自定义的FrameLayout 
    ImagesTemplates带的布局 View view = View.inflate(mContext, R.layout.view_images_templates, null); 
    addView(view); 
    简单形成一个组合控件。

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:id="@+id/flRoot"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:background="#FFF"
        >
    
        <ImageView
            android:id="@+id/ivBg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    
        <FrameLayout
            android:id="@+id/flZone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#50654786"
            android:clipChildren="false"
            >
    
        </FrameLayout>
    
    </FrameLayout>

    操作区域内加上 编辑素材图的容器与编辑区域相同

     initBg(30, 90, 800, 1200);//背景起点 长宽
      private void initBg(int x, int y, int width, int height) {
            ivBg.setX(x);
            ivBg.setY(y);
            ivBg.setScaleType(ImageView.ScaleType.CENTER_CROP);
            ivBg.setImageResource(R.mipmap.yudi);
            ViewGroup.LayoutParams layoutParams = ivBg.getLayoutParams();
            layoutParams.width = width;
            layoutParams.height = height;
            ivBg.setLayoutParams(layoutParams);
        }
    
    //可多个
    
    
    -----------------------
    
     initEditZone(30, 30, 600, 800);// 展现编辑区域 虚线 和半透明  可能多个拓展
         /**
         * 通过起点和区域范围  得到编辑区域
         *
         * @param x
         * @param y
         * @param width
         * @param height
         */
        private void initEditZone(final int x, final int y, final int width, final int height) {
    
            ViewTreeObserver vto = ivBg.getViewTreeObserver();
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                                              @Override
                                              public void onGlobalLayout() {
    
                                                  //监听一次马上结束
    
                                                  if (Build.VERSION.SDK_INT < 16) {
                                                      ivBg.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                                                  } else {
                                                      ivBg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                                                  }
    
                                                  Bitmap bitmap = Bitmap.createBitmap(ivBg.getWidth(), ivBg.getHeight(), Bitmap.Config.ARGB_8888);
                                                  Canvas canvas = new Canvas(bitmap);
                                                  canvas.drawColor(Color.WHITE);
                                                  ivBg.draw(canvas);
    
    
                                                  Paint p = new Paint();
                                                  p.setStyle(Paint.Style.STROKE);
                                                  //设置虚线效果
                                                  p.setPathEffect(new DashPathEffect(new float[]{10, 5}, 0));
                                                  p.setStrokeWidth(3);
                                                  p.setColor(Color.parseColor("#D0104C"));
    
    
                                                  Path path = new Path();
                                                  path.moveTo(x, y);
                                                  path.lineTo(x + width, y);
                                                  path.lineTo(x + width, y + height);
                                                  path.lineTo(x, y + height);
                                                  path.close();
                                                  canvas.drawPath(path, p);
    
                                                  ivBg.setImageBitmap(bitmap);
    
    
                                                  //显示编辑区域范围
                                                  flZone.setX(x + ivBg.getX());
                                                  flZone.setY(y + ivBg.getY());
                                                  FrameLayout.LayoutParams layoutParams = (LayoutParams) flZone.getLayoutParams();
                                                  layoutParams.width = width;
                                                  layoutParams.height = height;
    
                                                  flZone.setLayoutParams(layoutParams);
    
    
                                              }
    
    
                                          }
    
            );
    
    
        }
      1.

    添加可编辑的view(这里方便观看用的ImageView)

    当然你可以一个ImageView画4个bitmap搞定 但是后面我否定了这个方法 重写了这种比较直观的4个ImageView 作为按钮盖在主图View方法,中间的View可以替换。也方便理解,简化了后面的步骤。 
    R.layout.add_img_item

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/fl"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >
    
        <ImageView
            android:id="@+id/iv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="15dp"
            android:scaleType="centerCrop"/>
    
        <ImageView
            android:id="@+id/ivLeft"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_gravity="top|left"
            android:src="@mipmap/r_close"
            />
    
        <ImageView
            android:id="@+id/ivRight"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_gravity="top|right"
            android:src="@mipmap/r_rotate"
            />
    
        <ImageView
            android:id="@+id/ivBLeft"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_gravity="bottom|left"
            android:src="@mipmap/r_symmetric"
            />
    
        <ImageView
            android:id="@+id/ivBRight"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_gravity="bottom|right"
            android:src="@mipmap/r_zoom"
            />
    </FrameLayout>
     private void initEditImage() {
    
            final View flEditImage = View.inflate(mContext, R.layout.add_img_item, null);
            flZone.addView(flEditImage);
    
            final ImageView iv = (ImageView) flEditImage.findViewById(R.id.iv);
            final ImageView ivLeft = (ImageView) flEditImage.findViewById(R.id.ivLeft);
            final ImageView ivRight = (ImageView) flEditImage.findViewById(R.id.ivRight);
            final ImageView ivBLeft = (ImageView) flEditImage.findViewById(R.id.ivBLeft);
            final ImageView ivBRight = (ImageView) flEditImage.findViewById(R.id.ivBRight);
            iv.setImageResource(R.mipmap.shaosiming);
            flEditImage.setTag(iv);
    
    
            ViewTreeObserver vto = flEditImage.getViewTreeObserver();
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                                              @Override
                                              public void onGlobalLayout() {
    
                                                  //监听一次马上结束
    
                                                  if (Build.VERSION.SDK_INT < 16) {
                                                      flEditImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                                                  } else {
                                                      flEditImage.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                                                  }
                                                  int[] location = new int[2];
                                                  flEditImage.getLocationOnScreen(location);//获取在整个屏幕内的绝对坐标
                                                  centerX0 = location[0] + flEditImage.getWidth() / 2;
                                                  centerY0 = location[1] + flEditImage.getHeight() / 2;
                                              }
                                          }
    
            );
    
            //平移
            flEditImage.setOnTouchListener(new OnTouchListener() {
    
                private boolean isMove;
                private int downY;
                private int downX;
    
                private ImageView iv;
    
                @Override
                public boolean onTouch(View view, MotionEvent event) {
                    FrameLayout flview = (FrameLayout) view;
                    iv = (ImageView) view.getTag();
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        downX = (int) event.getRawX();
                        downY = (int) event.getRawY();
                        isMove = false;
                    }
                    if (event.getAction() == MotionEvent.ACTION_MOVE) {
                        isMove = true;
                        int moveX = (int) event.getRawX();
                        int moveY = (int) event.getRawY();
    //                Log.d(TAG,"moveX   "+moveX+"  moveY  "+moveY);
                        int dx = moveX - downX;
                        int dy = moveY - downY;
                        int i1 = dx + (int) ViewHelper.getTranslationX(flview);
                        int i2 = dy + (int) ViewHelper.getTranslationY(flview);
                        ViewHelper.setTranslationX(flview, i1);
                        ViewHelper.setTranslationY(flview, i2);
                        downX = moveX;
                        downY = moveY;
                        Log.i("rex", "ACTION_MOVE");
                        flRoot.setClipChildren(false);//是否限制子View在其范围内*(注意这个属性必须放在拖动布局的爷爷布局才能生效)
    
                    }
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        Log.i("rex", "ACTION_UP");
                        centerX = centerX0 + flEditImage.getTranslationX();
                        centerY = centerY0 + flEditImage.getTranslationY();
                        flRoot.setClipChildren(true);
                        flRoot.invalidate();
    
                        if (CheckIsOut(iv, flview)) {
                            ViewGroup parent = (ViewGroup) flview.getParent();
                            parent.removeView(flview);
    
    //                    flZone.removeView(flview);
                            Toast.makeText(mContext, "超出范围已移除", Toast.LENGTH_SHORT).show();
                        }
    
                        if (!isMove) {
    //                    Log.i("rex", "i 点击事件 ");
                        }
    //                    centerX = (flEditImage.getLeft() + flEditImage.getWidth()) / 2;
    //                    centerY = (flEditImage.getTop() + flEditImage.getHeight()) / 2;
    
                    }
    
                    return true;
                }
            });
    
            //删除
            ivLeft.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    flZone.removeView(flEditImage);
                }
            });
    
            //镜像
            ivBLeft.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    Bitmap bitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Bitmap.Config.ARGB_8888);
                    Canvas canvas = new Canvas(bitmap);
                    canvas.drawColor(Color.WHITE);
                    iv.draw(canvas);
                    iv.setImageBitmap(flip(bitmap, false));
    
                }
            });
            //旋转
            ivRight.setOnTouchListener(new OnTouchListener() {
    
                private float mDownY;
                private float mDownX;
    
    
    //
    //            float centerX = flEditImage.getWidth() / 2;
    //            float centerY = flEditImage.getHeight() / 2;
    
                @Override
                public boolean onTouch(View view, MotionEvent event) {
    
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
    
    
                            mDownX = event.getRawX();
                            mDownY = event.getRawY();
                            break;
                        case MotionEvent.ACTION_MOVE:
                            float moveX = event.getRawX();
                            float moveY = event.getRawY();
                            float rotate = flEditImage.getRotation();
                            float angle = getDegress(moveX, moveY) - getDegress(mDownX, mDownY);
    //                        float angle = getDegress(mDownX, mDownY) - getDegress(moveX, moveY);
    
    
                            Log.d("name", "degress -> " + (angle + rotate));
                            flEditImage.setRotation((rotate + angle) % 360);
    
                            mDownX = moveX;
                            mDownY = moveY;
                            break;
                        case MotionEvent.ACTION_UP:
    
                            break;
                    }
                    return true;
    
                }
    
                private float getDegress(float newX, float newY) {
                    float x = newX - centerX;
                    float y = newY - centerY;
                    return (float) Math.toDegrees(Math.atan2(y, x));
                }
            });
    
            //缩放
            ivBRight.setOnTouchListener(new OnTouchListener() {
    
    
                @Override
                public boolean onTouch(View view, MotionEvent event) {
    
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
    //                        mDownX = event.getRawX();
    //                        mDownY = event.getRawY();
                            break;
                        case MotionEvent.ACTION_MOVE:
                            float moveX = event.getRawX();
                            float moveY = event.getRawY();
    
                            float bili = getBili(moveX, moveY);
                            Log.d("rex", "bili -> " + bili);
                            flEditImage.setScaleX(bili);
                            flEditImage.setScaleY(bili);
                            correct4ButtonSize(1 / bili);
    
                            Log.d("rex", " ivBRight.getScaleX(); " + ivBRight.getScaleX());
    //                        mDownX = moveX;
    //                        mDownY = moveY;
                            break;
                        case MotionEvent.ACTION_UP:
    
                            break;
                    }
                    return true;
    
                }
    
                /**
                 *
                 * @param bili
                 */
                private void correct4ButtonSize(float bili) {
    
                    ivLeft.setScaleX(bili);
                    ivLeft.setScaleY(bili);
    
                    ivRight.setScaleX(bili);
                    ivRight.setScaleY(bili);
    
                    ivBLeft.setScaleX(bili);
                    ivBLeft.setScaleY(bili);
    
                    ivBRight.setScaleX(bili);
                    ivBRight.setScaleY(bili);
                    ;
                }
    
                private float getBili(float moveX, float moveY) {
    
                    int[] location = new int[2];
    //                flEditImage.getLocationInWindow(location); //获取在当前窗口内的绝对坐标
                    flEditImage.getLocationOnScreen(location);//获取在整个屏幕内的绝对坐标
                    float radius = ivBLeft.getWidth();//不精确
    
                    float oldLine = (float) Math.sqrt(flEditImage.getWidth() * flEditImage.getWidth() + flEditImage.getHeight() * flEditImage.getHeight());
                    float newLine = (float) Math.sqrt((moveX - location[0] + radius) * (moveX - location[0] + radius) + (moveY - location[1] + radius) * (moveY - location[1] + radius));
    
                    float scale = newLine / oldLine;//此处有微量误差
                    return scale;
                }
            });
    
    
        }
    /**
         * 判断是否超出
         * @param iv
         * @param fl
         * @return
         */
        private boolean CheckIsOut(ImageView iv, FrameLayout fl) {
            int maxX = flZone.getWidth();
            int maxY = flZone.getHeight();
    
            int a = fl.getWidth();
            int a2 = (int) fl.getX();
            int a3 = iv.getLeft();
            int a4 = iv.getRight();
            int x1 = (int) (fl.getX() + iv.getLeft());
            int x2 = (int) (fl.getX() + fl.getWidth() - iv.getLeft());
            int y1 = (int) (fl.getY() + iv.getTop());
            int y2 = (int) (fl.getY() + fl.getHeight() - iv.getTop());
    
    
            if (x1 > maxX || x2 < 0 || y1 > maxY || y2 < 0) {
                return true;
            }
            return false;
        }
    
    
        public static Bitmap flip(Bitmap bitmap, boolean isVer) {
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();
            Matrix matrix = new Matrix();
            if (isVer)
                matrix.postScale(1, -1);//镜像垂直翻转
            else
                matrix.postScale(-1, 1); //镜像水平翻转
            Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
            bitmap.recycle();
            return newBitmap;
        }

    转自:Android DIY之路 (一) 指定区域多图片合成 放大 缩小 镜像 旋转 等
  • 相关阅读:
    CentOS系统下NFS服务器
    网络封包分析
    Android端抓包方法
    SQL Server 2008从基础开始学习的历程(1)------创建表与查询
    序--CentOS6.5 mini 安装和基本配置
    MonkeyRunner(猴哥快跑)常用类方法总结
    python 开源数据抓取框架scrapy
    pycharm最新版注册
    python flask下传数据到js
    centos打架django + mysql环境
  • 原文地址:https://www.cnblogs.com/woaixingxing/p/7199561.html
Copyright © 2011-2022 走看看