效果图
photo.png需求: 获取手机内存中的所有图片,以及拍照图片。可勾选上传到服务器。
本文只实现了获取内存中的所有图片展示勾选,但未放置上传服务器代码。毕竟服务器各不相同且上传只需IO操作
首页布局RecyclerView,就不上布局代码了。
直接上整体首页代码
<pre>
public class PhotoListActivity extends AppCompatActivity implements View.OnClickListener {
private RecyclerView recycManager;
private LoaderManager.LoaderCallbacks<Cursor> loaderCallbacks;//图片加载器
private Activity mActivity = null;
private ArrayList<PhotoInfo> photoInfoList = new ArrayList<>();
private PhotoAdapter photoAdapter;
private File path;
private TextView textNumber;
private TextView textEnter;
private ArrayList<String> resultList = new ArrayList<>();//返回首页的集合
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_list);
initView();
initListener();
initPhoto();
initRecycler();
}
private void initView() {
mActivity = this;
recycManager = (RecyclerView) findViewById(R.id.recycManager);
textNumber = (TextView) findViewById(R.id.textNumber);
textEnter = (TextView) findViewById(R.id.textEnter);
textNumber.setText("(" + 0 + "/9" + ")");
}
private void initListener() {
textEnter.setOnClickListener(this);
}
private File createCreamePath;
private void initRecycler() {
GridLayoutManager gridLayoutManager = new GridLayoutManager(mActivity, 3);
recycManager.setLayoutManager(gridLayoutManager);
photoAdapter = new PhotoAdapter(mActivity, photoInfoList);
recycManager.setAdapter(photoAdapter);
photoAdapter.getPhoto(new PhotoAdapter.getPhoto() {
@Override
public void getTakeCreame(View v) {
Intent intentPhone = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
createCreamePath = createTmpFile(mActivity, "/Edreamoon/Pictures");
intentPhone.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(createCreamePath));
intentPhone.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivityForResult(intentPhone, 100);
}
});
photoAdapter.getSelectPhoto(new PhotoAdapter.getSelectPhoto() {
@Override
public void getListPhoto(List<String> photoPath) {
resultList.clear();
int size = photoPath.size();
textNumber.setText("(" + size + "/9" + ")");
if (size > 0) {
textEnter.setVisibility(View.VISIBLE);
} else {
textEnter.setVisibility(View.GONE);
}
//获取选择集合赋值给 返回MAIN集合
for (String path : photoPath) {
if (resultList.contains(path)) {
resultList.remove(path);
} else {
resultList.add(path);
}
}
}
});
}
</pre>
private void initPhoto() {
loaderCallbacks = new LoaderManager.LoaderCallbacks<Cursor>() {
private final String[] IMAGE_PROJECT = {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.SIZE,
};
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (id == 0) {
return new CursorLoader(mActivity, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECT, null, null, IMAGE_PROJECT[2] + " DESC");
} else if (id == 1) {
return new CursorLoader(mActivity, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECT, IMAGE_PROJECT[0] + "like '%" + args.getString("path") + "%'", null, IMAGE_PROJECT[2] + " DESC");
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data != null) {
photoInfoList.clear();
int count = data.getCount();
data.moveToFirst();
if (count > 0) {
do {
String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECT[0]));
String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECT[1]));
long time = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECT[2]));
int size = data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECT[4]));
PhotoInfo photoInfo = new PhotoInfo(path, name, time, false);
Boolean isSize5k = size > 1024 * 5;
if (isSize5k) {
photoInfoList.add(photoInfo);
}
} while (data.moveToNext());
}
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
};
getSupportLoaderManager().restartLoader(0, null, loaderCallbacks);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100 && resultCode == RESULT_OK) {
resultList.clear();
String absolutePath = createCreamePath.getAbsolutePath();
resultList.add(absolutePath);
Intent intent = new Intent(mActivity, MainActivity.class);
intent.putExtra("resultPath", resultList);
setResult(200, intent);
finish();
}
}
/**
* 创建文件
*
* @param context context
* @param filePath 文件路径
* @return file
*/
public static File createTmpFile(Context context, String filePath) {
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA).format(new Date());
String externalStorageState = Environment.getExternalStorageState();
File dir = new File(Environment.getExternalStorageDirectory() + filePath);
if (externalStorageState.equals(Environment.MEDIA_MOUNTED)) {
if (!dir.exists()) {
dir.mkdirs();
}
return new File(dir, timeStamp + ".jpg");
} else {
File cacheDir = context.getCacheDir();
return new File(cacheDir, timeStamp + ".jpg");
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.textEnter:
Intent intent = new Intent(mActivity, MainActivity.class);
intent.putExtra("resultPath", resultList);
setResult(200, intent);
finish();
break;
}
}
}
adapter代码
<pre>
public class PhotoAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<PhotoInfo> list;
private LayoutInflater inflater;
private getPhoto getPhoto;
private List<String> selectPhoto = new ArrayList<>();
private getSelectPhoto getSelectPhoto;
public PhotoAdapter(Context mContext, List<PhotoInfo> list) {
this.mContext = mContext;
this.list = list;
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
selectPhoto.clear();
}
public void getPhoto(getPhoto getPhoto) {
this.getPhoto = getPhoto;
}
public void getSelectPhoto(getSelectPhoto getSelectPhoto) {
this.getSelectPhoto = getSelectPhoto;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {//显示的第一张图片的布局 , 就是调用摄像头拍照的布局。
return new MyViewHolder(inflater.inflate(R.layout.item_photo_adapter_first, parent, false));
}//之后的图片显示的布局。
return new MyViewHolder(inflater.inflate(R.layout.item_photo_adapter, parent, false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
holder.setIsRecyclable(false);
ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
params.height = getScreenWidth(mContext) / 3;
params.width = getScreenWidth(mContext) / 3;
holder.itemView.setLayoutParams(params);//重设item大小
if (getItemViewType(position) == 0) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//因为拍照要返回参数,所以接口回调方式将事件处理交给activity处理
getPhoto.getTakeCreame(v);
}
});
return;
}
final MyViewHolder myViewHolder = (MyViewHolder) holder;
final PhotoInfo photoInfo = list.get(position - 1);
Glide.with(mContext).load(photoInfo.path).into(myViewHolder.image);
myViewHolder.image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (selectPhoto.size() < 9) {
//selectPhoto为选中的集合。
if (selectPhoto.contains(photoInfo.path)) {
selectPhoto.remove(photoInfo.path);
photoInfo.setChecked(false);
myViewHolder.checkBox.setButtonDrawable(R.mipmap.uncheck);
} else {
selectPhoto.add(photoInfo.path);
photoInfo.setChecked(true);
myViewHolder.checkBox.setButtonDrawable(R.mipmap.checked);
}
myViewHolder.checkBox.setChecked(photoInfo.getChecked());
getSelectPhoto.getListPhoto(selectPhoto);
} else {
if (selectPhoto.contains(photoInfo.path)) {
selectPhoto.remove(photoInfo.path);
photoInfo.setChecked(false);
myViewHolder.checkBox.setButtonDrawable(R.mipmap.uncheck);
} else {
Toast.makeText(mContext, "最多选择9张", Toast.LENGTH_SHORT).show();
}
}
}
});
if (photoInfo.getChecked()) {
myViewHolder.checkBox.setChecked(photoInfo.getChecked());
myViewHolder.checkBox.setButtonDrawable(R.mipmap.checked);
} else {
myViewHolder.checkBox.setButtonDrawable(R.mipmap.uncheck);
}
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return 0;
}
return 1;
}
@Override
public int getItemCount() {
return list.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
private CheckBox checkBox;
public MyViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
checkBox = (CheckBox) itemView.findViewById(R.id.checkbox);
}
}
/**
* 获得屏幕高度
*
* @param context context
* @return 屏幕高度
*/
public int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
//获取拍照后的照片
public interface getPhoto {
void getTakeCreame(View v);
}
public interface getSelectPhoto {
void getListPhoto(List<String> photoPath);
}
}
</pre>
模型类
<pre>
public class PhotoInfo {
public String name; // 图片名
public String path; // 图片路径
public long time; // 图片添加时间
public Boolean checked; //checkbox 选中状态
public PhotoInfo(String path, String name, long time ,Boolean checked) {
this.path = path;
this.name = name;
this.time = time;
this.checked =checked;
}
public Boolean getChecked() {
return checked;
}
public void setChecked(Boolean checked) {
this.checked = checked;
}
@Override
public String toString() {
return "PhotoInfo{" +
"name='" + name + '\'' +
", path='" + path + '\'' +
", time=" + time +
'}';
}
@Override
public boolean equals(Object object) {
try {
PhotoInfo other = (PhotoInfo) object;
return this.path.equalsIgnoreCase(other.path);
} catch (ClassCastException e) {
e.printStackTrace();
}
return super.equals(object);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
}
</pre>
具体思路
1-写一个模型类储存自己想要的数据: 路径,文件名,时间
2-涉及到recyclerView复用套checkbox的问题,所以在模型类中加了Boolean类型显示checkbox状态
3-通过LoaderManager.LoaderCallbacks<Cursor> 获取内存图片
4-书写adapter :由于调用本地拍照需返回,所以adapter写接口,讲事件处理交给activity
5-加部分细节,比如只能只能9张 ,等。
6-activityResult回调处理,我将路径全都存到了集合中,可直接拿来路径上传服务器等或别的操作
有兴趣的小伙伴可以帮忙关注一下csdn,谢谢
https://blog.csdn.net/binbinxiaoz
网友评论