参考:Android RecyclerView实现长按删除 recyclerview 长按多选_大猩猩的技术博客_51CTO博客
activity_file_list.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"
android:splitMotionEvents="false"
android:background="#eee"
tools:context=".FileListActivity">
<Toolbar android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#eee"
android:elevation="5dp">
<ImageButton android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:src="@drawable/backward_enable"
android:background="@null"/>
<ImageButton android:id="@+id/btn_exitCheck"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:src="@drawable/error"
android:background="@null"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_gravity="center"
android:text="录音文件列表"/>
</Toolbar>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:padding="10dp">
<androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_fl"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<androidx.cardview.widget.CardView android:id="@+id/recording_start"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginVertical="10dp"
app:cardCornerRadius="32dp"
app:cardElevation="5dp"
android:clickable="true"
app:rippleColor="#eee"
android:layout_gravity="center"
android:background="@drawable/recording_sl">
<ImageButton android:id="@+id/btn_recording_start"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:background="@drawable/recording_start" />
</androidx.cardview.widget.CardView>
<Button android:id="@+id/btn_del"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="删除"
android:textSize="12sp"
android:textColor="@color/black"
android:padding="0dp"
android:drawableTop="@drawable/rubbish_bin"
android:background="#00000000"
android:visibility="gone"/>
<Button android:id="@+id/btn_check_all"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="全选"
android:textSize="12sp"
android:textColor="@color/black"
android:padding="0dp"
android:drawableTop="@drawable/check_list"
android:background="#00000000"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
layout_item_file_list.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="120dp"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:paddingVertical="10dp"
android:paddingHorizontal="10dp"
android:layout_marginBottom="5dp"
android:id="@+id/ll_itemView"
android:background="@drawable/filelist_item_corner"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="16sp"
android:textColor="@color/black"
android:text="20240408_134401"/>
<TextView android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
android:textSize="14sp"
android:textColor="#7F7F7F"
android:text="2024/4/8"/>
<androidx.constraintlayout.helper.widget.Flow
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "horizontal"
app:constraint_referenced_ids= "tv_timeAcc, record_stop, record_start"
app:flow_verticalAlign= "center"
app:flow_wrapMode= "chain"
app:layout_constraintTop_toTopOf= "parent"/>
<TextView android:id="@+id/tv_timeAcc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toLeftOf="@+id/record_stop"
android:layout_marginRight="5dp"
android:textSize="14sp"
android:textColor="#7F7F7F"
android:text="00:00:11"/>
<androidx.cardview.widget.CardView android:id="@+id/record_stop"
android:layout_width="24dp"
android:layout_height="24dp"
app:cardCornerRadius="12dp"
android:layout_marginBottom="5dp"
android:clickable="true"
app:rippleColor="#eee"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toLeftOf="@+id/record_start"
android:background="@drawable/recording_sl"
tools:ignore="MissingConstraints">
<ImageButton
android:id="@+id/btn_record_stop"
android:layout_height="12dp"
android:layout_width="12dp"
android:layout_gravity="center"
android:background="@drawable/record_stop"/>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView android:id="@+id/record_start"
android:layout_width="24dp"
android:layout_height="24dp"
app:cardCornerRadius="12dp"
android:layout_marginBottom="5dp"
android:clickable="true"
app:rippleColor="#eee"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toLeftOf="@+id/check_box"
android:background="@drawable/recording_sl"
android:visibility="gone"
tools:ignore="MissingConstraints">
<ImageButton
android:id="@+id/btn_record_start"
android:layout_height="12dp"
android:layout_width="12dp"
android:layout_gravity="center"
android:background="@drawable/record_start"/>
</androidx.cardview.widget.CardView>
<CheckBox android:id="@+id/check_box"
android:visibility="gone"
android:layout_width="20dp"
android:layout_height="20dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="10dp">
<SeekBar android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:outlineSpotShadowColor="#ff0000"
app:layout_constraintBottom_toTopOf="@+id/tv_timeLen"
app:layout_constraintStart_toStartOf="parent"/>
<TextView android:id="@+id/tv_timeCur"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="#7F7F7F"
android:text="00:00:00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView android:id="@+id/tv_timeLen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="#7F7F7F"
android:text="00:00:11"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
FileListActivity.java
package com.example.myapplication;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.cardview.widget.CardView;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;
import android.widget.Toolbar;
import com.example.myapplication.adapter.LinearAdapter;
import com.example.myapplication.utils.Item;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
public class FileListActivity extends AppCompatActivity implements View.OnClickListener {
private String TAG = "RecordTAG";
private String [] permissions = {
android.Manifest.permission.RECORD_AUDIO,
android.Manifest.permission.MANAGE_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
};
private static int REQUEST_RECORD_AUDIO_PERMISSION = 1;
private CardView recording_start;
private ImageButton btn_recording_start, btn_exitCheck, btn_back;
private Button btn_check_all, btn_del;
private boolean checkTag = false;
private Toolbar toolbar;
private RecyclerView rv_fl;
private LinearAdapter linearAdapter = null;
private List<Item> list = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_list);
init();
}
private void init () {
if (!Environment.isExternalStorageManager()) {
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION);
recording_start = findViewById(R.id.recording_start);
btn_recording_start = findViewById(R.id.btn_recording_start);
toolbar = findViewById(R.id.toolbar);
btn_check_all = findViewById(R.id.btn_check_all);
btn_del = findViewById(R.id.btn_del);
btn_exitCheck = findViewById(R.id.btn_exitCheck);
btn_back = findViewById(R.id.btn_back);
rv_fl = findViewById(R.id.rv_fl);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
rv_fl.setLayoutManager(linearLayoutManager);
loadFiles();
recording_start.setOnClickListener(this);
btn_recording_start.setOnClickListener(this);
btn_check_all.setOnClickListener(this);
btn_del.setOnClickListener(this);
btn_exitCheck.setOnClickListener(this);
btn_back.setOnClickListener(this);
}
private void loadFiles () {
list = new ArrayList<>();
File sdCard = Environment.getExternalStorageDirectory();
File[] files = sdCard.listFiles();
Pattern pattern = Pattern.compile("^record_\\d{14}.amr$");
for (File file : files) {
if (file.isFile() && pattern.matcher(file.getName().toString()).matches()) {
list.add(new Item(file));
}
}
showData();
}
private void showData () {
if (linearAdapter == null) {
linearAdapter = new LinearAdapter(this, list);
linearAdapter.setOnLayoutChangeListener(new LinearAdapter.OnLayoutChangeListener() {
@Override
public void onLayoutChange(boolean isShow) {
if (isShow) {
btn_back.setVisibility(View.GONE);
recording_start.setVisibility(View.GONE);
btn_del.setVisibility(View.VISIBLE);
btn_exitCheck.setVisibility(View.VISIBLE);
btn_check_all.setVisibility(View.VISIBLE);
} else {
btn_back.setVisibility(View.VISIBLE);
recording_start.setVisibility(View.VISIBLE);
btn_del.setVisibility(View.GONE);
btn_exitCheck.setVisibility(View.GONE);
btn_check_all.setVisibility(View.GONE);
}
}
});
rv_fl.setAdapter(linearAdapter);
} else {
linearAdapter.setList(list);
linearAdapter.notifyDataSetChanged();
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.recording_start || v.getId() == R.id.btn_recording_start) {
Intent intent = new Intent(this, AudioActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("DOWHAT", "RECORD");
intent.putExtras(bundle);
startActivity(intent);
} else if (v.getId() == R.id.btn_check_all) {
if (!checkTag) {
linearAdapter.selectAll(true);
btn_check_all.setText("取消全选");
} else {
linearAdapter.selectAll(false);
btn_check_all.setText("全选");
}
linearAdapter.notifyDataSetChanged();
checkTag = !checkTag;
} else if (v.getId() == R.id.btn_del) {
List<Item> selectList = linearAdapter.getSelectList();
if (selectList.size() == 0) Toast.makeText(this, "您未选中任何文件~", Toast.LENGTH_SHORT).show();
for (Item item : selectList) {
File file = item.getFile();
file.delete();
}
loadFiles();
} else if (v.getId() == R.id.btn_exitCheck) {
btn_back.setVisibility(View.VISIBLE);
btn_recording_start.setVisibility(View.VISIBLE);
btn_exitCheck.setVisibility(View.GONE);
btn_del.setVisibility(View.GONE);
btn_check_all.setVisibility(View.GONE);
} else if (v.getId() == R.id. btn_back) {
finish();
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
if (grantResults.length == permissions.length
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.e("attention", "已授权");
} else {
Log.e("attention", "拒绝授权, grantResults.length=" + grantResults.length);
}
}
}
}
Item.java
package com.example.myapplication.utils;
import java.io.File;
public class Item {
private File file;
private boolean isChecked = false, isShow = false;
public Item () {}
public Item (File file) {
this.file = file;
}
public void setFile (File file) {
this.file = file;
}
public File getFile () {
return file;
}
public void setChecked (boolean isChecked) {
this.isChecked = isChecked;
}
public boolean getChecked () {
return isChecked;
}
public void setIsShow (boolean isShow) {
this.isShow = isShow;
}
public boolean getIsShow () {
return isShow;
}
}
LinearAdapter.java
package com.example.myapplication.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import com.example.myapplication.R;
import com.example.myapplication.utils.AudioUtils;
import com.example.myapplication.utils.Item;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class LinearAdapter extends RecyclerView.Adapter<LinearAdapter.LinearViewHolder> {
private List<Item> list = null;
private LayoutInflater layoutInflater = null;
private List<Item> selectList = new ArrayList<>();
private OnLayoutChangeListener onLayoutChangeListener = null;
public void setSelectList (List<Item> selectList) {
this.selectList = selectList;
}
public List<Item> getSelectList () {
return selectList;
}
public LinearAdapter () {}
public LinearAdapter (Context context, List<Item> list) {
layoutInflater = LayoutInflater.from(context);
this.list = list;
}
public void setList (List<Item> list) {
this.list = list;
}
@NonNull
@Override
public LinearViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.layout_item_file_list, parent, false);
return new LinearViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull LinearViewHolder holder, int position) {
Item item = list.get(position);
File file = item.getFile();
String title = file.getName().toString();
holder.tv_title.setText(title);
try {
Date date = new SimpleDateFormat("yyyyMMdd").parse(title.substring(7, 15));
SimpleDateFormat sdf = new SimpleDateFormat("y/M/d");
holder.tv_date.setText(sdf.format(date));
} catch (ParseException e) {
throw new RuntimeException(e);
}
AudioUtils audioUtils = new AudioUtils();
String timeLen = audioUtils.getAudioDuration(file.getAbsolutePath());
holder.tv_timeLen.setText(timeLen);
holder.tv_timeCur.setText(timeLen);
holder.record_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
holder.record_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
holder.seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
holder.check_box.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
item.setChecked(isChecked);
if (isChecked) selectList.add(item);
else selectList.remove(item);
}
});
holder.check_box.setChecked(item.getChecked());
if (item.getIsShow()){
holder.check_box.setVisibility(View.VISIBLE);
holder.record_start.setVisibility(View.GONE);
holder.record_stop.setVisibility(View.GONE);
} else {
holder.check_box.setVisibility(View.GONE);
holder.record_stop.setVisibility(View.VISIBLE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
notifyDataSetChanged();
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (item.getIsShow()){
showAll(false);
if (onLayoutChangeListener != null) onLayoutChangeListener.onLayoutChange(false);
} else {
showAll(true);
if (onLayoutChangeListener != null) onLayoutChangeListener.onLayoutChange(true);
}
return false;
}
});
}
@Override
public int getItemCount() {
return list.size();
}
public class LinearViewHolder extends RecyclerView.ViewHolder {
TextView tv_title, tv_date, tv_timeAcc, tv_timeCur, tv_timeLen;
CardView record_stop, record_start;
SeekBar seekbar;
CheckBox check_box;
LinearLayout ll_itemView;
public LinearViewHolder(@NonNull View itemView) {
super(itemView);
tv_title = itemView.findViewById(R.id.tv_title);
tv_date = itemView.findViewById(R.id.tv_date);
tv_timeAcc = itemView.findViewById(R.id.tv_timeAcc);
tv_timeCur = itemView.findViewById(R.id.tv_timeCur);
tv_timeLen = itemView.findViewById(R.id.tv_timeLen);
record_stop = itemView.findViewById(R.id.record_stop);
record_start = itemView.findViewById(R.id.record_start);
seekbar = itemView.findViewById(R.id.seekbar);
check_box = itemView.findViewById(R.id.check_box);
ll_itemView = itemView.findViewById(R.id.ll_itemView);
}
}
public void selectAll (boolean selected) {
if (selectList.size() == list.size()) return;
for (Item item : list) {
item.setChecked(selected);
if (selected && !selectList.contains(item)) selectList.add(item);
else if (!selected && selectList.contains(item)) selectList.remove(item);
}
}
public void showAll (boolean isShow) {
for (Item item : list) {
item.setIsShow(isShow);
}
}
public interface OnLayoutChangeListener {
void onLayoutChange (boolean isShow);
}
public void setOnLayoutChangeListener (OnLayoutChangeListener onLayoutChangeListener) {
this.onLayoutChangeListener = onLayoutChangeListener;
}
}