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;
    }

}

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

 
到这里我要做的也完成了,有问题欢迎提出探讨指正。。。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM