项目需求只需要一张图片,需要其他的可以自己改改;代码地址在最下面
不好意思,在下午的测试中测到如果用户没有拍照,直接finish掉会空指针异常,现在已解决
@Override
protected void onDestroy() {
super.onDestroy();
if (!isImageView) {
mFile.delete();
}
}
在onDestroy()方法中这样去判断,现在已经改正,疏忽大意了.代码地址就不变了,我不知道怎么重新上传。。。
项目需求是这个效果,搜到的Demo对比一下也不太满意,干脆自己写一个
分析起来很简单,一个GridView和EditText组成,为了保持那个图标一直都是最后一个所以在Adapter的getCount那里把size+1;
package com.example.y.demo;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import java.util.ArrayList;
/**
* Created by y on 2016/3/16.
*/
public class Adapter extends BaseAdapter {
private ArrayList<Bitmap> list;
private Context context;
public Adapter(Context context, ArrayList<Bitmap> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size() + 1;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.item, null);
ImageView iv = (ImageView) convertView.findViewById(R.id.iv);
if (position < list.size()) {
iv.setImageBitmap(list.get(position));
} else if (position == list.size()) {
iv.setImageResource(R.mipmap.photo);
}
return convertView;
}
}
布局就是两个控件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context="com.example.y.demo.MainActivity">
<EditText
android:id="@+id/et_feedback"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="20dp"
android:background="@mipmap/bg_edit_feedback"
android:gravity="left"
android:hint="照片只可以上传一张"
android:minHeight="200dp"
android:padding="10dp"
android:textColorHint="#a8a8a8"
android:textSize="14sp" />
<GridView
android:id="@+id/gv_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/et_feedback"
android:layout_marginTop="-70dp"
android:background="@null"
android:listSelector="@android:color/transparent"
android:numColumns="4" />
</RelativeLayout>
这里要注意以下,加了GridView我的EditText总是自动获取焦点自动弹出键盘,在manifests.xml的那个activity下加一句
android:windowSoftInputMode="stateHidden"
一共有好几个属性,有兴趣的可以自己去查下资料
记得一定要添加权限
<!--在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 从SDCard读取数据权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Activity的注释比较详细,就不细说了
package com.example.y.demo;
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.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private Uri imageUri;
private boolean isImageView = true;
private String path;
private ArrayList<Bitmap> list;
private Adapter adapter;
private GridView gridView;
private static final int RESULT_OPENCAMERA_LOAD_IMAGE = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new ArrayList<>();
adapter = new Adapter(getApplicationContext(), list);
gridView = (GridView) findViewById(R.id.gv_photo);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (isImageView && position == adapter.getCount() - 1) {
openCamera();
} else if (position == adapter.getCount() - 1) {
Toast.makeText(getApplicationContext(), "抱歉,只能选择一张照片", Toast.LENGTH_LONG).show();
}
}
});
}
private void openCamera() {
//建议一些缓存的东西都这样弄,放在Android/data文件夹下的包名,这样你的软件卸载了,缓存也会被一起卸载。
path = getExternalFilesDir(Environment.DIRECTORY_DCIM).getPath() + File.separator + "temp.png";
File mFile = new File(path);
try {
if (mFile.exists()) {
mFile.delete();
}
mFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
imageUri = Uri.fromFile(mFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//这个属性可以拿到正常拍照的图,否则得到的图和打了马赛克的动作片没区别
startActivityForResult(intent, RESULT_OPENCAMERA_LOAD_IMAGE);//想在onActivityResult里面得到返回的数据,只能startActivityForResult
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case RESULT_OPENCAMERA_LOAD_IMAGE:
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
list.add(saveFile(bitmap, path));//之所以用同一个路径是方便,直接覆盖原图,避免原图好几M,而让SD卡垃圾过多,看需求而定
adapter.notifyDataSetChanged();
isImageView = false;
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
/**
* 压缩图片的方法
*
* @param bm
* @param fileName
* @return
* @throws Exception
*/
public Bitmap saveFile(Bitmap bm, String fileName) throws Exception {
File dirFile = new File(fileName);
if (dirFile.exists()) {
dirFile.delete();
}
File myCaptureFile = new File(fileName);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));
bm.compress(Bitmap.CompressFormat.JPEG, 50, bos);//压缩图片,成像基本没变
bos.flush();
bos.close();
return bm;
//这样压缩的图片亲测从2M被压倒了300K,而且清晰度没怎么变
}
@Override
protected void onDestroy() {
super.onDestroy();
if (!isImageView) {
mFile.delete();
}
}//一般只用一次的图片,比如换头像之类的一定要在onDestroy方法中删除文件。避免SD卡垃圾过多}}