-
看下效果图
select_file.gif
-- 没有什么技术的地方,直接上代码吧,代码里注释还是蛮清晰的
- java文件
- Activity:
/**
* 选择文件
*/
public class SelectFileActivity extends AppCompatActivity {
private final static String TAG = "SelectFileActivity";
private LinearLayoutManager mLayoutManager;
private List<SelectFile> mList = new ArrayList<>(); //当前路径下的所有文件
private CommonAdapter<SelectFile> mAdapter;
private List<ItemData> mHierarchyList = new ArrayList<>(); //点击的层级
private List<SelectFile> mRootList = new ArrayList<>(); //根目录文件下所有文件 一般内容最多 内存中保存下
private File mCurrentFile; //当前目录
private List<SelectFile> mSelectList = new ArrayList<>(); //已经选择的
private TextView tvSelectFileActivitySend;
private View viewSelectFileActivitySend;
private TextView tvSelectFileActivity; //空目录提示
private RecyclerView recyclerView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_file);
initView();
initData();
initListener();
}
private void initView() {
tvSelectFileActivitySend = findViewById(R.id.tvSelectFileActivitySend);
viewSelectFileActivitySend = findViewById(R.id.viewSelectFileActivitySend);
tvSelectFileActivity = findViewById(R.id.tvSelectFileActivity);
initAdapter();
}
private void initData() {
addRootData();
}
private void initListener() {
//发送
tvSelectFileActivitySend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putParcelableArrayListExtra("selectList", (ArrayList<? extends Parcelable>) mSelectList);
finish();
setResult(RESULT_OK, intent);
}
});
}
private void initAdapter() {
mLayoutManager = new LinearLayoutManager(getApplication());
recyclerView.setLayoutManager(mLayoutManager);
mAdapter = new CommonAdapter<SelectFile>(getApplication(), R.layout.activity_select_file_item, mList) {
@Override
protected void convert(ViewHolder holder, SelectFile data, int position) {
ImageView ivSelectFileActivityRv = holder.getView(R.id.ivSelectFileActivityRv);
TextView tvSelectFileActivityRvName = holder.getView(R.id.tvSelectFileActivityRvName);
TextView tvSelectFileActivityRvCenter = holder.getView(R.id.tvSelectFileActivityRvCenter);
TextView tvSelectFileActivityRvSize = holder.getView(R.id.tvSelectFileActivityRvSize);
ImageView ivSelectFileActivityRvSelect = holder.getView(R.id.ivSelectFileActivityRvSelect);
//最顶级 显示手机内存或者其他内存
if (mHierarchyList.isEmpty()) {
tvSelectFileActivityRvCenter.setVisibility(View.VISIBLE);
ivSelectFileActivityRv.setImageResource(data.getFileIcon());
tvSelectFileActivityRvName.setText("");
tvSelectFileActivityRvCenter.setText(data.getFileName());
tvSelectFileActivityRvSize.setText("");
ivSelectFileActivityRvSelect.setVisibility(View.GONE);
} else {
tvSelectFileActivityRvCenter.setVisibility(View.GONE);
tvSelectFileActivityRvName.setText(data.getFileName());
//文件夹
if (data.isDirectory()) {
ivSelectFileActivityRvSelect.setVisibility(View.GONE);
ivSelectFileActivityRv.setImageResource(R.drawable.icon_file);
//设置下面后多少个文件
tvSelectFileActivityRvSize.setText(data.getChildNum() > 0 ? data.getChildNum() + "个文件" : "没有文件");
} else {
ivSelectFileActivityRvSelect.setVisibility(View.VISIBLE);
ivSelectFileActivityRv.setImageResource(data.getFileIcon());
//设置该文件的大小
tvSelectFileActivityRvSize.setText(data.getFileSize());
if (data.isSelect()) {
ivSelectFileActivityRvSelect.setImageResource(R.drawable.icon_select);
} else {
ivSelectFileActivityRvSelect.setImageResource(R.drawable.icon_un_select);
}
}
}
//前面图片点击
ivSelectFileActivityRv.setOnClickListener(v -> {
//文件夹图标点击 当做item点击
if (data.isDirectory()) {
holder.itemView.performClick();
} else { //打开文件
openFile(new File(data.getFilePath()));
}
});
//item点击
holder.itemView.setOnClickListener(v -> {
//文件夹点击
if (mHierarchyList.isEmpty() || data.isDirectory()) {
//点击后赋值当前目录
mCurrentFile = new File(data.getFilePath());
addData(mCurrentFile, true);
} else { //文件点击
if (!data.isSelect() && mSelectList.size() >= 20) {
ToastUtils.showToast(mContext, "超出数量");
} else {
data.setSelect(!data.isSelect());
mAdapter.notifyDataSetChanged();
setSendView(data, data.isSelect());
}
}
});
}
};
recyclerView.setAdapter(mAdapter);
}
//打开某文件
private void openFile(File f) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
String extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(f).toString());
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
intent.setDataAndType(Uri.fromFile(f), mimeType);
startActivity(intent);
} catch (ActivityNotFoundException e) {
ToastUtils.showToast(getApplication(), "文件不支持打开");
}
}
//顶级目录添加
private void addRootData() {
setSendView(null, false);
mHierarchyList.clear();
mRootList.clear();
mList.clear();
mList.add(new SelectFile("手机内存", R.drawable.icon_file_phone,
Environment.getExternalStorageDirectory().getAbsolutePath()));
mAdapter.notifyDataSetChanged();
tvSelectFileActivity.setVisibility(View.GONE);
}
//根据目录加载文件 next是否往下走
private void addData(File file, boolean next) {
setSendView(null, false);
//层级赋值 往下走 添加一个
if (next) {
mHierarchyList.add(new ItemData(mLayoutManager.findFirstCompletelyVisibleItemPosition(),
mLayoutManager.findViewByPosition(mLayoutManager.findFirstCompletelyVisibleItemPosition()).getTop()));
}
mList.clear();
mAdapter.notifyDataSetChanged();
showLoadContent();
//在子线程添加
Observable.unsafeCreate((Observable.OnSubscribe<Boolean>) subscriber -> {
File[] files = file.listFiles();
for (File value : files) {
//过滤隐藏文件
if (!value.getName().substring(0, 1).equals(".")) {
mList.add(new SelectFile(value.getName(),
FileUtils.getFileIcon(value.getName()),
value.getPath(),
value.isDirectory(),
value.isDirectory() ? ((long) (value.listFiles().length)) : 0L,
value.isDirectory() ? "" : FileUtils.getFormatSize(value)));
}
}
//文件排序
Collections.sort(mList, (selectFile1, selectFile2) -> {
if (selectFile1.isDirectory() && !selectFile2.isDirectory())
return -1;
if (!selectFile1.isDirectory() && selectFile2.isDirectory())
return 1;
return selectFile1.getFileName().compareTo(selectFile2.getFileName());
});
//保存根目录列表
if (mHierarchyList.size() == 1) {
mRootList.clear();
mRootList.addAll(mList);
}
subscriber.onNext(true);
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Boolean>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Boolean b) {
dismissLoading();
mAdapter.notifyDataSetChanged();
tvSelectFileActivity.setVisibility(mList.isEmpty() ? View.VISIBLE : View.GONE);
//列表滑到指定地方
scrollTo(next);
}
});
}
//设置右上角发送view
private void setSendView(SelectFile selectFile, boolean select) {
//清空
if (null == selectFile) {
mSelectList.clear();
} else if (select) { //添加一个
mSelectList.add(selectFile);
} else { //减一个
mSelectList.remove(selectFile);
}
tvSelectFileActivitySend.setText(mSelectList.isEmpty() ? "发送" : "发送(" + mSelectList.size() + "/20)");
viewSelectFileActivitySend.setVisibility(mSelectList.isEmpty() ? View.VISIBLE : View.GONE);
tvSelectFileActivitySend.setEnabled(!mSelectList.isEmpty());
}
private boolean back() {
//返回回到上级目录
if (!mHierarchyList.isEmpty()) {
//当前已经返回到倒数第一和第二级了
if (mHierarchyList.size() == 1 || mHierarchyList.size() == 2) {
//当前在倒数第二级 直接把内存中的mRootList添加进去
if (mHierarchyList.size() == 2) {
setSendView(null, false);
mList.clear();
mList.addAll(mRootList);
mAdapter.notifyDataSetChanged();
tvSelectFileActivity.setVisibility(mList.isEmpty() ? View.VISIBLE : View.GONE);
//列表滑到指定地方
scrollTo(false);
} else { //在倒数第一级了,直接返回到最初始状态
addRootData();
}
} else { //根据mCurrentFile 往上走
mCurrentFile = mCurrentFile.getParentFile();
addData(mCurrentFile, false);
}
return false;
} else {
return true;
}
}
//列表滑到指定地方 next是否往下走
private void scrollTo(boolean next) {
//往下走 直接移到0位置
if (next) {
mLayoutManager.scrollToPosition(0);
} else { //往上走
mLayoutManager.scrollToPositionWithOffset(mHierarchyList.get(mHierarchyList.size() - 1).getVisibleItemIndex(),
mHierarchyList.get(mHierarchyList.size() - 1).getVisibleItemTop());
//层级往上走一个
mHierarchyList.remove(mHierarchyList.size() - 1);
}
}
@Override
public void onBackPressed() {
if (back()) {
super.onBackPressed();
}
}
private static class ItemData {
private int visibleItemIndex; //完全可见的item下标
private int visibleItemTop; //完全可见的item距离顶部距离
ItemData(int visibleItemIndex, int visibleItemTop) {
this.visibleItemIndex = visibleItemIndex;
this.visibleItemTop = visibleItemTop;
}
int getVisibleItemIndex() {
return visibleItemIndex;
}
public void setVisbleItemIndex(int visbleItemIndex) {
this.visibleItemIndex = visbleItemIndex;
}
int getVisibleItemTop() {
return visibleItemTop;
}
public void setVisibleItemTop(int visibleItemTop) {
this.visibleItemTop = visibleItemTop;
}
}
}
- FileUtils:
public class FileUtils {
//根据文件名获相应要图片
public static int getFileIcon(String fileName) {
if (TextUtils.isEmpty(fileName)) {
fileName = "";
}
fileName = fileName.toLowerCase();
int fileIcon = R.drawable.icon_file_none;
if (fileName.endsWith(".txt")) {
fileIcon = R.drawable.icon_file_txt;
} else if (fileName.endsWith(".jpg") ||
fileName.endsWith(".jpeg") ||
fileName.endsWith(".png") ||
fileName.endsWith(".gif") ||
fileName.endsWith(".pic")) {
fileIcon = R.drawable.icon_file_image;
} else if (fileName.endsWith(".mp3") ||
fileName.endsWith(".amr") ||
fileName.endsWith(".ram") ||
fileName.endsWith(".wav") ||
fileName.endsWith(".aif")) {
fileIcon = R.drawable.icon_file_music;
} else if (fileName.endsWith(".mp4") ||
fileName.endsWith(".avi") ||
fileName.endsWith(".mov") ||
fileName.endsWith(".rm") ||
fileName.endsWith(".mpg")) {
fileIcon = R.drawable.icon_file_video;
} else if (fileName.endsWith(".zip") ||
fileName.endsWith(".rar") ||
fileName.endsWith(".arj")) {
fileIcon = R.drawable.icon_file_compress;
} else if (fileName.endsWith(".doc") ||
fileName.endsWith(".docx")) {
fileIcon = R.drawable.icon_file_word;
} else if (fileName.endsWith(".xls") ||
fileName.endsWith(".xlsx")) {
fileIcon = R.drawable.icon_file_xls;
} else if (fileName.endsWith(".ppt") ||
fileName.endsWith(".pptx")) {
fileIcon = R.drawable.icon_file_ppt;
} else if (fileName.endsWith(".pdf")) {
fileIcon = R.drawable.icon_file_pdf;
} else if (fileName.endsWith(".psd")) {
fileIcon = R.drawable.icon_file_psd;
} else if (fileName.endsWith(".cad")) {
fileIcon = R.drawable.icon_file_cad;
} else if (fileName.endsWith(".iso")) {
fileIcon = R.drawable.icon_file_iso;
} else if (fileName.endsWith(".exe")) {
fileIcon = R.drawable.icon_file_exe;
}
return fileIcon;
}
/**
* 获取文件大小
*/
public static String getFormatSize(File file) {
try {
return getFormatSize(file.length());
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
/**
* 格式化单位
*/
public static String getFormatSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
return "0K";
}
double megaByte = kiloByte / 1024;
if (megaByte < 1) {
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
.stripTrailingZeros().toPlainString() + "K";
}
double gigaByte = megaByte / 1024;
if (gigaByte < 1) {
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
.stripTrailingZeros().toPlainString() + "M";
}
double teraBytes = gigaByte / 1024;
if (teraBytes < 1) {
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
.stripTrailingZeros().toPlainString() + "GB";
}
BigDecimal result4 = new BigDecimal(teraBytes);
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()
+ "TB";
}
}
- SelectFile:
//选择文件
public class SelectFile implements Parcelable {
private String fileName; //文件名
private int fileIcon; //文件图标
private String filePath; //文件路径 不包括当前文件名
private boolean isDirectory; //是否是文件夹
private long childNum; //子目录数量
private String fileSize; //文件大小
private boolean select;
public SelectFile(String fileName, int fileIcon, String filePath) {
this.fileName = fileName;
this.fileIcon = fileIcon;
this.filePath = filePath;
this.isDirectory = true;
}
public SelectFile(String fileName, int fileIcon, String filePath, boolean isDirectory, long childNum, String fileSize) {
this.fileName = fileName;
this.fileIcon = fileIcon;
this.filePath = filePath;
this.isDirectory = isDirectory;
this.childNum = childNum;
this.fileSize = fileSize;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getFileIcon() {
return fileIcon;
}
public void setFileIcon(int fileIcon) {
this.fileIcon = fileIcon;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public boolean isDirectory() {
return isDirectory;
}
public void setDirectory(boolean directory) {
isDirectory = directory;
}
public long getChildNum() {
return childNum;
}
public void setChildNum(long childNum) {
childNum = childNum;
}
public String getFileSize() {
return fileSize;
}
public void setFileSize(String fileSize) {
this.fileSize = fileSize;
}
public boolean isSelect() {
return select;
}
public void setSelect(boolean select) {
this.select = select;
}
protected SelectFile(Parcel in) {
fileName = in.readString();
fileIcon = in.readInt();
filePath = in.readString();
isDirectory = in.readByte() != 0;
childNum = in.readLong();
fileSize = in.readString();
select = in.readByte() != 0;
}
public static final Creator<SelectFile> CREATOR = new Creator<SelectFile>() {
@Override
public SelectFile createFromParcel(Parcel in) {
return new SelectFile(in);
}
@Override
public SelectFile[] newArray(int size) {
return new SelectFile[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(fileName);
dest.writeInt(fileIcon);
dest.writeString(filePath);
dest.writeByte((byte) (isDirectory ? 1 : 0));
dest.writeLong(childNum);
dest.writeString(fileSize);
dest.writeByte((byte) (select ? 1 : 0));
}
// @Override
// public int compareTo(SelectFile selectFile) {
// //自己和比较的都是文件夹 或者两个都不是文件夹
// if (isDirectory && selectFile.isDirectory || !isDirectory && !selectFile.isDirectory) {
// return compareAB(getFileName(), selectFile.getFileName());
// } else if (isDirectory && !selectFile.isDirectory) { //自己是文件夹 比较的不是
// return -1;
// } else if (!isDirectory && selectFile.isDirectory) { //自己不是文件夹 比较的是
// return 1;
// } else {
// return 0;
// }
// }
// //自定义文件排序,汉字,_,字母依次
// private int compareAB(String left, String right) {
// String A = left.substring(0, 1);
// String B = right.substring(0, 1);
// if (!isLetter(A) && !isLetter(B)) {
// return A.compareTo(B);
// } else if (!isLetter(A)) {
// return -1;
// } else if (!isLetter(B)) {
// return 1;
// } else {
// String a = A.toLowerCase();
// String b = B.toLowerCase();
// if (a.compareTo(b) == 0) {
// return A.compareTo(B);
// } else {
// return a.compareTo(b);
// }
// }
// }
//
// private boolean isLetter(String str) {
// String regex = "^[a-zA-Z]+$";//其他需要,直接修改正则表达式就好
//// String regex = "^[a-z0-9A-Z\u4e00-\u9fa5]+$"
// return str.matches(regex);
// }
}
- xml文件
- activity_select_file.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="match_parent"
android:background="#F5F5F5"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="@color/white"
android:gravity="center_vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
android:singleLine="true"
android:text="文件"
android:textColor="@color/c_1D1D1D"
android:textSize="17sp"
/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
>
<TextView
android:id="@+id/tvSelectFileActivitySend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/view_click_bg_fc5d09_6"
android:gravity="center"
android:minWidth="50dp"
android:padding="5dp"
android:text="发送"
android:textColor="@color/white"
android:textSize="12sp"
/>
<View
android:id="@+id/viewSelectFileActivitySend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/tvSelectFileActivitySend"
android:layout_alignTop="@+id/tvSelectFileActivitySend"
android:layout_alignEnd="@+id/tvSelectFileActivitySend"
android:layout_alignBottom="@+id/tvSelectFileActivitySend"
android:background="@drawable/view_bg_99f2f2f5_6"
/>
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_alignParentBottom="true"
android:background="@color/c_F8F8F8"
/>
</RelativeLayout>
<TextView
android:id="@+id/tvSelectFileActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F5F5"
android:gravity="center"
android:text="没有文件"
android:textSize="16sp"
android:visibility="gone"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/rvSelectFileActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbarSize="5dp"
android:scrollbars="vertical"
/>
</LinearLayout>
- activity_select_file_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:background="@color/white"
>
<ImageView
android:id="@+id/ivSelectFileActivityRv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="@drawable/icon_file"
/>
<TextView
android:id="@+id/tvSelectFileActivityRvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/ivSelectFileActivityRv"
android:layout_marginTop="3dp"
android:layout_toStartOf="@+id/ivSelectFileActivityRvSelect"
android:layout_toEndOf="@+id/ivSelectFileActivityRv"
android:singleLine="true"
android:textColor="@color/c_1D1D1D"
android:textSize="14sp"
/>
<TextView
android:id="@+id/tvSelectFileActivityRvCenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/ivSelectFileActivityRvSelect"
android:layout_toEndOf="@+id/ivSelectFileActivityRv"
android:singleLine="true"
android:textColor="@color/c_1D1D1D"
android:textSize="14sp"
android:visibility="gone"
/>
<TextView
android:id="@+id/tvSelectFileActivityRvSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/ivSelectFileActivityRv"
android:layout_marginBottom="3dp"
android:layout_toEndOf="@+id/ivSelectFileActivityRv"
android:textColor="#999999"
android:textSize="10sp"
/>
<ImageView
android:id="@+id/ivSelectFileActivityRvSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_margin="8dp"
android:src="@drawable/icon_un_select"
android:visibility="gone"
/>
</RelativeLayout>
- view_bg_99f2f2f5_6.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="0"
android:endColor="#99F2F2F5"
android:startColor="#99F2F2F5"
/>
<!--<stroke android:width="1dp" android:color="@color/white"></stroke>-->
<corners android:radius="6dp" />
</shape>
- view_click_bg_fc5d09_6.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 没有选中 -->
<item android:state_pressed="false"
android:state_selected="false"
>
<shape>
<!-- 按钮背景图 -->
<solid android:color="#FC5D09" />
<!-- 弧度 -->
<corners android:radius="6dp" />
<!-- 边框宽度和颜色 -->
<stroke android:width="0dp" android:color="#00000000" />
</shape>
</item>
<!-- 选中 -->
<item android:state_selected="true"
>
<shape>
<solid android:color="#00000000" />
<corners android:radius="0dp" />
<stroke android:width="0dp" android:color="#51A2FF" />
</shape>
</item>
<!-- 点击事件 -->
<item android:state_pressed="true"
android:state_selected="false"
>
<shape>
<solid android:color="#55FC5D09" />
<corners android:radius="6dp" />
</shape>
</item>
</selector>
- 其他文件 直接上传到百度云了 (CommonAdapter和一些drawable图片)
链接:链接:https://pan.baidu.com/s/1Ra_rGLtVnAuQP21HE_9Ctw
提取码:jzyu
网友评论