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之路 (一) 指定区域多图片合成 放大 缩小 镜像 旋转 等
posted @ 2017-07-18 11:29  一只呆萌的萌呆  阅读(751)  评论(0编辑  收藏  举报