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