之前的log打得跟日记一样

1.感觉先显示文件再显示文件夹还是太丑了,改了回来
2.获取外部存储根目录的由直接给路径改成方法调用获取
3.新建了一个NetCheck类,用于检测当前网络状态,但是具体功能并没有实现
4.实现了fragment之间的跳转和数据的传递,即点击文件夹打开该目录,然后发现空目录会发生空指针异常也一并处理了
fragment的跳转和参考官方文档和https://blog.csdn.net/m0_46962786/article/details/109119746,这篇文章,对nav_graph中的filemanagefragment(简称fm)添加了action和argument

完成了文件管理的功能,然后正在删除一些冗余的代码
master
ThankVinci 4 years ago
parent 63314b320d
commit 899b9ff899

@ -1,5 +1,6 @@
package com.thankvinci.CloudKey.Files;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@ -10,15 +11,23 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView;
import com.thankvinci.CloudKey.Fragment.FileManageFragment;
import com.thankvinci.CloudKey.R;
import java.io.File;
import java.util.List;
public class FileAdapter extends RecyclerView.Adapter<FileAdapter.ViewHolder> {
private List<FileItem> fileList;
private Fragment fragment;
private static FileAdapter adapter;
static class ViewHolder extends RecyclerView.ViewHolder{
ImageView icon;
@ -31,19 +40,44 @@ public class FileAdapter extends RecyclerView.Adapter<FileAdapter.ViewHolder> {
name = file.findViewById(R.id.file_name);
}
}
public FileAdapter(List<FileItem> fileList){
public static FileAdapter getInstance(List<FileItem> fileList,Fragment fragment){
if(adapter != null){
return adapter;
}
adapter = new FileAdapter(fileList,fragment);
return adapter;
}
public void setFileList(List<FileItem> fileList){
this.fileList = fileList;
}
public FileAdapter(List<FileItem> fileList,Fragment fragment){
this.fileList = fileList;
this.fragment = fragment;
}
@Override
public FileAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.file_item,parent,false);
ViewHolder holder = new ViewHolder(view);
Bundle data = new Bundle();
holder.file.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
int position = holder.getAdapterPosition();
FileItem fitem = fileList.get(position);
Toast.makeText(view.getContext(),fitem.getName(),Toast.LENGTH_SHORT).show();
Toast.makeText(v.getContext(),fitem.getName(),Toast.LENGTH_SHORT).show();
if(fitem.isDir()){
StringBuilder builder = new StringBuilder();
builder.append(((FileManageFragment)fragment).getDir());
builder.append("/");
builder.append(fitem.getName());
data.putString("dir",builder.toString());
data.putBoolean("isRoot",false);
Navigation.findNavController(v).navigate(R.id.action_openDir,data);
}else{
Toast.makeText(v.getContext(),"没有打开除文件夹和压缩包以外的功能",Toast.LENGTH_SHORT).show();
}
}
});
return holder;
@ -58,6 +92,9 @@ public class FileAdapter extends RecyclerView.Adapter<FileAdapter.ViewHolder> {
@Override
public int getItemCount() {
if (fileList == null){
return 0;
}
return fileList.size();
}
}

@ -29,4 +29,7 @@ public class FileItem {
public int getIcon(){
return icon;
}
public boolean isDir(){
return !type;
}
}

@ -7,19 +7,19 @@ import java.util.Comparator;
import java.util.List;
public class FileUtils {
//按照文件,文件,文件名次序的顺序进行排序,参考:https://blog.csdn.net/qq_34246164/article/details/111785553
//按照文件,文件,文件名次序的顺序进行排序,参考:https://blog.csdn.net/qq_34246164/article/details/111785553
public static void orderByName(File[] files){
List fileList = Arrays.asList(files);
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File f1,File f2){
if(f1.isDirectory() && f2.isFile()){
return 0;
return -1;
}
if(f2.isDirectory() && f1.isFile()){
return -1;
return 0;
}
return f1.getName().compareTo(f2.getName());
return (f1.getName().toUpperCase()).compareTo((f2.getName().toUpperCase()));
}
});
}

@ -1,10 +1,15 @@
package com.thankvinci.CloudKey.Fragment;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
@ -18,27 +23,48 @@ import com.thankvinci.CloudKey.R;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class FileManageFragment extends Fragment {
private String dir; //当前fragment加载的目录
private boolean isRoot; //是否是根目录布局
private EditText path_edit;
private RecyclerView directoryView;
private List<FileItem> fileItemList = new ArrayList<>();
private List<FileItem> fileItemList;
private String fileNames[];
private File files[];
public FileManageFragment(){
super(R.layout.filemanage_fragment);
}
@Override
public void onViewCreated(View view,Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
path_edit = getView().findViewById(R.id.path_name);
directoryView = (RecyclerView)getView().findViewById(R.id.dir_list);
Bundle data = getArguments();
dir = data.getString("dir");
isRoot = data.getBoolean("isRoot");
Toast.makeText(getActivity(),dir+isRoot,Toast.LENGTH_SHORT).show();
if(isRoot){
loadRoot();
}else{
loadDirectory(dir);
}
initLayout();
}
public String getDir(){
return dir;
}
private void initLayout(){
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL);
directoryView.setLayoutManager(layoutManager);
FileAdapter adapter = new FileAdapter(fileItemList);
FileAdapter adapter = FileAdapter.getInstance(fileItemList,this);
adapter.setFileList(fileItemList);
directoryView.setAdapter(adapter);
}
private void loadRoot() {
@ -46,25 +72,39 @@ public class FileManageFragment extends Fragment {
ActivityCompat.requestPermissions(getActivity(), new String[]{ //运行时权限
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE"}, 1);
//File root = getActivity().getExternalFilesDir(null);
//File root = new File(Environment.getExternalStorageState());
File root = new File("/storage/emulated/0");
Toast.makeText(getActivity(),root.getAbsolutePath()+"",Toast.LENGTH_SHORT).show();
Toast.makeText(getActivity(),root.canRead()+"",Toast.LENGTH_SHORT).show();
String rootPath = Environment.getExternalStorageDirectory().getPath();
dir = rootPath;
path_edit.setText(dir);
File root = new File(rootPath);
files = root.listFiles();
if (files == null){
//当目录里为空时,列表为空对象
}else{
FileUtils.orderByName(files);
path_edit.setText("/storage/emulated/0");
initDirectory();
}
}
public void loadDirectory(String path){
ActivityCompat.requestPermissions(getActivity(), new String[]{ //运行时权限
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE"}, 1);
path_edit.setText(path);
File directory = new File(path);
Toast.makeText(getActivity(),directory.getAbsolutePath()+"",Toast.LENGTH_SHORT).show();
files = directory.listFiles();
if (files == null){
//当目录里为空时,列表为空对象
}else{
FileUtils.orderByName(files);
initDirectory();
}
Toast.makeText(getActivity(),directory.canRead()+"",Toast.LENGTH_SHORT).show();
}
private void initDirectory(){
fileItemList = null;
fileItemList = new ArrayList<>();
String filename,suffix;
boolean isFile,isZip;
int lastIndex,index;
@ -90,8 +130,6 @@ public class FileManageFragment extends Fragment {
if(index != 0){ //隐藏.开头的隐藏文件
FileItem fitem = new FileItem(filename,isFile,isZip);
fileItemList.add(fitem);
}else{
}
}
}

@ -0,0 +1,4 @@
package com.thankvinci.CloudKey.NetUtils;
public class NetCheck {
}

@ -10,10 +10,11 @@
android:id="@+id/path_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:focusedByDefault="true"
android:focusable="false"
android:text="/emulated/0/sdcard"
android:textColor="@color/grey"
android:textSize="14dp"
android:singleLine="true"
tools:ignore="MissingConstraints" />
<androidx.recyclerview.widget.RecyclerView

@ -8,7 +8,21 @@
android:id="@+id/fileManageFragment"
android:name="com.thankvinci.CloudKey.Fragment.FileManageFragment"
android:label="目录"
tools:layout="@layout/filemanage_fragment" />
tools:layout="@layout/filemanage_fragment" >
<action
android:id="@+id/action_openDir"
app:destination="@id/fileManageFragment" />
<argument
android:name="dir"
android:defaultValue=""
app:argType="string"
app:nullable="true"/>
<argument
android:name="isRoot"
android:defaultValue="true"
app:argType="boolean"
app:nullable="false"/>
</fragment>
<fragment
android:id="@+id/aboutFragment"
android:name="com.thankvinci.CloudKey.Fragment.AboutFragment"

@ -186,3 +186,38 @@ implementation 'androidx.navigation:navigation-ui:2.2.2'
**2021/6/11**
发现物理机的隐藏文件挺多的,于是设置默认隐藏.开头的隐藏文件,关于file类获取当前目录下的子文件,在Windows上默认按文件名排序,但是在Android里却没有,所以要对文件和文件夹以及名字和文件夹进行排序,考虑到我们可能要优先找文件,所以,文件就显示在文件夹前
**2021/6/11**
感觉先文件再文件夹还是太丑了,就改回来了,然后是获取根目录
从File root = new File("/storage/emulated/0");改为:File root = new File(Environment.getExternalStorageDirectory().getPath())
在实现点击recyclerview子项的时候就在想,由于我点击的是自己设计的FileItem类对象,我只能把当前的文件名传出去,却获取不到文件的完整路径,最后我在想,用一个栈来存我每次打开的目录,默认栈顶是根目录,打开一个目录就入栈,退出一个目录就出栈,栈顶为1时,若再退出则弹出Dialog提示是否退出
新建了一个NetCheck类,用于检测当前网络状态,不过并没有实现功能
在完成打开目录的时候,没有考虑到一些问题,比如,返回键,由于我是重新加载布局,所以就变成了按一下返回键就finish()这样的情况,在想要不要设置成每点击一个文件夹就实例化一个fragment
===========================================分割线=====================================
具体流程是这样:
进入APP,默认是根目录,加载布局的时候初始化栈,栈顶是根目录,每打开一个目录就实例化一个布局,然后放到栈顶,每按一次返回就把栈顶的布局弹出并finish(),当到达栈底时,会询问是否退出APP,是则弹栈finish();
程序左边的nav导航中的"我的文件"点击不仅会加载根目录布局,还会直接把栈初始化
打完这几行字后发现自己很蠢,打开,返回finish已经是栈的操作了,要实现的是,fragment之间的跳转
在执行fragment之间跳转的部分卡住了,书上的跳转是一个activity的layout文件的子控件framelayout的跳转,但是这里写的是navHostFragment中的fragment跳转
从官方文档中可以找到
public static final View.OnClickListener createNavigateOnClickListener(@IdRes int resId, @Nullable Bundle args)
第一个参数是在nav_graph中设置的action,我设置了从FM到FM的action,第二个参数是Bundle,用于传递数据
返回一个OnClickListener,但是我是分文件和目录的,这个方法又不能重写,然后又找到了https://blog.csdn.net/m0_46962786/article/details/109119746这篇文章,这里面是在普通的OnClickListener中获取当前的Navigation的controller,然后调用navigate()方法去触发action和传递参数

Loading…
Cancel
Save