layout: post
title: 安卓开发(四)收藏的轮子——图片相关
description: 安卓开发(四)收藏的轮子——图片相关
tag: 安卓
界面布局
沉浸式标题栏
一个可以使得屏幕铺满顶部状态栏的方法:
/**
* 通过设置全屏,设置状态栏透明
*
* @param activity
*/
public static void fullScreen(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
//导航栏颜色也可以正常设置
// window.setNavigationBarColor(Color.TRANSPARENT);
} else {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
attributes.flags |= flagTranslucentStatus;
// attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
}
在manifest中指定app的主题style:
style中的下边两个属性分别表示标题栏背景色和状态栏背景色,两者设为一致既可实现沉浸式效果,铺满全屏。
走马灯轮播图
引入依赖:implementation 'com.youth.banner:banner:1.4.10'
xml:
<com.youth.banner.Banner
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_10"
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="150dp" >
activity中,先获取到banner组件对象,然后初始化:
主要是构建imgePath列表和标题列表,然后banner.setImages设置图片,banner.setTittles设置标题。
加载具体的实现是通过加载器Myloader,通过glide加载图片到imageview中。然后可以重写OnBannerClick,设置轮播图点击反馈事件。
private void initBanner() {
List<User> friends = application.getFriendList();
//放图片地址的集合
list_path = new ArrayList<>();
//放标题的集合
list_title = new ArrayList<>();
if (friends!=null) {
for (int i = 0; i < friends.size(); i++) {
list_path.add(friends.get(i).getAvatar());
list_title.add(friends.get(i).getFullName());
}
}
list_title.add("更多");
list_path.add("https://img-blog.csdnimg.cn/9a6ae33e401543589b3f953a87166746.png");
//设置内置样式,共有六种可以点入方法内逐一体验使用。
banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE);
//设置图片加载器,图片加载器在下方
banner.setImageLoader(new MyLoader());
//设置图片网址或地址的集合
banner.setImages(list_path);
//设置轮播的动画效果,内含多种特效,可点入方法内查找后内逐一体验
banner.setBannerAnimation(Transformer.Default);
//设置轮播图的标题集合
banner.setBannerTitles(list_title);
//设置轮播间隔时间
banner.setDelayTime(3000);
//设置是否为自动轮播,默认是“是”。
banner.isAutoPlay(true);
//设置指示器的位置,小点点,左中右。
banner.setIndicatorGravity(BannerConfig.CENTER)
//以上内容都可写成链式布局,这是轮播图的监听。比较重要。方法在下面。
.setOnBannerListener(this)
//必须最后调用的方法,启动轮播图。
.start();
}
//自定义的图片加载器
private class MyLoader extends ImageLoader {
@Override
public void displayImage(Context context, Object path, ImageView imageView) {
Glide.with(context).load((String) path).into(imageView);
}
}
@Override
public void OnBannerClick(int position) {
Log.i("tag", "你点了第"+position+"张轮播图");
}
图标、图片处理、头像相关
下载图标
一些依赖:
implementation 'com.github.bumptech.glide:glide:4.11.0' // 图片加载
implementation 'com.github.chrisbanes:PhotoView:2.3.0' // 大图图片显示,拖拉放大
implementation 'top.zibin:Luban:1.1.8' // 图片压缩类
implementation 'com.github.Othershe:CombineBitmap:1.0.5' //bitmap合成,仿微信群头像
implementation 'com.githang:clipimageview:0.1' // 头像剪裁
implementation 'cjt.library.wheel:camera:1.1.9' // 调用相机拍照和录制视频
ImageUtils
包含在Bitmap中绘制文字水印;从网络上下载图片Bitmap保存;取出视频的第一帧转为Bitmap构建视频缩略图;旋转Bitmap指定angle;Glide加载头像的封装;view转bitmap显示自定义图标。
package com.beidouapp.model.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.beidouapp.Config;
import com.beidouapp.R;
import com.beidouapp.ui.DemoApplication;
import com.beidouapp.ui.Setting.ActivityUser;
import com.beidouapp.ui.Setting.ClipAvatar;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Response;
import wseemann.media.FFmpegMediaMetadataRetriever;
public class ImageUtil {
/**
* 设置水印图片在左上角
*
* @param context 上下文
* @param src
* @param watermark
* @param paddingLeft
* @param paddingTop
* @return
*/
public static Bitmap createWaterMaskLeftTop(Context context, Bitmap src, Bitmap watermark, int paddingLeft, int paddingTop) {
return createWaterMaskBitmap(src, watermark,
dp2px(context, paddingLeft), dp2px(context, paddingTop));
}
private static Bitmap createWaterMaskBitmap(Bitmap src, Bitmap watermark, int paddingLeft, int paddingTop) {
if (src == null) {
return null;
}
int width = src.getWidth();
int height = src.getHeight();
//创建一个bitmap
Bitmap newb = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
//将该图片作为画布
Canvas canvas = new Canvas(newb);
//在画布 0,0坐标上开始绘制原始图片
canvas.drawBitmap(src, 0, 0, null);
//在画布上绘制水印图片
canvas.drawBitmap(watermark, paddingLeft, paddingTop, null);
// 保存
canvas.save();
// 存储
canvas.restore();
return newb;
}
/**
* 设置水印图片在右下角
*
* @param context 上下文
* @param src
* @param watermark
* @param paddingRight
* @param paddingBottom
* @return
*/
public static Bitmap createWaterMaskRightBottom(Context context, Bitmap src, Bitmap watermark, int paddingRight, int paddingBottom) {
return createWaterMaskBitmap(src, watermark,
src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight),
src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom));
}
/**
* 设置水印图片到右上角
*
* @param context
* @param src
* @param watermark
* @param paddingRight
* @param paddingTop
* @return
*/
public static Bitmap createWaterMaskRightTop(Context context, Bitmap src, Bitmap watermark, int paddingRight, int paddingTop) {
return createWaterMaskBitmap(src, watermark,
src.getWidth() - watermark.getWidth() - dp2px(context, paddingRight),
dp2px(context, paddingTop));
}
/**
* 设置水印图片到左下角
*
* @param context
* @param src
* @param watermark
* @param paddingLeft
* @param paddingBottom
* @return
*/
public static Bitmap createWaterMaskLeftBottom(Context context, Bitmap src, Bitmap watermark, int paddingLeft, int paddingBottom) {
return createWaterMaskBitmap(src, watermark, dp2px(context, paddingLeft),
src.getHeight() - watermark.getHeight() - dp2px(context, paddingBottom));
}
/**
* 设置水印图片到中间
*
* @param src
* @param watermark
* @return
*/
public static Bitmap createWaterMaskCenter(Bitmap src, Bitmap watermark) {
return createWaterMaskBitmap(src, watermark,
(src.getWidth() - watermark.getWidth()) / 2,
(src.getHeight() - watermark.getHeight()) / 2);
}
/**
* 给图片添加文字到左上角
*
* @param context
* @param bitmap
* @param text
* @return
*/
public static Bitmap drawTextToLeftTop(Context context, Bitmap bitmap, String text, int size, int color, int paddingLeft, int paddingTop) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(bitmap, text, paint, bounds,
dp2px(context, paddingLeft),
dp2px(context, paddingTop) + bounds.height());
}
/**
* 绘制文字到右下角
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @return
*/
public static Bitmap drawTextToRightBottom(Context context, Bitmap bitmap, String text, int size, int color, int paddingRight, int paddingBottom) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(bitmap, text, paint, bounds,
bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight),
bitmap.getHeight() - dp2px(context, paddingBottom));
}
/**
* 绘制文字到右上方
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @param paddingRight
* @param paddingTop
* @return
*/
public static Bitmap drawTextToRightTop(Context context, Bitmap bitmap, String text, int size, int color, int paddingRight, int paddingTop) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(bitmap, text, paint, bounds,
bitmap.getWidth() - bounds.width() - dp2px(context, paddingRight),
dp2px(context, paddingTop) + bounds.height());
}
/**
* 绘制文字到左下方
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @param paddingLeft
* @param paddingBottom
* @return
*/
public static Bitmap drawTextToLeftBottom(Context context, Bitmap bitmap, String text, int size, int color, int paddingLeft, int paddingBottom) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(bitmap, text, paint, bounds,
dp2px(context, paddingLeft),
bitmap.getHeight() - dp2px(context, paddingBottom));
}
/**
* 绘制文字到中间
*
* @param context
* @param bitmap
* @param text
* @param size
* @param color
* @return
*/
public static Bitmap drawTextToCenter(Context context, Bitmap bitmap, String text, int size, int color) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(bitmap, text, paint, bounds,
(bitmap.getWidth() - bounds.width()) / 2,
(bitmap.getHeight() + bounds.height()) / 2);
}
//图片上绘制文字
private static Bitmap drawTextToBitmap(Bitmap bitmap, String text, Paint paint, Rect bounds, int paddingLeft, int paddingTop) {
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
paint.setDither(true); // 获取跟清晰的图像采样
paint.setFilterBitmap(true);// 过滤一些
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
canvas.drawText(text, paddingLeft, paddingTop, paint);
return bitmap;
}
/**
* 缩放图片
*
* @param src
* @param w
* @param h
* @return
*/
public static Bitmap scaleWithWH(Bitmap src, double w, double h) {
if (w == 0 || h == 0 || src == null) {
return src;
} else {
// 记录src的宽高
int width = src.getWidth();
int height = src.getHeight();
// 创建一个matrix容器
Matrix matrix = new Matrix();
// 计算缩放比例
float scaleWidth = (float) (w / width);
float scaleHeight = (float) (h / height);
// 开始缩放
matrix.postScale(scaleWidth, scaleHeight);
// 创建缩放后的图片
return Bitmap.createBitmap(src, 0, 0, width, height, matrix, true);
}
}
/**
* dip转pix
*
* @param context
* @param dp
* @return
*/
public static int dp2px(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
public static Bitmap getDefaultBitmap(String nickname ,int size,Context context ){
Bitmap base = BitmapFactory.decodeResource(context.getResources(),R.drawable.avatar_default);
String text;
if (nickname!=null && nickname.length() > 0){
if (nickname.length() >1){
// 如果昵称有一个字以上,取最后两位
text = nickname.substring(nickname.length()-2);
}else {
// 一个字就是本身
text = nickname;
}
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setTextSize(dp2px(context, size));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
return drawTextToBitmap(base,text,paint,bounds,(base.getWidth() - bounds.width()) / 2,
(base.getHeight() + bounds.height()) / 2);
}else {
return base;
}
}
/**
* 保存位图到本地
* @param bitmap
* @param name 图片名
* @return 图片文件
*/
public static File SavaImage(Bitmap bitmap,String name){
String path = Config.PHOTO_SAVE_DIR;
File file=new File(path);
FileOutputStream fileOutputStream=null;
//文件夹不存在,则创建它
if(!file.exists()){
file.mkdir();
}
String localAvatar = path+"/"+ name +".png";
try {
fileOutputStream=new FileOutputStream(localAvatar);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100,fileOutputStream);
fileOutputStream.close();
Log.d("下载头像", "SavaImage: 保存图片,地址为" + localAvatar);
return new File(localAvatar);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 判断文件是否为图片文件(GIF,PNG,JPG),且可用
* @param srcFilePath
* @return
*/
public static boolean isImage(File srcFilePath) {
FileInputStream imgFile = null;
byte[] b = new byte[10];
int l = -1;
try {
imgFile = new FileInputStream(srcFilePath);
l = imgFile.read(b);
imgFile.close();
} catch (Exception e) {
return false;
}
Bitmap bitmap = BitmapFactory.decodeFile(srcFilePath.getAbsolutePath());
try{
bitmap.getWidth();
}catch(Exception e) {
return false;
}
if (l == 10) {
byte b0 = b[0];
byte b1 = b[1];
byte b2 = b[2];
byte b3 = b[3];
byte b6 = b[6];
byte b7 = b[7];
byte b8 = b[8];
byte b9 = b[9];
if (b0 == (byte) 'G' && b1 == (byte) 'I' && b2 == (byte) 'F') {
return true;
} else if (b1 == (byte) 'P' && b2 == (byte) 'N' && b3 == (byte) 'G') {
return true;
} else if (b6 == (byte) 'J' && b7 == (byte) 'F' && b8 == (byte) 'I'&& b9 == (byte) 'F') {
return true;
} else {
return false;
}
} else {
return false;
}
}
/**
* 检查图片是否损坏
*
* @param filePath
* @return
*/
public static boolean checkImgDamage(String filePath) {
BitmapFactory.Options options = null;
if (options == null) {
options = new BitmapFactory.Options();
}
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
if (options.mCancel || options.outWidth == -1
|| options.outHeight == -1) {
return true;
}
return false;
}
/**
* 复制文件
*
* @param source 输入文件
* @param target 输出文件
*/
public static void copy(File source, File target) {
Log.d("glide加载", "copy: 复制图片到指定路径");
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(source);
fileOutputStream = new FileOutputStream(target);
byte[] buffer = new byte[1024];
while (fileInputStream.read(buffer) > 0) {
fileOutputStream.write(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 异步生成默认头像上传至服务器
*/
public static void drawDefaultAvatar(DemoApplication application, Context context, String token, String username, String fullName){
if (fullName!=null){
Observable.just(fullName).map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(@NonNull String s) throws Exception {
try {
return getDefaultBitmap(fullName,200,context);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}).subscribeOn(Schedulers.io())
.map(new Function<Bitmap, File>() {
@Override
public File apply(@NonNull Bitmap bitmap) throws Exception {
try {
return SavaImage(bitmap,username);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}).subscribeOn(Schedulers.io())
.subscribe(new Observer<File>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull File file) {
String url = Config.getUrl("/system/user/profile/avatar");
OkHttpUtils.getInstance(context).uploadAvatar(url,file, token, new OkHttpUtils.MyCallback() {
@Override
public void success(Response response) throws IOException {
JSONObject object = JSON.parseObject(response.body().string());
int code = object.getInteger("code");
if(code == 200){
String imgUrl = object.getString("imgUrl");
Log.d("默认头像", "success: 默认头像上传成功");
application.setAvatar(Config.getUrl(imgUrl));
}
}
@Override
public void failed(IOException e) {
e.printStackTrace();
}
});
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
Log.d("默认头像", "onComplete: 生成默认头像成功");
}
});
}
}
/**?
* 异步补充下载本地缺失头像,execute传递两个参数,第一个为手机号username决定头像文件名,
* 第二个为头像的服务器地址,avatar
*/
public static class downloadAvatar extends AsyncTask<String,Integer,File>{
@Override
protected File doInBackground(String... strings) {
String username = strings[0];
String avatar = strings[1];
Observable.just(avatar).map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(@NonNull String s) throws Exception {
try {
URL url = new URL(avatar);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(5000);
int code = httpURLConnection.getResponseCode();
if (code == HttpURLConnection.HTTP_OK) {
InputStream inputStream = httpURLConnection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}).subscribeOn(Schedulers.io())
.map(new Function<Bitmap, File>() {
@Override
public File apply(@NonNull Bitmap bitmap) throws Exception {
String path = Config.PHOTO_SAVE_DIR;
File file = new File(path);
FileOutputStream fileOutputStream = null;
//文件夹不存在,则创建它
if (!file.exists()) {
file.mkdir();
}
String localAvatar = path + "/" + username + ".png";
File oldFile = new File(localAvatar);
if (oldFile.isFile() && oldFile.exists()) {
oldFile.delete();
}
try {
fileOutputStream = new FileOutputStream(localAvatar);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.close();
Log.d("下载头像", "SavaImage: 保存图片,地址为" + localAvatar);
return new File(localAvatar);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}).subscribeOn(Schedulers.io())
.subscribe(new Observer<File>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull File file) {
System.out.println("头像下载路径"+file.getAbsolutePath()+"----头像大小"+file.length());
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
return null;
}
}
public static InputStream getInputStream(FileInputStream fileInput) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024*4];
int n = -1;
InputStream inputStream = null;
try {
while ((n=fileInput.read(buffer)) != -1) {
baos.write(buffer, 0, n);
}
byte[] byteArray = baos.toByteArray();
inputStream = new ByteArrayInputStream(byteArray);
return inputStream;
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static byte[] getBitmapByte(String filepath){
Bitmap bitmap = BitmapFactory.decodeFile(filepath);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
public static void loadAvatar(Context context, String id, ImageView view) {
File localAvatar = new File(Config.getAvatarPath((id)));
if (localAvatar.exists() && isImage(localAvatar)) {
Log.d("聊天界面头像", "onResume: 如果本地有图片加载本地");
Glide.with(context)
.load(localAvatar)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.centerCrop()
.placeholder(R.mipmap.default_header)
.into(view);
} else {
Log.d("聊天界面头像", "onResume: 如果本地没有图片加载服务器");
Glide.with(context)
.load(view)
.centerCrop()
.thumbnail(0.1f)
.placeholder(R.mipmap.default_header)
.error(R.mipmap.default_header) // will be displayed if the image cannot be loaded
.into(view);
}
}
/**
* 加载头像
* @param context 上下文
* @param id 目标id
* @param url 目标网络头像地址
* @param view 目标ImageView
*/
public static void loadAvatar(Context context, String id, String url,ImageView view) {
File localAvatar = new File(Config.getAvatarPath((id)));
if (localAvatar.exists() && isImage(localAvatar)) {
Log.d("聊天界面头像", "onResume: 如果本地有图片加载本地");
Glide.with(context)
.load(localAvatar)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.centerCrop()
.into(view);
} else {
Log.d("聊天界面头像", "onResume: 如果本地没有图片加载服务器");
Glide.with(context)
.load(url)
.centerCrop()
.thumbnail(0.1f)
.error(R.mipmap.default_header) // will be displayed if the image cannot be loaded
.into(view);
if(url!=null){
downloadAvatar task = new downloadAvatar();
task.execute(id, url);
}
}
}
public static Bitmap getAvatar(Context context, String id, String url) throws ExecutionException, InterruptedException {
File localAvatar = new File(Config.getAvatarPath((id)));
Bitmap bitmap;
if (localAvatar.exists() && isImage(localAvatar)) {
Log.d("聊天界面头像", "onResume: 如果本地有图片加载本地");
bitmap = Glide.with(context)
.asBitmap()
.load(localAvatar)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.centerCrop()
.into(100,100)
.get();
} else {
Log.d("聊天界面头像", "onResume: 如果本地没有图片加载服务器");
bitmap = Glide.with(context)
.asBitmap()
.load(url)
.centerCrop()
.thumbnail(0.1f)
.error(R.mipmap.default_header) // will be displayed if the image cannot be loaded
.into(100,100)
.get();
if(url!=null){
downloadAvatar task = new downloadAvatar();
task.execute(id, url);
}
}
return bitmap;
}
public static Bitmap getVideoImg(Context context, Bitmap baseBitmap) {
Bitmap startBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.start_new);
Bitmap bitmap = null;
bitmap = Bitmap.createBitmap(baseBitmap);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
int w1 = baseBitmap.getWidth();
int h1 = baseBitmap.getHeight();
int w2 = startBitmap.getWidth();
int h2 = startBitmap.getHeight();
paint.setColor(Color.GRAY);
paint.setAlpha(125);
canvas.drawRect(0,0, w1, h1, paint);
paint = new Paint();
canvas.drawBitmap(startBitmap, Math.abs((w1 - w2)/2), Math.abs((h1 - h2)/2), paint);
canvas.save();
canvas.restore();
return bitmap;
}
public static Bitmap getVideoFrame(String path){
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
try {
// retriever.setDataSource("/storage/emulated/0/test.mp4"); //file's path
retriever.setDataSource(path); //file's path
Bitmap bitmap = retriever.getFrameAtTime(100000,FFmpegMediaMetadataRetriever.OPTION_CLOSEST_SYNC ); //这个时间就是第一秒的
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
finally{
retriever.release();
}
return null;
}
public static Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {
Matrix m = new Matrix();
m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
try {
Bitmap bm1 = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), m, true);
return bm1;
} catch (OutOfMemoryError ex) {
}
return null;
}
/**
* 通过设置全屏,设置状态栏透明
*
* @param activity
*/
public static void fullScreen(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
//导航栏颜色也可以正常设置
// window.setNavigationBarColor(Color.TRANSPARENT);
} else {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
attributes.flags |= flagTranslucentStatus;
// attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
}
/**
* 将View转换成Bitmap
* @param addViewContent
* @return
*/
public static Bitmap getViewBitmap(View addViewContent) {
addViewContent.setDrawingCacheEnabled(true);
addViewContent.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
addViewContent.layout(0, 0,
addViewContent.getMeasuredWidth(),
addViewContent.getMeasuredHeight());
addViewContent.buildDrawingCache();
Bitmap cacheBitmap = addViewContent.getDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
return bitmap;
}
}
图片压缩鲁班压缩
Luban.with(ClipAvatar.this)
.load(file) // 传人要压缩的图片列表
.ignoreBy(100) // 忽略不压缩图片的大小
.setTargetDir(Config.PHOTO_SAVE_DIR) // 设置压缩后文件存储位置
.setCompressListener(new OnCompressListener() { //设置回调
@Override
public void onStart() {
Log.d(TAG, "onStart: 压缩前图片大小:"+file.length());
}
@Override
public void onSuccess(File file) {
File compressAvatar = file;
Log.d(TAG, "onSuccess: 压缩成功后图片大小"+compressAvatar.length());
String url = Config.getUrl("/system/user/profile/avatar");
OkHttpUtils.getInstance(ClipAvatar.this).uploadAvatar(url,compressAvatar,
application.getToken(), new OkHttpUtils.MyCallback() {
@Override
public void success(Response response) throws IOException {
JSONObject object = JSON.parseObject(response.body().string());
int code = object.getInteger("code");
String msg = object.getString("msg");
ClipAvatar.this.runOnUiThread(() -> Toast.makeText(ClipAvatar.this,msg,Toast.LENGTH_LONG).show());
if(code == 200){
String imgUrl = object.getString("imgUrl");
//服务器返回地址类型: "imgUrl": "/profile/avatar/2022/03/08/3cd6f0f2-8a77-43e2-b105-401ef0e7f123.jpg",
//路径补全
String avatar = "http://" + Config.BeiDou_SERVER_HOST + ":" + Config.BeiDou_SERVER_PORT + imgUrl;
application.setAvatar(avatar);
File savaAvatar = new File(Config.getAvatarPath(application.getUserID()));
copy(compressAvatar,savaAvatar);
}
}
@Override
public void failed(IOException e) {
e.printStackTrace();
}
});
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: 压缩失败");
}
}).launch(); //启动压缩
头像裁剪
<com.githang.clipimage.ClipImageView
android:id="@+id/clip_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
app:civHeight="3"
app:civMaskColor="#CC000000"
app:civClipPadding="30dp"
app:civWidth="3" />
ClipImageLayout相当于一个图片裁剪的容器,在裁剪完毕后可以使用.clip()方法,即可获取到裁剪后的Bitmap图片。
mClipImageLayout = (ClipImageView) findViewById(R.id.clip_image_view);
Intent intent = getIntent();
String imagePath = intent.getStringExtra("imagePath");
bitmap = BitmapFactory.decodeFile(imagePath);
mClipImageLayout.setImageBitmap(bitmap);
ClippedBitmap = mClipImageLayout.clip();
拍照录制视频
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.cjt2325.cameralibrary.JCameraView
android:id="@+id/cameraView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:iconMargin="20dp"
app:iconSize="30dp"
app:iconSrc="@drawable/ic_camera_enhance_black_24dp" />
</RelativeLayout>
使用相机需要权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- 摄像头权限 -->
<uses-permission android:name="android.permission.CAMERA" />
package com.beidouapp.ui.Setting;
import static com.beidouapp.model.utils.ImageUtil.SavaImage;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.beidouapp.Config;
import com.beidouapp.R;
import com.cjt2325.cameralibrary.JCameraView;
import com.cjt2325.cameralibrary.listener.JCameraListener;
import java.io.File;
/**
* 拍照、拍摄,作为其他activity的onActivityResult目标
* 返回data有两个参数,一个是type:photo/video(区分拍照和摄影),一个是path,返回本地文件名
*/
public class TakePhoto extends AppCompatActivity {
private JCameraView mJCameraView;
private static final String TAG = "拍照";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_take_photo);
initView();
}
private void initView() {
mJCameraView = findViewById(R.id.cameraView);
//(0.0.7+)设置视频保存路径(如果不设置默认为Environment.getExternalStorageDirectory().getPath())
mJCameraView.setSaveVideoPath(Environment.getExternalStorageDirectory().getPath());
//(0.0.8+)设置手动/自动对焦,默认为自动对焦
//设置小视频保存路径
File file = new File(Config.VIDEO_SAVE_DIR);
if (!file.exists()) {
file.mkdirs();
}
Log.d(TAG, "initView: "+file.getAbsolutePath());
mJCameraView.setSaveVideoPath(Config.VIDEO_SAVE_DIR);
mJCameraView.setJCameraLisenter(new JCameraListener() {
@Override
public void captureSuccess(Bitmap bitmap) {
//获取到拍照成功后返回的Bitmap
File photoFile = SavaImage(bitmap, "takePhoto"+System.currentTimeMillis());
Intent data = new Intent();
data.putExtra("type", "photo");
data.putExtra("path", photoFile.getAbsolutePath());
Log.d(TAG, "captureSuccess: "+photoFile.getAbsolutePath());
setResult(RESULT_OK, data);
finish();
}
@Override
public void recordSuccess(String url, Bitmap firstFrame) {
//获取成功录像后的视频路径
Intent data = new Intent();
data.putExtra("type", "video");
data.putExtra("path", url);
setResult(RESULT_OK, data);
finish();
}
});
}
@Override
protected void onResume() {
super.onResume();
if (mJCameraView != null) {
mJCameraView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
if (mJCameraView != null) {
mJCameraView.onPause();
}
}
}