Android进阶之路 - 截取View为图片

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20451879/article/details/85236771

此篇文章都来源于项目需求 - -

起由:因需分享图片到微信、QQ等三方平台 ; 同时不可展现View在当前分享一级视图内;
解决方式:使用相对布局进行布局覆盖,需要分享的View设置为Invisible状态,点击分享时截取View转为图片,然后进行分享

Effect :
在这里插入图片描述

注意 :

  • 虽然已经工作了很久,我依旧喜欢复杂的事情简单化~ 能直接Copy的决不自己写~能写一行的代码绝不写俩行(内心独白:毕竟我还要去学更多的东西嘛 ~ ~)
  • 所截View,按理不应展示在一级视图内!但是为了效果,故进行了显示;
  • 在我的真实项目场景中,所截View我们需要设置 android:visibility=“invisible” ,这样既在一级表现页进行了展示,又不会报出空指针
  • 因为只是截取View变成图片进行分享,并没有保存在本地,所以不需要申请权限!
  • 最后有一些扩展方法,包含图片压缩、保存图片、友盟分享使用

特别注意:

因为我截取View转为Bitmap主要作用于三方分享!

但是QQ分享时多次点击,多次无效 ;

经过Debug查看后~

首先发现原因是bitmap返回为null

然后我用了文章末尾的扩展方法(大多都是返回为null,使用缓存处理)
但是根本无效!!!

然后耗费了一下午时间,我发现QQ分享竟然要申请存储权限!竟然要申请存储权限!竟然要申请存储权限!

好吧, 哥们或许你截取View转bitmap并不是为空!因为View传入之后Debug发现是可以获取图片的,只是到了return的时候发现bitmap为空!!!

代码部分

截取View转为图片的方法

  private static Bitmap convertViewToBitmap(View tempView) {
      /**
       * 创建一个bitmap放于画布之上进行绘制 (简直如有神助)
       */
        Bitmap bitmap = Bitmap.createBitmap(tempView.getWidth(),
                tempView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tempView.draw(canvas);
        return bitmap;
    }

Demo代码(Demo下载

  • MainActivity
package com.example.viewtobitmap;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;

/**
 * @author Mr.Liu
 * */
public class MainActivity extends Activity {
    private LinearLayout tempview;
    private ImageView mView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //我们要截取的View
        tempview = (LinearLayout) findViewById(R.id.gone_view);
        //用于展示我们已截取View的承载视图
        mView = (ImageView) findViewById(R.id.img);

        //点击事件
        findViewById(R.id.changeviewtobitmap).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //屏幕参数
                //Display disPlay = getWindowManager().getDefaultDisplay();
                mView.setImageBitmap(convertViewToBitmap(tempview, null));
            }
        });
    }

    /**
     * 主要方法:创建一个bitmap放于画布之上进行绘制 (简直如有神助)
     */
    private static Bitmap convertViewToBitmap(View tempView, Display disPlay) {
        Bitmap bitmap = Bitmap.createBitmap(tempView.getWidth(),
                tempView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tempView.draw(canvas);
        return bitmap;
    }
}

  • MainActivity Xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="#ffffff"
              android:orientation="vertical">

    <LinearLayout
        android:id="@+id/gone_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff0"
        android:orientation="vertical"
        android:paddingBottom="10dp"
        android:visibility="visible">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="你是我患得患失的梦,我是你可有可无的人~~"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="毕竟这穿越山河的箭,刺的都是用情致疾的人~~"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="毕竟这穿越山河的箭,刺的都是用情致疾的人~~"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="就让这牵肠挂肚的酒,硫酸一样刺激在你我的心头~~"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="4dp">

        <Button
            android:id="@+id/changeviewtobitmap"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="截View视图"/>
    </LinearLayout>

    <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
</LinearLayout>

项目代码(主要是QQ分享,所以只贴出关键部分!这是文中我用到的权限申请

	RxPermissions rxPermissions = new RxPermissions(this);
                //Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA 文件存储权限、相机权限
                rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, 		Manifest.permission.CAMERA).subscribe(new Observer<Boolean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Boolean aBoolean) {
                        //有权限的状态
                        if (aBoolean) {
                            Display displayQQ = getWindowManager().getDefaultDisplay();
                            UMImage umImageQQ = new UMImage(InviteAwardActivity.this, convertViewToBitmap(mSharePicture, displayQQ));
                           /* 便于找到自身错误
                            if (thumbImage == null) {
                                ToastUtils.shortShow("分享图片为空");
                            }*/
                            umImageQQ.setThumb(umImageQQ);
                            boolean qqClientAvailable = PlatformUtil.isQQClientAvailable(InviteAwardActivity.this);
                            if (qqClientAvailable) {
                                new ShareAction(InviteAwardActivity.this)
                                        .setPlatform(SHARE_MEDIA.QQ)
                                        .withMedia(umImageQQ)
                                        .setCallback(new UMShareListener() {
                                            @Override
                                            public void onStart(SHARE_MEDIA shareMedia) {

                                            }

                                            @Override
                                            public void onResult(SHARE_MEDIA shareMedia) {
                                                ToastUtils.shortShow("分享成功!");
                                            }

                                            @Override
                                            public void onError(SHARE_MEDIA shareMedia, Throwable throwable) {

                                            }

                                            @Override
                                            public void onCancel(SHARE_MEDIA shareMedia) {

                                            }
                                        }).share();
                            } else {
                                ToastUtils.shortShow("请安装QQ客户端");
                            }
                        }
                        //无权限的状态
                        else {
                            Toast.makeText(InviteAwardActivity.this, getString(R.string.picture_jurisdiction), Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
        

扩展方法

以下内容 : 我认为可以先行忽略,不过也可以看看,毕竟是看了十几篇类似博文的产物 ~

方式一 :

  • 图片压缩、View转换
 /**
     * 压缩图片
     *
     * @param bgimage
     * @param newWidth
     * @param newHeight
     * @return
     */
    public static Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {
        // 获取这个图片的宽和高
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        // 创建操作图片用的matrix对象
        Matrix matrix = new Matrix();
        // 计算宽高缩放率
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 缩放图片动作
        //matrix.postScale(scaleWidth, scaleHeight);//TODO 因为宽高不确定的因素,所以不缩放
        Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
                (int) height, matrix, true);
        return bitmap;
    }

	/**
     * 截取指定View为图片
     *
     * @param view
     * @return
     * @throws Throwable
     */
    public static Bitmap captureView(View view) throws Throwable {
        Bitmap bm = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        view.draw(new Canvas(bm));
        return bm;
    }

压缩使用

	
	 	Bitmap bitmap = null;
          try {
                 bitmap = captureView(mShareBackgroundSign);
              } catch (Throwable throwable) {
                    throwable.printStackTrace();
              }
           //图片压缩,加快使用速度~
           zoomImage(bitmap, 720, 1280);

  • 图片保存到本地 (若要保存,务必记得权限申请)
public static void savePhotoToSDCard(Bitmap photoBitmap, String path, String photoName) {
        if (checkSDCardAvailable()) {
            File dir = new File(path);
            if (!dir.exists()) {
                dir.mkdirs();
            }
 
            File photoFile = new File(path, photoName + ".png");
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(photoFile);
                if (photoBitmap != null) {
                    if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
                        fileOutputStream.flush();
                    }
                }
            } catch (FileNotFoundException e) {
                photoFile.delete();
                e.printStackTrace();
            } catch (IOException e) {
                photoFile.delete();
                e.printStackTrace();
            } finally {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

方式二 (有人说截取view转bitmap后为null~ 用这种方式清理缓存) :

    public static Bitmap getViewBp(View v) {
        if (null == v) {
            return null;
        }
        v.setDrawingCacheEnabled(true);
        v.buildDrawingCache();
        if (Build.VERSION.SDK_INT >= 11) {
            v.measure(View.MeasureSpec.makeMeasureSpec(v.getWidth(),
                    View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(
                    v.getHeight(), View.MeasureSpec.EXACTLY));
            v.layout((int) v.getX(), (int) v.getY(),
                    (int) v.getX() + v.getMeasuredWidth(),
                    (int) v.getY() + v.getMeasuredHeight());
        } else {
            v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
        }
        Bitmap b = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

        v.setDrawingCacheEnabled(false);
        v.destroyDrawingCache();
        return b;
    }

方式三 (有人说截取view转bitmap后为null~ 用这种方式清理缓存):

	public static Bitmap convertViewToBitmap(View view) {
        view.setDrawingCacheEnabled(true);
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        view.setDrawingCacheEnabled(false);
        return bitmap;
 }

猜你喜欢

转载自blog.csdn.net/qq_20451879/article/details/85236771