凝视都在代码里,这里就不再说了。特别注意cnClick中的//TODO凝视以及onActivityResult方法中的凝视
效果图
权限:
<!-- 在SD卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
使得屏幕不旋转:
<activity
android:name=".MainActivity_21_Photo_Compress_Img"
android:screenOrientation="portrait"/>
1、布局:
1.1主界面的布局:activity_main_21
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F6F6F6"
android:fitsSystemWindows="true"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/search_gold_expert_back_title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ec434b"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="点击icon"
android:textColor="#ffffff"
android:textSize="20sp"/>
</RelativeLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:id="@+id/iv_image"
android:layout_width="310dp"
android:layout_height="250dp"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/show_tv_21"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:background="#ec434b"
android:gravity="center"
android:onClick="onClick"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:text="显示结果"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:text="拍照得到照片的原路径"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:id="@+id/result_url_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:text="拍照得到照片的大小"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:id="@+id/photo_src_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:text="压缩后的图片的路径"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:id="@+id/result_url_tv_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:text="压缩后照片的大小"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
<TextView
android:id="@+id/photo_compress_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:lineSpacingMultiplier="1.4"
android:textColor="#4F4F4F"
android:textSize="16sp"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
1.2popupwindow的布局:photo_select_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/dialog_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000000"
/>
<TextView
android:id="@+id/pic_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f6f6f6"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:text="从相冊中选取"
android:textSize="20sp"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000000"
/>
<TextView
android:id="@+id/pic_from_take_photo_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f6f6f6"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:text="拍照"
android:textSize="20sp"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000000"
/>
<TextView
android:id="@+id/cancle_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f6f6f6"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:text="取消"
android:textSize="20sp"
/>
</LinearLayout>
2、工具类及其它准备的东西
2.1:Utils
/**
* 把浮点型数据转换成小数点后2位的数
* @param f
* @return
*/
public static String getNumAccuracy_2(float f) {
//构造方法的字符格式这里假设小数不足2位,会以0补足.
DecimalFormat decimalFormat = new DecimalFormat(".00");
//format 返回的是字符串
String result = decimalFormat.format(f);
return result;
}
2.2:全局变量:CHEN
/**
* 图片压缩的边界值。以2M为例。超过2M,就对图片进行压缩
*/
public static long img_compress_limit = 2 * 1048 * 1024;
/**
* 拍照后存储照片的路径
*/
public static String img_path = Environment.getExternalStorageDirectory() + "/chen/img";
/**
* 存放压缩后的图片的路径
*/
public static String img_compress_path = Environment.getExternalStorageDirectory() + "/chen/compress/";
public static int picWidth = 1000;
public static int picHeight = 1000;
2.3:PopSelectListener
/**
* 图片来源选择的popupwindow
*/
public interface PopSelectListener {
void popSelect(int flag);
}
2.4:popupwindow:PhotoFromSelectPop
package com.chen.customviewdemo.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.PopupWindow;
import com.chen.customviewdemo.R;
import com.chen.customviewdemo.listener.PopSelectListener;
/**
* 从底部出来的PopupWindow
*/
public class PhotoFromSelectPop {
Context context;
private PopupWindow popupWindow;
View popupWindowView;
public PhotoFromSelectPop(Context context) {
this.context = context;
}
/**
* 初始化
*/
public void initPopupWindow(final PopSelectListener listener) {
popupWindowView = LayoutInflater.from(context).inflate(R.layout.photo_select_layout, null);
popupWindow = new PopupWindow(popupWindowView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
popupWindow.setAnimationStyle(R.style.BottompSelectAnimationShow);
// 菜单背景色。加了一点透明度
ColorDrawable dw = new ColorDrawable(0xddffffff);
popupWindow.setBackgroundDrawable(dw);
popupWindow.showAtLocation(LayoutInflater.from(context).inflate(R.layout.activity_main, null),
Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
// 设置背景半透明
backgroundAlpha(0.7f);
popupWindow.setOnDismissListener(new popupDismissListener());
popupWindowView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
popupWindowView.findViewById(R.id.pic_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// listener.popSelect(0);
dimss();
}
});
popupWindowView.findViewById(R.id.pic_from_take_photo_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.popSelect(1);
dimss();
}
});
popupWindowView.findViewById(R.id.cancle_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dimss();
}
});
}
/**
* 设置加入屏幕的背景透明度
*
* @param bgAlpha
*/
public void backgroundAlpha(float bgAlpha) {
WindowManager.LayoutParams lp = ((Activity) context).getWindow().getAttributes();
lp.alpha = bgAlpha; // 0.0-1.0
((Activity) context).getWindow().setAttributes(lp);
}
class popupDismissListener implements PopupWindow.OnDismissListener {
@Override
public void onDismiss() {
backgroundAlpha(1f);
}
}
public void dimss() {
if (popupWindow != null) {
popupWindow.dismiss();
}
}
}
2.4.1:styles.xml
<style name="BottompSelectAnimationShow">
<item name="android:windowEnterAnimation">@anim/bottom_enter</item>
<item name="android:windowExitAnimation">@anim/bottom_exit</item>
</style>
2.4.2:bottom_enter
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="100%"
android:toYDelta="0"
android:duration="500"/>
</set>
2.4.3:bottom_exit
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromYDelta="0"
android:toYDelta="100%"/>
</set>
2.5:FileHelper
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class FileHelper {
/**
* 检查指定路径下的文件尺寸
*
* @param filePath
* @return
*/
public static String checkFileSize(String filePath) {
File file = new File(filePath);
if (file.length() > CHEN.img_compress_limit) {
System.out.print("照片大于2M进行压缩=" + file.length());
String compress_img = CHEN.img_compress_path + System.currentTimeMillis() + ".jpg";
compressPic(filePath, compress_img);
return compress_img;
} else {
return filePath;
}
}
/**
* 压缩图片
*
* @param fromPicUrl
*/
public static void compressPic(String fromPicUrl, String compress_img_path) {
int width = CHEN.picWidth;
int height = CHEN.picHeight;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true; // 翻译:仅仅是解码边界
// 当opts不为null时,但decodeFile返回空,
// 不为图片分配内存,仅仅获取图片的大小,并保存在opts的outWidth和outHeight
Bitmap bitmap = BitmapFactory.decodeFile(fromPicUrl, opts);
int srcWidth = opts.outWidth; // 获得原始图片的长
int srcHeight = opts.outHeight; // 获得原始图片的宽
Log.e("CHEN", "原始图片的宽高=" + srcWidth + "/" + srcHeight);
opts.inJustDecodeBounds = false; // 设置载入照片进入内存中
int be = 0; // 缩放倍数(假设为2,则长,宽各自缩短一倍,整张图片缩短至四分之中的一个)
int x = 0; // 长的倍数
int y = 0; // 宽的倍数
if (srcWidth > srcHeight) {
x = srcWidth / width;
y = srcHeight / height;
} else {
x = srcWidth / height;
y = srcHeight / width;
}
if (x > y) {
be = y;
} else {
be = x;
}
if (be <= 0) {
be = 1;
}
opts.inSampleSize = be; // 设置缩放倍数
bitmap = BitmapFactory.decodeFile(fromPicUrl, opts); // 读取缩放后的图片
srcWidth = bitmap.getWidth(); // 取得缩放后的长度
srcHeight = bitmap.getHeight(); // 取得缩放后的宽度
float scaleWidth = 0; // 定义截取的固定长度
float scaleHeight = 0; // 定义截取的固定宽度
if (srcWidth > srcHeight) {
scaleWidth = (float) width / srcWidth; // 按固定大小缩放 sWidth 写多大就多大
scaleHeight = (float) height / srcHeight;
} else {
scaleWidth = (float) height / srcWidth; // 按固定大小缩放 sWidth 写多大就多大
scaleHeight = (float) width / srcHeight;
}
if (scaleHeight != 1.0 && scaleWidth != 1.0) {// 排除手机拍出来的就是320*240的
Matrix matrix = new Matrix(); // 定义图片的矩阵对象
matrix.postScale(scaleWidth, scaleHeight); // 传入缩放的比例值
bitmap = Bitmap.createBitmap(bitmap, 0, 0, srcWidth, srcHeight, matrix, false);// 取得320*240的图片
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 60, baos);
byte[] pictureByte = baos.toByteArray();
// 释放bitmap的内存,非常重要
bitmap.recycle();
// 将bitmap保存为文件
OutputStream os = null;
try {
File file = new File(compress_img_path); // 定义保存照片的文件
if (!file.exists()) {
mkdirs(CHEN.img_compress_path, getname(compress_img_path));
}
os = new FileOutputStream(file); // 文件输出流
os.write(pictureByte, 0, pictureByte.length); // 写入文件
} catch (Exception e) {
e.toString();
} finally {
try {
if (os != null) {
os.close(); // 关闭文件输出流
}
} catch (IOException e) {
e.toString();
}
}
}
/**
* 切割字符串,得到不包括路径的文件名称
*/
public static String getname(String str) {
String name = "";
String[] ss = str.split("/");
name = ss[ss.length - 1];
return name;
}
/**
* 创建目录
*/
public static File mkdirs(String path, String name) {
File file = new File(path);
if (!file.exists()) {
try {
file.mkdirs();
} catch (Exception e) {
return null;
}
}
file = createNewFile(path + "/" + name);
return file;
}
/**
* 创建文件
*/
public static File createNewFile(String path) {
File file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
return null;
}
}
return file;
}
}
3、主代码:
import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.chen.customviewdemo.listener.PopSelectListener;
import com.chen.customviewdemo.utils.CHEN;
import com.chen.customviewdemo.utils.FileHelper;
import com.chen.customviewdemo.utils.Utils;
import com.chen.customviewdemo.view.PhotoFromSelectPop;
import java.io.File;
/**
* 拍照。并压缩图片
*/
public class MainActivity_21_Photo_Compress_Img extends BaseActivity implements View.OnClickListener, PopSelectListener {
ImageView iv_image;
TextView result_url_tv;
TextView result_url_tv_2;
TextView photo_src_size;
TextView photo_compress_size;
TextView show_tv_21;
PhotoFromSelectPop photoFromSelectPop;
String url;
String imageName;
String compress_url;
@Override
void initview() {
setContentView(R.layout.activity_main_21);
iv_image = (ImageView) findViewById(R.id.iv_image);
result_url_tv = (TextView) findViewById(R.id.result_url_tv);
result_url_tv_2 = (TextView) findViewById(R.id.result_url_tv_2);
photo_src_size = (TextView) findViewById(R.id.photo_src_size);
photo_compress_size = (TextView) findViewById(R.id.photo_compress_size);
show_tv_21 = (TextView) findViewById(R.id.show_tv_21);
iv_image.setOnClickListener(this);
show_tv_21.setOnClickListener(this);
File file = new File(CHEN.img_path);
if (!file.exists()) {
try {
file.mkdirs();
Toast.makeText(this, "路径创建成功", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, "路径创建失败", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_image:
photoFromSelectPop = new PhotoFromSelectPop(this);
photoFromSelectPop.initPopupWindow(this);
break;
case R.id.show_tv_21:
//TODO
//点击显示结果。这仅仅是demo,没有做太多推断,不要有益报空指针。拍完照以后,等3秒左右再点击
result_url_tv.setText(url);
File file = new File(url);
photo_src_size.setText("图片大小==KB==" + Utils.getNumAccuracy_2(file.length() / 1024f) + "---图片大小==MB==" + Utils.getNumAccuracy_2(file.length() / (1024f * 1024f)));
//压缩
result_url_tv_2.setText(compress_url);
File compress_file = new File(compress_url);
photo_compress_size.setText("图片大小==KB==" + Utils.getNumAccuracy_2(compress_file.length() / 1024) + "---图片大小==MB==" + Utils.getNumAccuracy_2(compress_file.length() / (1024f * 1024f)));
break;
}
}
@Override
public void popSelect(int flag) {
switch (flag) {
case 0:
Toast.makeText(this, "从相冊选取", Toast.LENGTH_SHORT).show();
break;
case 1:
//拍照
imageName = "/" + System.currentTimeMillis() + ".jpg";
Intent intent_photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent_photo.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(CHEN.img_path, imageName)));
startActivityForResult(intent_photo, 1002);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != 0) {
url = CHEN.img_path + imageName;
if (!TextUtils.isEmpty(url)) {
//开一个子线程去处理压缩。这是由于,压缩会由于一些原因先运行。即:拍照结束后,点击确认button,会停一下,才跳转回自己的界面。开了子线程去处理压缩。会让跳转变的流畅一点
new Thread() {
public void run() {
//压缩
compress_url = FileHelper.checkFileSize(url);
}
}.start();
}
} else {
result_url_tv.setText("没有拍照,返回");
}
super.onActivityResult(requestCode, resultCode, data);
}
}