Android 文件管理器的列表界面
程序员文章站
2022-06-10 10:43:40
...
前言:
之前做了一个文件管理器的app,那么列表中只有名字....实在太简陋了,所以我打算做一个比较好看一点的列表。
效果图:
可能对于专业的你来说,还是比较简陋。这次列表中,除了文件名,我还添加了图标,文件大小,文件权限还有修改日期。
首先这是一个RecyclerView..然后先上代码,这个RecyclerView的部分代码
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/myFileImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="5dp"
app:srcCompat="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/myFileName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:singleLine="true"
android:ellipsize="start"
android:textSize="25sp"
android:layout_gravity="center"
android:text="TextView" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/fileSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="大小" />
<TextView
android:id="@+id/filePower"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="权限" />
<TextView
android:id="@+id/fileDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="创建日期" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
这个是列表每个项目的样子,来张截图
然后是这个包装类
package com.example.administrator.day2_15;
/**
* Created by Administrator on 2018/2/25 0025.
*/
public class MyFile {
private int imageId;
private String fileName;
private String fileSize;
private String filePower;
private String fileDate;
public MyFile(String fileName, int imageId, String fileSize, String filePower, String fileDate) {
super();
this.fileName = fileName;
this.imageId = imageId;
this.fileSize = fileSize;
this.filePower = filePower;
this.fileDate = fileDate;
}
public String getFileName() {
return fileName;
}
public int getImageId() {
return imageId;
}
public String getFileSize() {
return fileSize;
}
public String getFilePower() {
return filePower;
}
public String getFileDate() {
return fileDate;
}
}
然后就到自定义的Adapter
package com.example.administrator.day2_15;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* Created by Administrator on 2018/2/25 0025.
*/
public class MyFileAdapter extends RecyclerView.Adapter<MyFileAdapter.ViewHolder> {
private List<MyFile> myFileList;
private Context mContext;
public MyFileAdapter(List<MyFile> list) {
super();
myFileList = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mContext == null) {
mContext = parent.getContext();
}
View view = LayoutInflater.from(mContext).inflate(R.layout.myfile_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
MyFile myFile = myFileList.get(position);
holder.myFileName.setText(myFile.getFileName());
holder.myFileImage.setImageResource(myFile.getImageId());
holder.myFileSize.setText(myFile.getFileSize());
holder.myFilePower.setText(myFile.getFilePower());
holder.myFileDate.setText(myFile.getFileDate());
}
@Override
public int getItemCount() {
return myFileList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder{
TextView myFileName;
ImageView myFileImage;
TextView myFileSize;
TextView myFilePower;
TextView myFileDate;
public ViewHolder(View itemView) {
super(itemView);
myFileName = itemView.findViewById(R.id.myFileName);
myFileImage = itemView.findViewById(R.id.myFileImage);
myFileSize = itemView.findViewById(R.id.fileSize);
myFilePower = itemView.findViewById(R.id.filePower);
myFileDate = itemView.findViewById(R.id.fileDate);
}
}
}
如果你了解RecyclerView的话,这些不用说你都明白,甚至会觉得有点啰嗦了。
好了,关键的地方到了,就是传入RecyclerView的数据,文件的大小,创建时间,图标怎么判断呢
private void initMyFile(File sourceFile) {
myFileList.clear();
List<File> files = new ArrayList<>();
Collections.addAll(files, sourceFile.listFiles());
for (File file : files) {
String fileName = file.getName();
//默认是未知文件
int imageId = R.drawable.interrogation;
//下面开始判断
if (file.isDirectory()) {
imageId = R.drawable.floder2;
} else {
//如果是文件,就从文件名的后缀名来判断是什么文件,从而添加对应图标
//获取后缀名前的分隔符"."在fName中的位置。
int dotIndex = fileName.lastIndexOf(".");
if(dotIndex >= 0){
/* 获取文件的后缀名*/
String end= fileName.substring(dotIndex,fileName.length()).toLowerCase();
if(!Objects.equals(end, "")){
if (Objects.equals(end, ".mp3")||Objects.equals(end, ".ape")
||Objects.equals(end, ".flac")||Objects.equals(end, ".m4a")
||Objects.equals(end, ".ape")||Objects.equals(end, ".wav")
||Objects.equals(end, ".aac")){
//如果是音乐文件
imageId = R.drawable.music;
}else if (Objects.equals(end, ".mp4")||Objects.equals(end, ".mkv")
||Objects.equals(end, ".avi")||Objects.equals(end, ".rmvb")
||Objects.equals(end, ".rm")||Objects.equals(end, ".mov")
||Objects.equals(end, ".mpeg")){
//如果是影视文件
imageId = R.drawable.play;
}
}
}
}
String fileSize = "";
long size = 0;
//下面开始判断文件大小
if (file.isDirectory()) {
//如果是文件夹就要求出占用大小 = 总大小 - 可用大小
try {
size = getTotalSizeOfFilesInDir(file);
} catch (Exception e) {
e.printStackTrace();
}
} else {
size = file.length();
}
//判断大小是该用什么单位,K\M\G
if (size / 1024 / 1024 / 1024 > 0) {
fileSize = size / 1024 / 1024 / 1024 + " G";
} else if (size / 1024 / 1024 > 0) {
fileSize = size / 1024 / 1024 + " M";
} else {
fileSize = size / 1024 + " K";
}
String filePower = "";
StringBuilder builder = new StringBuilder();
builder.append("-");
if (file.canRead()) builder.append("r");
if (file.canWrite()) builder.append("w");
if (file.canExecute()) builder.append("x");
filePower = builder.toString();
String fileDate = "";
fileDate = getModifiedTime_2(file);
MyFile myFile = new MyFile(fileName, imageId, fileSize, filePower, fileDate);
myFileList.add(myFile);
}
adapter.notifyDataSetChanged();
}
该方法只是测试样子,所以图标那块仅仅区分了音乐文件和影视文件,还有其他文件格式没有添加进去。不过大同小异,也是照葫芦画瓢而已。
那么至于怎么获取文件夹的大小,上代码
private class SubDirectoriesAndSize {
final public long size;
final public List<File> subDirectories;
public SubDirectoriesAndSize(final long totalSize,
final List<File> theSubDirs) {
size = totalSize;
subDirectories = Collections.unmodifiableList(theSubDirs);
}
}
private SubDirectoriesAndSize getTotalAndSubDirs(final File file) {
long total = 0;
final List<File> subDirectories = new ArrayList<File>();
if (file.isDirectory()) {
final File[] children = file.listFiles();
if (children != null)
for (final File child : children) {
if (child.isFile())
total += child.length();
else
subDirectories.add(child);
}
}
return new SubDirectoriesAndSize(total, subDirectories);
}
private long getTotalSizeOfFilesInDir(final File file)
throws InterruptedException, ExecutionException, TimeoutException {
final ExecutorService service = Executors.newFixedThreadPool(100);
try {
long total = 0;
final List<File> directories = new ArrayList<File>();
directories.add(file);
while (!directories.isEmpty()) {
final List<Future<SubDirectoriesAndSize>> partialResults = new ArrayList<Future<SubDirectoriesAndSize>>();
for (final File directory : directories) {
partialResults.add(service
.submit(new Callable<SubDirectoriesAndSize>() {
public SubDirectoriesAndSize call() {
return getTotalAndSubDirs(directory);
}
}));
}
directories.clear();
for (final Future<SubDirectoriesAndSize> partialResultFuture : partialResults) {
final SubDirectoriesAndSize subDirectoriesAndSize = partialResultFuture
.get(100, TimeUnit.SECONDS);
directories.addAll(subDirectoriesAndSize.subDirectories);
total += subDirectoriesAndSize.size;
}
}
return total;
} finally {
service.shutdown();
}
}
这个方法使用Executors.newFixedThreadPool和callable 多线程实现,是来自网址
点击打开链接 ,这个博客里面还介绍了很多种获取文件夹大小的方法,我开头试过单线程递归,发现很耗时间和内存。
返回字节后再通过一点判断来决定显示单位。
最后就是怎么获取文件的修改时间呢?
public static String getModifiedTime_2(File f){
Calendar cal = Calendar.getInstance();
long time = f.lastModified();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
cal.setTimeInMillis(time);
return formatter.format(cal.getTime());
}
这个方法是来自百度知道 回答者 vdny 。。。点击打开链接
最后再贴上mainActivity的部分代码
private List<MyFile> myFileList = new ArrayList<>();
private MyFileAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new MyFileAdapter(myFileList);
initMyFile(Environment.getExternalStorageDirectory());
RecyclerView recyclerView = findViewById(R.id.rv);
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(adapter);
}
好了,那么写到这里终于把文件管理器的Bug和坑填完了。但是我也失去了去年那种小小进步就能兴奋不已的感觉了。
希望这篇文章能够帮助到你。如有问题,请尽管提出,看到我会尽量回答你。拜