实现访问相册和拍摄功能,并进行动态添加、删除、浏览(思路清晰明了)

效果展示图

步骤一:导入依赖
(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();
        }

    }
}

大体上三步,一步一步来,中间的一些控件图片,就得你们自己去找资源了,替代一下就行,基本可以实现该功能了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值