1. 程式人生 > >Android實現仿微信朋友圈釋出動態(拍照、相簿選擇、照片壓縮、顯示、儲存、縮圖、點選縮圖刪除對應檔案等)附原始碼

Android實現仿微信朋友圈釋出動態(拍照、相簿選擇、照片壓縮、顯示、儲存、縮圖、點選縮圖刪除對應檔案等)附原始碼

         原創作品,轉載請註明出處:http://blog.csdn.net/zhang3776813/article/details/52092591

最近專案需求中要用到類似微信朋友圈釋出動態選擇圖片的UI效果,研究了一下,特來分享成果,多的不說來看程式碼。

Activity類

package com.whfp.circle_of_friends;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.whfp.adapter.GridViewAdapter;
import com.whfp.utils.FileUtils;
import com.whfp.utils.ImageTools;

import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;



/**
 * 仿微信朋友圈釋出動態
 * 拍照或相簿選擇 
 * 壓縮圖片並儲存
 * @author 張明楊
 *
 */
public class MainActivity extends BasicActivity implements OnItemClickListener {

	// 圖片 九宮格
	private GridView gv;
	// 圖片 九宮格介面卡
	private GridViewAdapter gvAdapter;

	// 用於儲存圖片資原始檔
	private List<Bitmap> lists = new ArrayList<Bitmap>();
	// 用於儲存圖片路徑
	private List<String> list_path = new ArrayList<String>();

	// 拍照
	public static final int IMAGE_CAPTURE = 1;
	// 從相簿選擇
	public static final int IMAGE_SELECT = 2;
	// 照片縮小比例
	private static final int SCALE = 5;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
	}

	/**
	 * 初始化控制元件
	 */
	private void init() {
		gv = (GridView) findViewById(R.id.noScrollgridview);
		gvAdapter = new GridViewAdapter(this, lists);
		gv.setOnItemClickListener(this);
		gv.setAdapter(gvAdapter);
		gvAdapter.setList(lists);
	}
	
	@Override
	protected void onDestroy() {
		//刪除資料夾及檔案
		FileUtils.deleteDir();
		super.onDestroy();
	}

	/**
	 * 拍照
	 * 
	 * @param path
	 *            照片存放的路徑
	 */
	public void captureImage(String path) {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		// 指定照片儲存路徑(SD卡),image.jpg為一個臨時檔案,每次拍照後這個圖片都會被替換
		Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "image.jpg"));
		intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
		startActivityForResult(intent, IMAGE_CAPTURE);
	}

	/**
	 * 從相簿中選取圖片
	 */
	public void selectImage() {
		 Intent intent = new Intent();
		 intent.setType("image/*");
		 intent.setAction(Intent.ACTION_PICK);
		 startActivityForResult(intent, IMAGE_SELECT);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == RESULT_OK && resultCode != RESULT_CANCELED) {
			String fileName;
			switch (requestCode) {
			case IMAGE_CAPTURE:// 拍照返回
				// 將儲存在本地的圖片取出並縮小後顯示在介面上
				Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/image.jpg");
				Bitmap newBitmap = ImageTools.zoomBitmap(bitmap,bitmap.getWidth() / SCALE, bitmap.getHeight() / SCALE);
				// 由於Bitmap記憶體佔用較大,這裡需要回收記憶體,否則會報out of memory異常
				bitmap.recycle();
				// 生成一個圖片檔名
				fileName = String.valueOf(System.currentTimeMillis());
				// 將處理過的圖片新增到縮圖列表並儲存到本地
				ImageTools.savePhotoToSDCard(newBitmap, FileUtils.SDPATH,fileName);
				lists.add(newBitmap);
				list_path.add(fileName+".jpg");
				
				for (int i = 0; i < list_path.size(); i++) {
					logI("第"+i+"張照片的地址:"+list_path.get(i));
				}
				
				// 更新GrideView
				gvAdapter.setList(lists);
				break;
			case IMAGE_SELECT:// 選擇照片返回
				ContentResolver resolver = getContentResolver();
				// 照片的原始資源地址
				Uri originalUri = data.getData();
				try {
					// 使用ContentProvider通過URI獲取原始圖片
					Bitmap photo = MediaStore.Images.Media.getBitmap(resolver,originalUri);
					if (photo != null) {
						// 為防止原始圖片過大導致記憶體溢位,這裡先縮小原圖顯示,然後釋放原始Bitmap佔用的記憶體
						Bitmap smallBitmap = ImageTools.zoomBitmap(photo,photo.getWidth() / SCALE, photo.getHeight()/ SCALE);
						// 釋放原始圖片佔用的記憶體,防止out of memory異常發生
						photo.recycle();
						// 生成一個圖片檔名
						fileName = String.valueOf(System.currentTimeMillis());
						// 將處理過的圖片新增到縮圖列表並儲存到本地
						ImageTools.savePhotoToSDCard(smallBitmap, FileUtils.SDPATH,fileName);
						lists.add(smallBitmap);
						list_path.add(fileName+".jpg");
						
						for (int i = 0; i < list_path.size(); i++) {
							logI("第"+i+"照片的地址:"+list_path.get(i));
						}
						
						// 更新GrideView
						gvAdapter.setList(lists);
					}
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				
				break;
			default:
				break;
			}
		}
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, final int position,
			long id) {
		Toast.makeText(getApplicationContext(), "" + position + getDataSize(),Toast.LENGTH_SHORT).show();

		if (position == getDataSize()) {// 點選“+”號位置新增圖片
			showAlertDialog(false, "提示", new String[] { "拍照", "從相簿選擇", "取消" },
					new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							switch (which + 1) {
							case 1:// 拍照
								captureImage(FileUtils.SDPATH);
								dialog.dismiss();
								break;
							case 2:// 從相簿選擇
								selectImage();
								dialog.dismiss();
								break;
							case 3:// 取消
								dialog.dismiss();
								break;

							default:
								break;
							}
						}
					});
		} else {// 點選圖片刪除
			showAlertDialog("提示", "是否刪除此圖片?", "確定", "取消", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					lists.remove(position);
					FileUtils.delFile(list_path.get(position));
					list_path.remove(position);
					gvAdapter.setList(lists);
					dialog.dismiss();
				}
			}, new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
				}
			});
		}
	}

	private int getDataSize() {
		return lists == null ? 0 : lists.size();
	}

}


圖片壓縮的工具類:

package com.whfp.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.util.Log;

public class FileUtils {

	/**
	 * 生成資料夾路徑
	 */
	public static String SDPATH = Environment.getExternalStorageDirectory()
			+ "/TEST_PY/";

	/**
	 * 將圖片壓縮儲存到資料夾
	 * 
	 * @param bm
	 * @param picName
	 */
	public static void saveBitmap(Bitmap bm, String picName) {
		try {

			// 如果沒有資料夾就建立一個程式資料夾
			if (!isFileExist("")) {
				File tempf = createSDDir("");
			}
			File f = new File(SDPATH, picName + ".JPEG");
			// 如果該資料夾中有同名的檔案,就先刪除掉原檔案
			if (f.exists()) {
				f.delete();
			}
			FileOutputStream out = new FileOutputStream(f);
			bm.compress(Bitmap.CompressFormat.JPEG, 90, out);
			out.flush();
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 質量壓縮 並返回Bitmap
	 * 
	 * @param image
	 *            要壓縮的圖片
	 * @return 壓縮後的圖片
	 */
	private Bitmap compressImage(Bitmap image) {

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 質量壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到baos中
		int options = 100;
		while (baos.toByteArray().length / 1024 > 100) { // 迴圈判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮
			baos.reset();// 重置baos即清空baos
			image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 這裡壓縮options%,把壓縮後的資料存放到baos中
			options -= 10;// 每次都減少10
		}
		ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把壓縮後的資料baos存放到ByteArrayInputStream中
		Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream資料生成圖片
		return bitmap;
	}

	/**
	 * 質量壓縮
	 * 
	 * @param bitmap
	 * @param picName
	 */
	public static void compressImageByQuality(final Bitmap bitmap,
			String picName) {
		// 如果沒有資料夾就建立一個程式資料夾
		if (!isFileExist("")) {
			try {
				File tempf = createSDDir("");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		File f = new File(SDPATH, picName + ".JPEG");
		// 如果該資料夾中有同名的檔案,就先刪除掉原檔案
		if (f.exists()) {
			f.delete();
		}

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int options = 100;
		// 質量壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到baos中
		bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
		// 迴圈判斷如果壓縮後圖片是否大於200kb,大於繼續壓縮
		while (baos.toByteArray().length / 1024 > 500) {
			// 重置baos即讓下一次的寫入覆蓋之前的內容
			baos.reset();
			// 圖片質量每次減少5
			options -= 5;
			// 如果圖片質量小於10,則將圖片的質量壓縮到最小值
			if (options < 0)
				options = 0;
			// 將壓縮後的圖片儲存到baos中
			bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
			// 如果圖片的質量已降到最低則,不再進行壓縮
			if (options == 0)
				break;
		}
		// 將壓縮後的圖片儲存的本地上指定路徑中
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(new File(SDPATH, picName + ".JPEG"));
			fos.write(baos.toByteArray());
			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}
	}

	/**
	 * 建立資料夾
	 * 
	 * @param dirName
	 *            資料夾名稱
	 * @return 資料夾路徑
	 * @throws IOException
	 */
	public static File createSDDir(String dirName) throws IOException {
		File dir = new File(SDPATH + dirName);
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {

			System.out.println("createSDDir:" + dir.getAbsolutePath());
			System.out.println("createSDDir:" + dir.mkdir());
		}
		return dir;
	}

	/**
	 * 判斷改檔案是否是一個標準檔案
	 * 
	 * @param fileName
	 *            判斷的檔案路徑
	 * @return 判斷結果
	 */
	public static boolean isFileExist(String fileName) {
		File file = new File(SDPATH + fileName);
		file.isFile();
		return file.exists();
	}

	/**
	 * 刪除指定檔案
	 * 
	 * @param fileName
	 */
	public static void delFile(String fileName) {
		File file = new File(SDPATH + fileName);
		if (file.isFile()) {
			file.delete();
		}
		file.exists();
	}

	/**
	 * 刪除指定檔案
	 * @param file
	 */
	public static void deleteFile(File file) {
		if (file.exists()) { // 判斷檔案是否存在
			if (file.isFile()) { // 判斷是否是檔案
				file.delete(); // delete()方法 你應該知道 是刪除的意思;
			} else if (file.isDirectory()) { // 否則如果它是一個目錄
				File files[] = file.listFiles(); // 宣告目錄下所有的檔案 files[];
				for (int i = 0; i < files.length; i++) { // 遍歷目錄下所有的檔案
					deleteFile(files[i]); // 把每個檔案 用這個方法進行迭代
				}
			}
			file.delete();
		} else {
			Log.i("TAG", "檔案不存在!");
		}
	}

	/**
	 * 刪除指定資料夾中的所有檔案
	 */
	public static void deleteDir() {
		File dir = new File(SDPATH);
		if (dir == null || !dir.exists() || !dir.isDirectory())
			return;

		for (File file : dir.listFiles()) {
			if (file.isFile())
				file.delete();
			else if (file.isDirectory())
				deleteDir();
		}
		dir.delete();
	}

	/**
	 * 判斷是否存在該檔案
	 * 
	 * @param path
	 *            檔案路徑
	 * @return
	 */
	public static boolean fileIsExists(String path) {
		try {
			File f = new File(path);
			if (!f.exists()) {
				return false;
			}
		} catch (Exception e) {

			return false;
		}
		return true;
	}

}

九宮格縮圖介面卡類:

package com.whfp.adapter;

import java.util.ArrayList;
import java.util.List;

import com.whfp.circle_of_friends.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

/**
 * 九宮格縮圖介面卡
 * @author 張明楊
 *
 */
public class GridViewAdapter extends BaseAdapter {

	private Context mContext;
	private List<Bitmap> list = new ArrayList<Bitmap>();
	
	public GridViewAdapter() {
		super();
	}
/**
 * 獲取列表資料
 * @param list
 */
	public void setList(List<Bitmap> list){
		this.list = list;
		this.notifyDataSetChanged();
	}
	
	public GridViewAdapter(Context mContext,List<Bitmap> list) {
		super();
		this.mContext = mContext;
		this.list = list;
	}

	@Override
	public int getCount() {
		Log.e("  ", list.size()+"");
		if(list==null){
			return 1;
		}else if(list.size()==9){
			return 9;
		}else{
			return list.size()+1;
		}
	}

	@Override
	public Object getItem(int position) {
		if (list != null
				&& list.size() == 9)
		{
			return list.get(position);
		}

		else if (list == null || position - 1 < 0
				|| position > list.size())
		{
			return null;
		}
		else
		{
			return list.get(position - 1);
		}
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		if(convertView==null){
			convertView = LayoutInflater.from(mContext).inflate(R.layout.item_published_grida, null);
			holder = new ViewHolder();
			holder.item_grida_image = (ImageView) convertView.findViewById(R.id.item_grida_image);
			convertView.setTag(holder);
		}else{
			holder = (ViewHolder) convertView.getTag();
		}

		if (isShowAddItem(position))
		{
			holder.item_grida_image.setImageResource(R.drawable.btn_add_pic);
			holder.item_grida_image.setBackgroundResource(R.color.bg_gray);
			
		}
		else
		{
			holder.item_grida_image.setImageBitmap(list.get(position));
			holder.item_grida_image.setBackgroundResource(R.color.bg_gray);
		}
		return convertView;
	}
	/**
	 * 判斷當前下標是否是最大值
	 * @param position  當前下標
	 * @return
	 */
	private boolean isShowAddItem(int position)
	{
		int size = list == null ? 0 : list.size();
		return position == size;
	}
	
	class ViewHolder{
		ImageView item_grida_image;
	}

}


效果圖 :

不會做動態圖,就隨便截了幾張

九宮格展示壓縮後的縮圖:

九宮格展示壓縮後的縮圖

點選“+”號新增圖片:

新增圖片

點選縮圖可刪除對應的原始檔:

刪除照片