版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}