九宫格选择照片

2023-11-06

一、Adapter

public class RecyclerImageAdapter extends RecyclerView.Adapter<RecyclerImageAdapter.ViewHolder> {
    public static final int TYPE_CAMERA = 1;
    public static final int TYPE_PICTURE = 2;
    private LayoutInflater mInflater;
    private List<String> list = new ArrayList<>();
    private int selectMax = 9;
    private Context context;
    private final RequestOptions options;
    /**
     * 点击添加图片跳转
     */
    private OnPickerListener mOnPickerListener;

    public void setOnPickerListener(OnPickerListener onPickerListener) {
        this.mOnPickerListener = onPickerListener;
    }

    /**
     * recyclerView设置的监听接口
     */
    public interface OnPickerListener {
        void onPicker(int position);
    }

    public RecyclerImageAdapter(Context context) {
        this.context = context;
        mInflater = LayoutInflater.from(context);
        options = new RequestOptions().placeholder(R.drawable.icon_choose_picture);
    }


    public void setSelectMax(int selectMax) {
        this.selectMax = selectMax;
    }

    public void setList(List<String> list) {
        this.list = list;
        this.notifyDataSetChanged();
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        ImageView iv_image, iv_delete;

        public ViewHolder(View view) {
            super(view);
            iv_image = view.findViewById(R.id.iv_image);
            iv_delete = view.findViewById(R.id.iv_delete);
            iv_delete.setOnClickListener(this);
            iv_image.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.iv_image:
                    mOnPickerListener.onPicker(getLayoutPosition());
                    break;
                case R.id.iv_delete:
                    list.remove(getLayoutPosition());
                    notifyItemRemoved(getLayoutPosition());
                    break;
            }
        }
    }

    @Override
    public int getItemCount() {
        if (list.size() < selectMax) {
            return list.size() + 1;
        } else {
            return list.size();
        }
    }

    public List<String> getList() {
        return list;
    }

    @Override
    public int getItemViewType(int position) {
        if (isShowAddItem(position)) {
            return TYPE_CAMERA;
        } else {
            return TYPE_PICTURE;
        }
    }

    /**
     * 创建ViewHolder
     */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = mInflater.inflate(R.layout.item_add_pic, viewGroup, false);
        final ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    private boolean isShowAddItem(int position) {
        int size = list.size() == 0 ? 0 : list.size();
        return position == size;
    }

    /**
     * 设置值
     */
    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int position) {

        //少于9张,显示继续添加的图标
        if (getItemViewType(position) == TYPE_CAMERA) {
            viewHolder.iv_image.setImageBitmap(BitmapFactory.decodeResource(context.getResources(),R.drawable.icon_choose_picture));
            viewHolder.iv_delete.setVisibility(View.INVISIBLE);
        } else {
            String imgUrl = list.get(position);
            Glide.with(context).load(new File(imgUrl)).apply(options).into(viewHolder.iv_image);
            viewHolder.iv_delete.setVisibility(View.VISIBLE);
        }
    }
}

二、Activity

public class SelectPhotoActivity extends MyTakePhotoActivity {
    private RecyclerView rv_photo;
    private RecyclerImageAdapter mRecyclerAdapter;
    private Uri imageUri;
    private ArrayList<String> imgUrlLists = new ArrayList<>();// 图片压缩后的地址

    @Override
    public int initLayout() {
        return R.layout.activity_select_photo;
    }

    @Override
    public void initData() {
        rv_photo = findViewById(R.id.rv_photo);
        rv_photo.setLayoutManager(new GridLayoutManager(this, 3));
        rv_photo.addItemDecoration(new MyPaddingDecoration(this));
        mRecyclerAdapter = new RecyclerImageAdapter(this);
        mRecyclerAdapter.setSelectMax(9);
        rv_photo.setAdapter(mRecyclerAdapter);
        mRecyclerAdapter.setOnPickerListener(position -> {
            if (imgUrlLists.size() != position) {
                String[] strings = new String[imgUrlLists.size()];
                imageBrower(position, imgUrlLists.toArray(strings));
            } else {
                showPopupWindow();
            }
        });
    }

    private void imageBrower(int position, String[] urls) {
        Intent intent = new Intent(this, ImagePagerActivity.class);
        intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_URLS, urls);
        intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_INDEX, position);
        this.startActivity(intent);
    }

    /**
     * 设置照片的一些配置
     */
    private void photoConfig() {
        File file = new File(Environment.getExternalStorageDirectory(), "/napp_base/" + System.currentTimeMillis() + ".jpg");
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        imageUri = Uri.fromFile(file);
        /**
         * 压缩配置
         * 设置压缩规则,最大300kb
         * enableReserveRaw是否保存原图
         */
        getTakePhoto().onEnableCompress(new CompressConfig.Builder().setMaxSize(300 * 1024).enableReserveRaw(false).create(), false);
    }

    @Override
    public void takeSuccess(TResult result, int id) {
        super.takeSuccess(result, id);
        ArrayList<TImage> images = result.getImages();
        for (int i = 0; i < images.size(); i++) {
            imgUrlLists.add(images.get(i).getCompressPath());
        }
        mRecyclerAdapter.setList(imgUrlLists);
    }

    @Override
    public void takeFail(TResult result, String msg) {
        super.takeFail(result, msg);
    }

    @Override
    public void takeCancel() {
        super.takeCancel();
    }


    /**
     * 弹出选择
     */
    private void showPopupWindow() {
        TakePhotoPopWindow popupWindow = new TakePhotoPopWindow(this);
        String[] str = {"拍照", "从相册中选择"};
        popupWindow.showPopupWindowForFoot(str, (text, position) -> {
            switch (position) {
                case 0://拍照
                    photoConfig();
                    getTakePhoto().onPickFromCapture(imageUri);
                    break;
                case 1://相册
                    photoConfig();
                    getTakePhoto().onPickMultiple(9 - mRecyclerAdapter.getList().size());
                    break;
            }
        });
    }

    public class MyPaddingDecoration extends RecyclerView.ItemDecoration {
        private int divider;

        public MyPaddingDecoration(Context context) {
            //即你要设置的分割线的宽度 --这里设为10dp
            divider = context.getResources().getDimensionPixelSize(R.dimen.divider);
        }

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
//        outRect.left = divider;  //相当于 设置 left padding
//        outRect.top = divider;   //相当于 设置 top padding
//        outRect.right = divider; //相当于 设置 right padding
            outRect.bottom = divider;  //相当于 设置 bottom padding
        }
    }
}

三、布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_photo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="15dp"
        android:overScrollMode="never"
        android:visibility="visible" />

</LinearLayout>

四、引用工程

TakePhoto-master

五、资源文件

资源链接

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

九宫格选择照片 的相关文章

  • 提交form表单 报错:POST http://localhost:8080/user/login 404 原因及解决方法

    原因 1 input没有设置name属性 jquery获取不到 更新 文章里边举得例子 稍微有点不恰当 button 千万不要用input标签 要不然servlet就会从它上获取数据 结果还会报错 报这种错误 说明jquery库中的方法 运
  • 前端的对决:React的JSX与Vue的templates

    请点击此处输入图片描述 React js和Vue js是这个星球上最流行的JavaScript库 它们都很强大 相对来说很容易获取和使用 React和Vue的共性 使用虚拟DOM 提供响应式视图组件 专注于开发过程中的一个方面 目前集中在视
  • 因为git忽略大小写而浪费的一天一夜修复bug

    改了多语言文件名 将小写改为大写 vite项目重新发布后 测试环境报找不到这个文件的错误 心路历程分析 1 第一反应是缓存问题 后清除浏览器缓存 vite项目版本号改动 强制清除vite包缓存 使用 force命令 报错 需要再研究一下 都
  • 【刷题笔记】——day.4 路径问题总结

    学习目标 用于记录每日刷的题目为了明年的python组蓝桥杯做准备 今天是打卡的第四天 冲 原题一 不同路径 题目描述 一个机器人位于一个 m x n 网格的左上角 机器人每次只能向下或者向右移动一步 机器人试图达到网格的右下角 问总共有多
  • Windows IntelliJ IDEA 快捷键终极大全

    目录 自动代码 查询快捷键 其他快捷键 调试快捷键 重构 十大Intellij IDEA快捷键 1 智能提示 2 重构 3 代码生成 4 编辑 5 查找打开 6 其他辅助 太难割舍 前三名并列吧 自动代码 常用的有fori sout psv
  • docker部署的mysql容器数据插入中文乱码问题及其衍生问题

    docker部署的mysql容器数据插入中文乱码问题及其衍生问题 前言 笔者使用的mysql时部署在docker容器中的 版本是5 5部分内容参考了https blog csdn net weixin 42168191 article de
  • node.js的文件操作常用命令

    在学习node的时候我们会经常用到一些文件的操作 所以来总结一些常用的文件操作 首先用文件操作之前要导入nodejs的文件模块 const fs require fs 写文件的模块 下面就是nodejs的一些常用文件命令 很详细的注解了 w
  • Web渗透测试---Web TOP 10 漏洞

    文章目录 前言 一 注入漏洞 二 跨站脚本 xss 漏洞 三 文件上传漏洞 四 文件包含漏洞 五 命令执行漏洞 六 代码执行漏洞 七 XML外部实体 XXE 漏洞 八 反序列化漏洞 九 SSRF漏洞 十 解析漏洞 前言 常见的漏洞有注入漏洞
  • 蓝桥杯-第九届决赛——版本分支

    标题 版本分支 小明负责维护公司一个奇怪的项目 这个项目的代码一直在不断分支 branch 但是从未发生过合并 merge 现在这个项目的代码一共有N个版本 编号1 N 其中1号版本是最初的版本 除了1号版本之外 其他版本的代码都恰好有一个
  • 边界类、控制类、实体类

    UML中类有三种主要的版型 边界类 控制类和实体类 引入边界类 控制类及实体类的概念有助于分析和设计人员确定系统中的类 边界类位于系统与外界的交界处 窗体 报表 以及表示通讯协议的类 直接与外部设备交互的类 直接与外部系统交互的类等都是边界
  • 从MSVC习惯到QTCreator工程pro文件实用介绍

    对于用惯VS的各位 一定想QT Creator也能用的那么溜 其实关键在 pro 从MSVC习惯到QTCreator工程pro文件实用介绍 首先建立一个相当于sln的工程文件 TEMPLATE subdirs SUBDIRS raknet
  • shell脚本—— case语句+函数

    文章目录 一 case语句 语法格式 示例 二 函数 函数定义 将函数定义到用户的环境变量中 在脚本中调用函数 示例 综合练习 环境准备 配置免密登录 编写脚本 一 case语句 case为多选择语句 可以用case语句匹配一个值与一个模式
  • 【 PMU】信号生成、采样、分割、估计器应用和误差计算(Matlab代码实现)

    个人主页 研学社的博客 欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 P
  • [C语言]柔性数组

    目录 1 柔性数组 2 柔性数组的特点 3 柔性数组的使用 1 柔性数组 柔性数组存在于结构体中 当结构体最后一个成员元素为一个未知大小的数组 则称其为柔性数组 struct s int a char arr 柔性数组 2 柔性数组的特点
  • 在Windwos系统下使用Putty登录SSH服务器

    远程登录服务器 以便使用主机资源或者管理维护主机 常见的远程登录方式主要有 rsh telnet ssh vnc等 下面主要介绍使用Putty登录SSH服务器 前提条件 下载Putty 下载地址 http www chiark greene
  • vs2017编译vs2013的duilib

    一 安装svn后桌面右键svn检出 注意URL为 https github com duilib duilib git 之前duilib是托管在Google code 现在谷歌那个导不出来了 目前放在GitHub上了 二 vs自动升级平台工
  • 2021年 Windows10 环境下使用WSL和Docker 配置深度学习环境- 可使用任意版本的 Ubuntu+CUDA image 以及踩坑记录

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 Windows10 环境下使用WSL2和Docker 配置深度学习环境以及踩坑记录 使用 Ubuntu 18 04 Cuda 前言 一 在Windows10 上配置WSL2
  • Spring与MyBatis 整合时关于SqlSessionTemplate的用法和映射器的使用(MapperFactoryBean,MapperScannerConfigurer)

    本文主讲在spring与MyBatis 整合时关于SqlSessionTemplate的用法和映射器的使用 如若转载请注明出处 谢谢 https mp csdn net postedit 82257281 首先要知道SqlSessionTe
  • JAVA里面的“指针”(对象引用)

    众所周知 在java里面是没有指针的 那为何此处还要说java里面的 指针 呢 我们知道在C C 中 指针是指向内存中的地址 该地址就是存储变量的值 该地址所存储的变量值是 公有 的 此处的 公有 是对于拥有该地址的变量而言 它们都可以访问
  • 原生JS实现ajax详解

    原生js写ajax可以类比打电话 打电话分下面4步 1 拿出手机 2 拨号 3 说话 4 听对方说话 ajax也分下面4步 1 创建ajax对象 2 连接到服务器 3 发送请求 告诉服务器我要什么文件 4 接收返回值 下面是原生js写aja

随机推荐

  • 使用MathJax在博客园里添加数学公式

    简单来说就是直接使用MathJax提供的JavaScript文件来生成数学公式 具体来说就是在页首加入粘贴如下JavaScript代码
  • 一文学会使用MethodHandle

    MethodHandle方法句柄 第一次看到这个类是在看Mybatis源码 自以为对java很熟悉 反射很熟的我 看到这个API竟然不知道是干什么用的 因此花了很多时间去了解这个东西 发现网上的资料是很少的 特别是对刚接触这个api的人很不
  • LeetCode_6_树----对称二叉树

    大家好 我是你们的好朋友 大数据老虾 相遇是缘 既然来了就拎着小板凳坐下来一起唠会儿 如果在文中有所收获 请别忘了一键三连 你的鼓励 是我创作的动力 废话不多说 直接开干 吧 先别急着走 文末干货 记得拎着小板凳离开的时候也给它顺走 树 对
  • 以太网ARP测试实验

    1 1 ARP测试整体框架 当上位机发送ARP请求时 FPGA返回ARP应答数据 当按下FPGA的触摸按键时 FPGA发送ARP请求 上位机返回ARP应答数据 PLL时钟对eth rxc的输入时钟进行相位调整 GMII TO RGMI 模块
  • uniapp微信小程序订阅消息发送服务通知

    版权声明 本文为博主原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接和本声明 本文链接 https blog csdn net qq 44718932 article details 126130702 uniap
  • 爬虫发送带headers报错内容为ValueError: too many values to unpack (expected 2)

    这个是我报错的代码 author li lee import requests 变量url接收访问地址 url http www baidu com 加headers 将浏览器的用户代理 写到headers中 用于重置User Agent
  • 《C++ Primer Plus 第六版》编程练习参考答案(第四章)

    第四章 第一题 include
  • NativeWindow 妙用,截取windows消息

    namespace System Windows Forms using System using System ComponentModel using System Drawing using System Drawing Design
  • linux设置VT模式,android – 如何在Linux上的BIOS和KVM模块中启用VT-x?

    KVM Installation I referred the instructions from Ubuntu community documentation page to get KVM installed To see if you
  • C#使用FFmpeg的总结

    上篇文章提到FFmpeg解决项目中视频和语音问题 说道C 和FFmpeg不得不提的2个类库 1 Xabe FFmpeg 简单查看了下源码和demo 发现基于ffmpeg exe的命令行参数进行处理 2 FFmpeg AutoGen 把C语言
  • sqlserver日期格式转换yyyymmdd_8个案例,玩转时间合并转换运算和提取,3个函数就够了...

    大家好 上一篇文章分享了关于日期时间的提取函数和判定 讲解了如何对日期是否是周末进行判定 今天继续分享关于日期时间方面的合并 提取方面的剩余内容 以及如何根据身份证号求算年龄 如何根据入职时间计算员工工龄两个案例 那么就让我们开始吧 操作一
  • jmeter errstr :“unsupported field type for multipart.FileHeader“

    在使用jmeter测试接口的时候 提示errstr unsupported field type for multipart FileHeader 如图所示 这是因为我们 在HTTP信息头管理加content type参数有问题 直接在HT
  • VS社区版许可证过期更新

    VS社区版许可证过期更新 VS社区版是免费使用的 然而会有许可证过期的问题 这时候就需要登录 再进行更新许可证 在登录时卡顿了一天还没有解决问题 我们无法下载许可证 请检查你的网络连接或代理设置 查找方案 有一个方案比较普遍 1 在VS安装
  • brk(), sbrk() 用法详解

    贴上原文地址 好不容易找到了 brk sbrk 改变数据段长度 brk sbrk 的声明如下 include
  • 机器学习实验 - MeanShift聚类

    目录 一 报告摘要 1 1 实验要求 1 2 实验思路 1 3 实验结论 二 实验内容 2 1 方法介绍 2 2 实验细节 2 2 1 实验环境 2 2 2 实验过程 2 2 3 实验与理论内容的不同点 2 3 实验数据介绍 2 4 评价指
  • Spring5 框架 详解 (一) ---- IOC控制反转

    Spring5 框架 spring 框架概述 IOC 容器 1 什么是 IOC 2 IOC底层原理 IOC 过程 IOC 接口 IOC 操作 Bean 管理 IOC 操作 Bean 管理 xml 注入其他类型属性 IOC 操作 Bean 管
  • PHP底层工作原理

    原文地址 http www cnblogs com phphuaibei archive 2011 09 13 2174927 html 最近搭建服务器 突然感觉lamp之间到底是怎么工作的 或者是怎么联系起来 平时只是写程序 重来没有思考
  • Java中数据类型详解

    文章目录 一 数据类型的作用 二 两种数据类型 1 基本数据类型 1 第一类 整数型 2 第二类 浮点型 3 第三类 布尔型 4 第四类 字符型 2 引用数据类型 1 类 2 数组 3 接口 三 基本数据类型之间的转化 一 数据类型的作用
  • Vue 项目如何实现一个全局菜单搜索框

    个人主页 山山而川 xyj 作者简介 前端领域新星创作者 专注于前端各领域技术 共同学习共同进步 一起加油 系列专栏 Vue 系列 学习格言 与其临渊羡鱼 不如退而结网 目录 前言 一 过滤路由 二 搜索框展示路由 三 雏形出现但有缺陷 四
  • 九宫格选择照片

    一 Adapter public class RecyclerImageAdapter extends RecyclerView Adapter