zoukankan      html  css  js  c++  java
  • Android-----RecyclerView绑定点击以及长按监听事件

    RecyclerView简介:

      可以理解 RecyclerView 是 ListView 的升级版,更加灵活,同时由于封装了 ListView 的部分实现,导致其使用更简单,结构更清晰。

      它直接提供了回收复用的功能,虽然 ListView 我们也可以自己实现 ViewHolder 以及 convertView 进行优化,但是在 RecyclerView 中,它直接封装了 ViewHolder 的回收复用,也就是说 RecyclerView 将 ViewHolder 标准化,我们不再需要面向 view ,而是直接面向 ViewHolder 编写实现我们需要的 Adapter,这样一来,逻辑结构就变得非常清晰。

    当然,说到 RecyclerView 的优点,就不得不提它的 插拔式 的体验,高度解耦:

    • 布局(显示方式):可通过LayoutManager(LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager )设置;
    • 分割线:通过 ItemDecoration 实现
    • Item 增删动画:通过 ItemAnimator
    • ViewHolder 的创建和绑定:通过实现 Adapter

    除此之外,还需要额外提一下关于点击事件的问题,RecyclerView 本身是不提供点击、长按事件的,而隔壁的 ListView 稳稳支持。对此,可能刚接触 RecyclerView 的同学会疯狂吐槽,怎么作为升级版的 RecyclerView 在这一点上还不如旧版呢?

    情况真的是这样么?

    显然不是。

    ListView 中对于点击事件的处理,其实是有很大弊端的,它的 setOnItemClickListener() 方法是为子项注册点击事件,这就导致只能识别到这一整个子项,对于子项中的组件比如按钮就束手无策了。为此,RecyclerView 直接放弃了这个为子项注册点击事件的监听方法,所有点击事件都有具体 View 去注册,好处显而易见,我可以按需为组件注册点击事件,不存在点击不到的组件

    下面就来为我们的RecyclerView注册绑定点击、长按事件 

     注意:下例使用的是我在工作过程中的一些功能实例,数据提交的可自行删除!!!(博主懒删直接整个实例拷贝过来)

    新建点击接口 ClickListener :
    fileName 是点击后我们要用到或者想要的数据,如果传入适配器的是数组,建议返回数组的单位数据
    public interface PhotoClickListener {
    
        public void onPhotoClick(RecyclerView parent , View view , String fileName );
    
    }
    新建长按接口 LongClickListener :
    public interface PhotoLongClickListener {
    
        public void onPhotoLongClick(RecyclerView parent , View view , String fileName);
    
    }
    我们的主视图布局 main.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.hsjgappzjj.DataUploadActivity">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimaryLight"
            android:orientation="vertical" >
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="15dp"
                android:layout_marginTop="15dp"
                android:text="非工况法材料上传"
                android:textColor="#FFFFFF"
                android:textSize="25dp" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:orientation="horizontal"
            android:gravity="center">
    
            <TextView
                android:id="@+id/text_tips"
                android:layout_width="0dp"
                android:layout_height="50dp"
                android:layout_weight="1"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:text="审核状态:"
                android:textColor="@color/white_overlay"
                android:textSize="20dp" />
    
            <Spinner
                android:id="@+id/resultState"
                android:layout_width="0dp"
                android:layout_height="50dp"
                android:layout_marginLeft="5dp"
                android:layout_weight="1"
                android:background="@drawable/btn_selector"
                android:textColor="@color/red_overlay" />
    
        </LinearLayout>
    
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <android.support.v7.widget.RecyclerView
                    android:id="@+id/photoRecyclerView"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
                </android.support.v7.widget.RecyclerView>
                <Button
                    android:id="@+id/photoUploadBtn"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@drawable/btn_selector"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="10dp"
                    android:layout_marginTop="5dp"
                    android:layout_marginBottom="5dp"
                    android:textColor="@color/red_overlay"
                    android:text="提交"/>
            </LinearLayout>
        </ScrollView>
    
    
    </LinearLayout>
    RecyclerView 自定义适配器:
    public class DataUploadAdapter extends RecyclerView.Adapter<DataUploadAdapter.myViewHolder>
            implements View.OnClickListener , View.OnLongClickListener{
    
        private Context context;
        private RecyclerView recyclerView;
        private String Jylsh;
        private String[] photoNames;private PhotoClickListener photoClickListener = null;
        private PhotoLongClickListener photoLongClickListener = null;
    
        /**【构造函数】**/
        public DataUploadAdapter(Context context , String Jylsh , RecyclerView recyclerView){
            this.context = context;
            this.recyclerView = recyclerView;
            this.Jylsh = Jylsh;
            initPhotoData();
        }
    
        /**【点击监听】**/
        public void setPhotoClickListener(PhotoClickListener clickListener){
            this.photoClickListener = clickListener;
        }
    
        /**【长按监听】**/
        public void setPhotoLongClickListener(PhotoLongClickListener longClickListener){
            this.photoLongClickListener = longClickListener;
        }
    
        @Override
        public myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.dataupload_item,parent,false);
            final myViewHolder holder = new myViewHolder(view);
            /**【点击事件】**/
            view.setOnClickListener(this);
            /**【长按事件】**/
            view.setOnLongClickListener(this);
            return holder;
        }
    
        /**【子项赋值】**/
        @Override
        public void onBindViewHolder(myViewHolder holder, int position) {
            holder.photoNameText.setText(photoNames[position]);
            holder.uploadStates.setText("已上传");
            String filePath = Environment.getExternalStorageDirectory() + "/" + "MyVehPhoto/";          //照片目录
            String fileName = Jylsh + "/" + photoNames[position] +".jpg";                               //照片流水号下的照片名称
            //Log.e("完整照片目录",filePath + fileName);
            Bitmap imgBitmap = BitmapFactory.decodeFile(filePath + fileName);
            holder.takePhotoImg.setImageBitmap(imgBitmap);
        }
    
        /**【子项总数量】**/
        @Override
        public int getItemCount() {
            return photoNames.length;
        }
    
        /**【点击事件】**/
        @Override
        public void onClick(View view) {
            TextView textView = view.findViewById(R.id.photoNameText);
            String fileName = textView.getText().toString() + "";
            if (photoClickListener != null){
                photoClickListener.onPhotoClick(recyclerView , view ,fileName);
            }
        }
    
        /**【长按事件】**/
        @Override
        public boolean onLongClick(View view) {
            TextView textView = view.findViewById(R.id.photoNameText);
            String fileName = textView.getText().toString() + "";
            if (photoLongClickListener != null){
                photoLongClickListener.onPhotoLongClick(recyclerView , view , fileName);
            }
            return false;
        }
    
        /**【自定义类中的组件】**/
        class myViewHolder extends RecyclerView.ViewHolder{
            private ImageView takePhotoImg;
            private TextView photoNameText , uploadStates;
            public myViewHolder(View itemView) {
                super(itemView);
                takePhotoImg = itemView.findViewById(R.id.takePhotoImg);
                photoNameText = itemView.findViewById(R.id.photoNameText);
                uploadStates = itemView.findViewById(R.id.uploadStates);
            }
        }
    
        /**【获取照片名字以及上传状态】**/
        private void initPhotoData(){
            SharedPreferences photoData = context.getSharedPreferences("photoData", 0);
            String photoName = photoData.getString("photoNames","");
            if (!photoName.equals("")){
                photoNames = photoName.split(",");
            }
        }
    }
    每一个子项布局 dataupload_item.xml :
    <?xml version="1.0" encoding="utf-8"?>
    <!--    数据展示页面子项布局    -->
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:id="@+id/uploadLayout"
        android:orientation="vertical"
        android:layout_marginTop="2dp"
        android:layout_marginBottom="3dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:gravity="center">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >
    
            <!--  android:src="@drawable/login_icon"  -->
            <ImageView
                android:id="@+id/takePhotoImg"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/bootstrap_gray_dark">
            </ImageView>
    
            <TextView
                android:id="@+id/photoNameText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:textSize="15sp"
                android:textColor="@color/white_overlay"
                android:layout_alignBottom="@id/takePhotoImg"
                android:text="照片名称"/>
    
            <TextView
                android:id="@+id/uploadStates"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:gravity="center"
                android:textColor="@color/red_overlay"
                android:textSize="15sp"
                android:text="上传状态"/>
        </RelativeLayout>
    
    </LinearLayout>
    主要处理代码 main.java
    public class DataUploadActivity extends BaseActivity {
    
        private RecyclerView recyclerView;
        private Button photoUploadBtn;
        private DataUploadAdapter adapter;
        private String clickFileName , photoName;
        private String Jylsh ; //"20210202008"
        private String ip , jkxlh;
        private Spinner resultState;
        private String status = "1" , selItemStr = "";  //审核状态
        private String uploadStatus = "";
    
        private Q11Domain theinformation;       //车辆信息项目
    
        private static final int MSG_SUCCESS = 2087;
        private static final int MSG_SHOW = 2088;
        private static final int MSG_DISMISS = 2089;
        private static final int MSG_ERROR = 2090;
        private ProgressDialog builder = null;
        private Message message;
    
        @SuppressLint("HandlerLeak")
        private Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                if (msg.what == MSG_SHOW) {
                    if (builder == null){
                        builder = new ProgressDialog(DataUploadActivity.this);
                        builder.setMessage(msg.obj.toString());
                        builder.setCancelable(false);
                        builder.show();
                    }else {
                        builder.show();
                    }
                }else if (msg.what == MSG_DISMISS) {
                    if (builder != null){
                        builder.dismiss();
                    }
                }else if (msg.what == MSG_ERROR) {
                    initAdapter();
                    DialogTool.AlertDialogShow(DataUploadActivity.this, msg.obj.toString());
                }else if (msg.what == MSG_SUCCESS){
                    initAdapter();
                    ToastUtil.showAnimaToast(msg.obj.toString());
                }
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            requestWindowFeature(Window.FEATURE_NO_TITLE);// 隐藏标题
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
            super.onCreate(savedInstanceState);
            setContentView(R.layout.data_upload);
    
            SharedPreferences photoData = getSharedPreferences("photoData", 0);
            SharedPreferences.Editor editor = photoData.edit();
            String photoNames = "申请图片,佐证材料1,佐证材料2,佐证材料3,佐证材料4";
            editor.putString("photoNames",photoNames);
            //String uploadStates = "1,0,1,0,1";
            //editor.putString("uploadStates",uploadStates);
            editor.commit();
    
            initAdapter();
        }
    
        /**【适配器初始化】**/
        private void initAdapter(){
    
            theinformation = (Q11Domain) getIntent().getExtras().getSerializable("informationsObj");            //车辆信息
            if (theinformation != null){
                Jylsh = theinformation.getJylsh();
            }else {
                Jylsh = "20210202008";
            }
            createUploadStatusFile(Jylsh , "");     //创建初始化记录照片上传状态
    
            SharedPreferences preferences = getSharedPreferences("cs_setup", 0);
            ip = preferences.getString("IP", "");
            jkxlh = preferences.getString("JKXLH", "");
    
            resultState = findViewById(R.id.resultState);
            final String [] selectItems = {"审核通过","审核不通过"};
            ArrayAdapter<String> selItem = new ArrayAdapter<>(this,android.R.layout.simple_list_item_single_choice,selectItems);
            resultState.setAdapter(selItem);
            resultState.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    selItemStr = selectItems[i];
                    if (selItemStr.equals("审核不通过")){
                        status = "2";
                    }else if (selItemStr.equals("审核通过")){
                        status = "1";
                    }
                }
                @Override
                public void onNothingSelected(AdapterView<?> adapterView) {
    
                }
            });
    
            /**【网格布局】**/
            recyclerView = findViewById(R.id.photoRecyclerView);
            GridLayoutManager gridlayout = new GridLayoutManager(this,2);
            recyclerView.setLayoutManager(gridlayout);
    
            adapter = new DataUploadAdapter(DataUploadActivity.this,Jylsh,recyclerView);
            /**【点击事件】**/
            adapter.setPhotoClickListener(new PhotoClickListener() {
                @Override
                public void onPhotoClick(RecyclerView parent, View view, String fileName) {
                    File file = new File(createFile(Jylsh , fileName));
                    if (!file.exists()){        //判断是否存在照片
                        ToastUtil.showAnimaToast("照片未拍摄,请长按拍照!");
                        return;
                    }
                    Intent intentClick = new Intent(DataUploadActivity.this,ImageShowActivity.class);
                    clickFileName = createFile(Jylsh , fileName);           //完整的文件名
                    photoName = fileName;
                    intentClick.putExtra("photoType", fileName);                    //当前照片名称
                    intentClick.putExtra("imageFullPath", clickFileName);           //照片完整目录和名称
                    startActivity(intentClick);
                }
            });
            /**【长按事件】**/
            adapter.setPhotoLongClickListener(new PhotoLongClickListener() {
                @Override
                public void onPhotoLongClick(RecyclerView parent, View view, String fileName) {
                    Toast.makeText(DataUploadActivity.this,fileName,Toast.LENGTH_LONG).show();
                    Intent intentLongClick = new Intent("android.media.action.IMAGE_CAPTURE");
                    clickFileName = createFile(Jylsh , fileName);           //完整的文件名
                    photoName = fileName;
                    File file = new File(clickFileName);                    //file:新建一个文件
                    Uri uri = Uri.fromFile(file);                           //将File文件转换成Uri以启动相机程序
                    intentLongClick.putExtra(MediaStore.EXTRA_OUTPUT,uri);  //指定图片输出地址
                    startActivityForResult(intentLongClick,88);
                }
            });
            recyclerView.setAdapter(adapter);
    
            photoUploadBtn = findViewById(R.id.photoUploadBtn);
            photoUploadBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.e("审核结果",status);
                    request02C31();
                    Toast.makeText(DataUploadActivity.this,"提交数据",Toast.LENGTH_LONG).show();
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            initAdapter();
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == Activity.RESULT_OK){
                switch (requestCode){
                    case 88:
                        FileInputStream inputStream = null;
                        try {
                            inputStream = new FileInputStream(clickFileName);
                            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);    //获取指定目录下保存的位图
                            OutputStream os = new FileOutputStream(clickFileName);
                            bitmap.compress(Bitmap.CompressFormat.JPEG,50,os);
                            os.flush();
                            os.close();
                            inputStream.close();
                            photoUpload(clickFileName ,photoName);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                }
            }
        }
    
        public void sendMessages(int msgNumber, String Mesg) {
            message = new Message();
            message.what = msgNumber;
            message.obj = Mesg;
            handler.sendMessage(message);
        }
    
        /**【创建文件目录,并返回完整的文件路径和名称】**/
        private String createFile(String Jylsh , String fileName){
            String filePath = Environment.getExternalStorageDirectory() + "/MyVehPhoto/" + Jylsh + "/"; //照片目录
            File folder = new File(filePath);
            if (!folder.exists()){
                folder.mkdirs();
            }
            String name = filePath + fileName + ".jpg";
            //Log.e("完整的照片名称",name);
            return name;
        }
    
        /**【获取照片字符串】**/
        private String getPhotoData(String fileName){
            File file = new File(fileName);
            String photo = "";
            if (!file.exists()){            //如果图片不存在
                return photo;
            }
            Bitmap bitmap = BitmapFactory.decodeFile(fileName);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG,80,outputStream);
            byte [] bytes = outputStream.toByteArray();
            photo = Base64.encodeToString(bytes,Base64.DEFAULT);
            Log.e("图片压缩64位字符串",photo);
            return photo;
        }
    
        /**【上传照片】**/
        private void photoUpload(final String updateFileName , final String photoName){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    sendMessages(MSG_SHOW , "正在上传中,请稍等。。。");
                    String photoData = getPhotoData(updateFileName);  //获取图片base64字符串数据
                    String photoXML = UnXmlTool.uploadPhotoXml(Jylsh,photoData,getPhotoName(photoName));
                    String photoInfo = ConnectMethods.connectWebService(ip, StaticValues.queryObject, jkxlh, "02C32", photoXML,
                            StaticValues.queryResult, StaticValues.timeoutThree, StaticValues.numberFive);
                    Log.e("照片上传返回结果",photoInfo);
                    List<Code> codeList = XMLParsingMethods.saxcode(photoInfo);
                    if (codeList.get(0).getCode().equals("1")){
                        handler.sendEmptyMessage(MSG_DISMISS);
                        String fileName = Environment.getExternalStorageDirectory()+"/MyVehPhoto/"+Jylsh+"/uploadStatus.txt";
                        File fileStatus = new File(fileName);
                        if (fileStatus.exists()){       //判断记录状态文件是否存在
                            String content = DocumentTool.readFileContent(fileName);
                            if (!content.equals("")){
                                uploadStatus = volidateFileData(photoName,photoData,content);
                                createUploadStatusFile(Jylsh , uploadStatus);
                            }
                        }
                        sendMessages(MSG_SUCCESS , "照片上传成功!");
                    }else{
                        handler.sendEmptyMessage(MSG_DISMISS);
                        sendMessages(MSG_ERROR , codeList.get(0).getMessage());
                    }
                }
            }).start();
        }
    
        /**【提交数据】**/
        private void request02C31(){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    sendMessages(MSG_SHOW , "正在上传中,请稍等。。。");
                    String photoXML = UnXmlTool.get02C31XML(Jylsh,status,"","","","","");
                    String photoData = ConnectMethods.connectWebService(ip, StaticValues.queryObject, jkxlh, "02C31", photoXML,
                            StaticValues.queryResult, StaticValues.timeoutThree, StaticValues.numberFive);
                    List<Code> codeList = XMLParsingMethods.saxcode(photoData);
                    if (codeList.get(0).getCode().equals("1")){
                        handler.sendEmptyMessage(MSG_DISMISS);
                        sendMessages(MSG_SUCCESS , "照片上传成功!");
                    }else{
                        handler.sendEmptyMessage(MSG_DISMISS);
                        sendMessages(MSG_ERROR , codeList.get(0).getMessage());
                    }
                }
            }).start();
        }
    
        /**【创建文件记录照片上传状态】**/
        private void createUploadStatusFile(String lsh , String updateContent){
            try {
                String fileName = Environment.getExternalStorageDirectory()+"/MyVehPhoto/"+lsh+"/uploadStatus.txt";
                File fileStatus = new File(fileName);
                if (!fileStatus.exists()) {     //文件不存在时
                    fileStatus.createNewFile();
                    updateContent = "apply:0-evidenceOne:0-evidenceTwo:0-evidenceThree:0-evidenceFour:0";
                    DocumentTool.writeData(fileStatus.getPath() , updateContent);
                }else{
                    if (!updateContent.equals("")){
                        DocumentTool.writeData(fileStatus.getPath() , updateContent);
                    }
                }
                String fileContent = DocumentTool.readFileContent(fileName);
                Log.e("uploadStatus的文件内容",fileContent);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**【判断是哪张照片的数据、更新照片上传状态】**/
        private String volidateFileData(String fileName , String photoData ,String content){
            String[] listStatus = content.split("-");   //"apply:0"
            String result = "";
            if (fileName.contains("申请图片")){
                if (!photoData.equals("")){
                    listStatus[0] = "apply:1";
                }
            }else if (fileName.contains("佐证材料1")){
                if (!photoData.equals("")){
                    listStatus[1] = "evidenceOne:1";
                }
            }else if (fileName.contains("佐证材料2")){
                if (!photoData.equals("")){
                    listStatus[2] = "evidenceTwo:1";
                }
            }else if (fileName.contains("佐证材料3")){
                if (!photoData.equals("")){
                    listStatus[3] = "evidenceThree:1";
                }
            }else if (fileName.contains("佐证材料4")){
                if (!photoData.equals("")){
                    listStatus[4] = "evidenceFour:1";
                }
            }
            if (listStatus.length > 0){
                for (int i = 0 ; i < listStatus.length ; i ++){
                    result = result + listStatus[i] + "-";
                }
            }
            result = result.substring(0,result.length() - 1);
            Log.e("重新合成的数据",result);
            return result;
        }
    
        /**【生成对应的文件名:photoName】**/
        private String getPhotoName(String name){
            String result = "";
            if (name != null && !name.equals("")){
                if (name.equals("申请图片")){
                    result = "SQPIC";
                }else if (name.equals("佐证材料1")){
                    result = "szZP1";
                }else if (name.equals("佐证材料2")){
                    result = "szZP2";
                }else if (name.equals("佐证材料3")){
                    result = "szZP3";
                }else if (name.equals("佐证材料4")){
                    result = "szZP4";
                }
            }
            return result;
        }
    
    }

    看下布局结果,具体的点击事件可以自行修改,长按我用来启动手机相机拍照:

     
    到这里我要做的也完成了,有问题欢迎提出探讨指正。。。
  • 相关阅读:
    oracle 存储过程
    交错数组
    延迟加载
    js 闭包
    引用类型和值类型
    事务
    web api 之身份验证
    SQLServer中的服务器角色与数据库角色
    按照某一字段的相同值合并所对应的行的值
    VC工程中的字符集工程属性和字符编码(转)
  • 原文地址:https://www.cnblogs.com/xiobai/p/14377565.html
Copyright © 2011-2022 走看看