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;
	}

}




效果图 :

不会做动态图,就随便截了几张


九宫格展示压缩后的缩略图:

九宫格展示压缩后的缩略图

点击“+”号添加图片:

添加图片

点击缩略图可删除对应的源文件:

删除照片


                       点此下载源码

  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
实现Android仿微信朋友片查看功能,可以按照以下步骤进行: 1. 首先,需要使用一个RecyclerView来展示朋友圈的列表,每个朋友圈项包含了片的略图、文字内容和评论等信息。 2. 当用户点某个朋友圈项时,需要跳转到一个新的Activity或者Fragment来显示朋友圈的详细内容。 3. 在新的界面中,可以使用ViewPager来展示朋友圈中的片。ViewPager的每一页对应一张片,并实现左右滑动切换片的功能。 4. 对于片的加载,可以使用一个片加载如Glide或Picasso来加载片,避免OOM(Out of Memory)的问题。 5. 为了更好的用户体验,可以在ViewPager上添加一个类似于微信片预览效果,即当用户点某张片时,可以全屏显示,并支持放、双放大、手势滑动等功能。 6. 为了保证性能和流畅度,可以使用一些优化技巧,如片的压缩、缓存、异步加载等。 7. 如果需要支持多张片的查看,可以使用PhotoView或类似的第三方实现,它可以显示多张片,并支持手势操作。 8. 最后,为了提高用户体验,可以加入一些其他功能,如显示片的点赞数和评论数、支持多种分享方式、保存等。 通过以上步骤的实现,就可以实现Android仿微信朋友片查看的功能了。这样用户就可以在朋友圈列表中预览片,点后再进行详细查看和操作,提高了用户的交互体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值