效果展示图
步骤一:导入依赖
(1)在build.gradle(app)
(2)在AndroidManifest.xml(清单文件)
访问权限配置
文件保护
文件路径定义
(3)在setting.gradle中通过将仓库URL更改为https://jitpack.io,可以确保Maven能够正确地访问仓库并下载和构建依赖项。
(4)在gradle.properties 需要构建和调试应用程序时启用Jetifier
步骤二:页面绘制和部署
(1)activity_main.xml 主页面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="top"
android:hint="请输入上传内容"
android:padding="15dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="15dp" />
<Button
android:id="@+id/upload"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="显示" />
</LinearLayout>
(2)activity_add_photo.xml 拍摄/访问相册弹窗
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:background="@color/gray"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/camera"
android:background="@color/white"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="拍摄"
android:textColor="@color/blue"
android:textSize="18dp"
tools:ignore="HardcodedText,RtlHardcoded" />
<TextView
android:id="@+id/ap_tv_line_1"
android:background="@drawable/shape_line"
android:layout_width="match_parent"
android:layout_height="1dp">
</TextView>
<TextView
android:id="@+id/pic"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text=" 从手机相册中选择 "
android:textColor="@color/blue"
android:textSize="18dp"
tools:ignore="HardcodedText,RtlHardcoded" />
<!-- <TextView
android:id="@+id/ap_tv_line_2"
android:background="@drawable/shape_line"
android:layout_width="match_parent"
android:layout_height="5dp">
</TextView>-->
<TextView
android:id="@+id/cancel"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="10dp"
android:padding="15dp"
android:text="取消"
android:textColor="@color/blue"
android:textSize="18dp"
tools:ignore="HardcodedText,RtlHardcoded" />
</LinearLayout>
(3)activity_photo_view.xml 浏览图片的页面
<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"
android:background="#000000"
tools:context=".PhotoViewActivity">
<ImageView
android:layout_centerInParent="true"
android:id="@+id/iv_photoView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="16sp"
android:id="@+id/mTvImageCount"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="5dp"
android:text="1/1" />
</RelativeLayout>
(4)item_add.xml 添加按钮
<?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="100dp">
<RelativeLayout
android:id="@+id/add_newsImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00000000">
<ImageView
android:id="@+id/im_show_gallery"
android:layout_centerHorizontal="true"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/btn_cp_add"
android:layout_centerInParent="true">
</ImageView>
</RelativeLayout>
</LinearLayou
(5)item_gallery.xml 展示按钮和删除按钮
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginBottom="5dp"
android:paddingRight="5dp">
<!--显示照片和删除照片-->
<ImageView
android:id="@+id/iv_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/iv_del"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:padding="5dp"
android:src="@drawable/picture_icon_delete_photo" />
</RelativeLayout>
步骤三:功能逻辑实现
(1)MainActivity.java 主页面
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private RecyclerView recyclerView;
private NineGridAdapter nineGridAdapter;
private Uri cameraUri; //相机拍照返回图片路径
private Uri photoUri; //相册返回图片路径
private File outputCameraImage;
private static final int CHOOSE_PHOTO = 1;
private static final int TAKE_PHOTO = 2;
public final List<Map<String,Object>> list = new ArrayList<>();
private transient View inflate;
private transient TextView camera;
private transient TextView picture;
private transient TextView cancel;
private transient Dialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//显示添加图片
Map<String,Object> map=new HashMap<>();
map.put("type",1);
list.add(map);
nineGridAdapter = new NineGridAdapter(MainActivity.this, list);
recyclerView = findViewById(R.id.recycler);
}
//拍摄对话框
public void showDialog() {
dialog = new Dialog(this,R.style.DialogTheme);
//填充对话框的布局
inflate = LayoutInflater.from(this).inflate(R.layout.activity_add_photos, null);
//初始化控件
camera = (TextView) inflate.findViewById(R.id.camera);
picture = (TextView) inflate.findViewById(R.id.pic);
cancel = (TextView) inflate.findViewById(R.id.cancel);
camera.setOnClickListener(this);
picture.setOnClickListener(this);
cancel.setOnClickListener(this);
//将布局设置给Dialog
dialog.setContentView(inflate);
//获取当前Activity所在的窗体
Window dialogWindow = dialog.getWindow();
//设置Dialog从窗体底部弹出
dialogWindow.setGravity( Gravity.BOTTOM);
//获得窗体的属性
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.y = 20;//设置Dialog距离底部的距离
//将属性设置给窗体
dialogWindow.setAttributes(lp);
dialog.show();//显示对话框
}
@Override
protected void onStart() {
super.onStart();
recyclerView.setAdapter(nineGridAdapter);
GridLayoutManager manager = new GridLayoutManager(this, 3);//布局管理为九宫格,每行三个
recyclerView.setLayoutManager(manager);
nineGridAdapter.setOnAddPicturesListener(new OnAddPicturesListener() {
//添加图片
@Override
public void onAdd() {
showDialog();
}
//删除图片
@Override
public void delete(int position) {
nineGridAdapter.remove(position);
}
//展示大图片
@Override
public void item(int position, List<Map<String, Object>> mList) {
nineGridAdapter.showImage(MainActivity.this, position, mList);
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//拍摄
case R.id.camera: {
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.CAMERA}, TAKE_PHOTO);
} else {
selectCamera();
Toast.makeText(MainActivity.this, "点击了拍摄", Toast.LENGTH_SHORT).show();
}
break;
}
//相册
case R.id.pic: {
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CHOOSE_PHOTO);
} else {
selectPhoto();
Toast.makeText(MainActivity.this, "点击了相册", Toast.LENGTH_SHORT).show();
}
break;
}
//取消
case R.id.cancel: {
dialog.dismiss();
break;
}
}
}
private void selectCamera() {
// 步骤一:创建一个File对象,用于保存摄像头拍下的图片,这里把图片命名为output_image.jpg
// 并将它存放在手机SD卡的应用关联缓存目录下
outputCameraImage = new File(getExternalCacheDir(), "camera_photos1" + System.currentTimeMillis() + ".jpg");
// 对照片的更换设置
try {
//如果上一次的照片存在,就删除
if (outputCameraImage.exists()) {
Log.i("outputCameraImage", String.valueOf(outputCameraImage.exists()));
outputCameraImage.delete();
}
// 创建一个新的文件
outputCameraImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= 24) {
// 将File对象转换成一个封装过的Uri对象
cameraUri = FileProvider.getUriForFile(this, "com.example.testrecycleview.fileprovider", outputCameraImage);
} else {
//将File对象转换为Uri对象,这个Uri标识着output_image.jpg这张图片的本地真实路径
cameraUri = Uri.fromFile(outputCameraImage);
}
//步骤二:启动相机
// 启动相机程序
Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定图片的输出地址为imageUri
intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, cameraUri);
startActivityForResult(intentCamera, TAKE_PHOTO);
}
//选择相册
private void selectPhoto(){
Intent intent = new Intent(ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, CHOOSE_PHOTO);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
//相册返回
case CHOOSE_PHOTO:
if (resultCode == RESULT_OK) {
photoUri = data.getData();
Photo(photoUri);
dialog.dismiss();//取消对话框
}
break;
//拍照返回TAKE_PHOTO
case TAKE_PHOTO:
if (resultCode == RESULT_OK) {
Photo(cameraUri);
dialog.dismiss();//取消对话框
}
break;
default:
}
}
public void Photo(Uri uri) {
int size = list.size();
list.remove(size-1);
Map<String, Object> map = new HashMap<>();
map.put("type",1);
map.put("uri",uri);
list.add(map);
if (list.size() != 9) {
Map<String, Object> map1 = new HashMap<>();
map1.put("type", 1);
list.add(map1);
}
nineGridAdapter.notifyDataSetChanged();
}
}
(2)NineGridAdapter.java 自定义一个RecyclerView适配器
public class NineGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private OnAddPicturesListener listener;
private Context context;
private List<Map<String,Object>> list;
private List<Uri> uriLists;
private List<Object> mList;
private View inflater;
private static final int no = 0;
private static final int yes = 1;
public NineGridAdapter(Context context, List<Map<String,Object>> list){
this.context = context;
this.list = list;
}
@Override
public int getItemViewType(int position) {
int size = list.get(position).size();
if (size == 1) {
return no;
} else {
return yes;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == no) {
inflater = LayoutInflater.from(context).inflate(R.layout.item_add, parent, false);
RecyclerView.ViewHolder ViewHolder = new NineGridAdapter.ViewHolder(inflater);
return ViewHolder;
} else {
inflater = LayoutInflater.from(context).inflate(R.layout.item_gallery, parent, false);
RecyclerView.ViewHolder showHolder = new NineGridAdapter.showHolder(inflater);
return showHolder;
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
int viewType=getItemViewType(position);
if(viewType==no)
{
ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.add_Image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onAdd();
}
});
}
else if(viewType==yes)
{
showHolder showHolder = (NineGridAdapter.showHolder) holder;
//在item中展示选择的图片
Glide.with(context).load(list.get(position).get("uri")).into(showHolder.show_image);
//浏览
showHolder.show_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "展示图片", Toast.LENGTH_SHORT).show();
listener.item(position, list);
}
});
//新增删除
showHolder.delete_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.delete(position);
}
});
}
}
public void remove(int position) {
list.remove(position);
notifyItemRemoved(position);
//刷新下标,不然下标就重复
notifyItemRangeChanged(position, list.size());
}
@Override
public int getItemCount() {
/* if (mediaDtoList == null || mediaDtoList.size() == 0) {
return 1;
} else {
return this.mediaDtoList.size() >= picMax ? picMax : this.mediaDtoList.size() + 1;
}*/
return list.size();
}
public void showImage(Context context, int position, List<Map<String, Object>> mList) {
Intent intent = new Intent(context, PhotoViewActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("position", position);
bundle.putSerializable("tbItemBeanList", (Serializable) mList);
intent.putExtras(bundle);
context.startActivity(intent);
}
//添加
class ViewHolder extends RecyclerView.ViewHolder {
RelativeLayout add_Image;
public ViewHolder(@NonNull View itemView) {
super(itemView);
add_Image = itemView.findViewById(R.id.add_newsImage);
}
}
//展示
class showHolder extends RecyclerView.ViewHolder{
ImageView show_image;
ImageView delete_image;
public showHolder(@NonNull View itemView) {
super(itemView);
show_image = itemView.findViewById(R.id.iv_show);
delete_image = itemView.findViewById(R.id.iv_del);
}
}
public void setOnAddPicturesListener(OnAddPicturesListener listener) {
this.listener = listener;
}
private class PicturesClickListener implements View.OnClickListener {
int position;
public PicturesClickListener(int position) {
this.position = position;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.add_newsImage:
//点击添加按钮
if (listener != null) {
listener.onAdd();
}
break;
case R.id.iv_del:
//点击删除
if (listener != null) {
listener.delete(list.size());
}
break;
case R.id.iv_show:
//点击展示
if (listener != null) {
listener.item(position, list);
}
break;
}
}
}
}
(3)OnAddPicturesListener 对接口定义添加、删除、浏览三种方法
public interface OnAddPicturesListener {
//添加
void onAdd();
//删除第几张图片
void delete(int position);
//图片点击
void item(int position, List<Map<String, Object>> list);
}
(4)PhotoViewActivity.java 图片展示页面(进行放大浏览)
public class PhotoViewActivity extends AppCompatActivity {
@BindView(R.id.iv_photoView)
ImageView photoView;
@BindView(R.id.mTvImageCount)
TextView mTvImageCount;
//点击的下标
private int currentPosition;
private transient Uri uriVideo ;
private List<Map<String, Object>> uriLists = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_view);
ButterKnife.bind(this);
//根据Intent意图 获取Bundle对象 再根据对象取出图片编号
Bundle bundle = getIntent().getExtras();
currentPosition = bundle.getInt("position", 0);
//图片集合
uriLists = (List<Map<String, Object>>) bundle.getSerializable("tbItemBeanList");
Bitmap bitmap = null;
try {
uriVideo = (Uri) uriLists.get(currentPosition).get("uri");
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uriVideo));
photoView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
大体上三步,一步一步来,中间的一些控件图片,就得你们自己去找资源了,替代一下就行,基本可以实现该功能了