您的位置:首页 > 移动开发 > Android开发

漂亮简洁的文件夹和文件选择器,可自由设置要选择的文件类型和文件图标

2016-07-12 11:58 1636 查看
转载请注明出处http://blog.csdn.net/sinat_25689603/article/details/51887756

本文出自yedongyang的博客

1.前言

我们平时希望从存储获取一个文件,总是要调用系统的文件管理器,但是系统的管理器并不是所有手机都有的,如果没有会提示用户安装,这种体验非常不好,并且系统选择器很难看,于是自己写了一个漂亮简洁的文件选择器,嵌入式的既方便又不复杂。
FolderChooserActivity.class
FolderChooserAdapter.class
FolderChooserInfo.class







2.功能

支持文件和文件夹选择,在调用到选择器时只需要传入一个boolean值即可区分。
Intent intent = new Intent(MainActivity.this, FolderChooserActivity.class);
intent.putExtra("isFolderChooser", true);
startActivityForResult(intent, REQUEST_FOLDER);


支持自定义文件类型的图标,我自己写了几种常用的类型,你可以在else下面加入你需要的类型
private int fileType(File file){
int image = R.mipmap.type_file;
if(file.isDirectory()){
image = R.mipmap.type_folder;
}else{
try {
//            指定文件类型的图标
String[] token = file.getName().split("\\.");
String suffix = token[token.length - 1];
if (suffix.equalsIgnoreCase("txt")) {
image = R.mipmap.type_txt;
} else if (suffix.equalsIgnoreCase("png") || suffix.equalsIgnoreCase("jpg") || suffix.equalsIgnoreCase("jpeg") || suffix.equalsIgnoreCase("gif")) {
image = R.mipmap.type_image;
} else if (suffix.equalsIgnoreCase("mp3")) {
image = R.mipmap.type_mp3;
} else if (suffix.equalsIgnoreCase("mp4") || suffix.equalsIgnoreCase("rmvb") || suffix.equalsIgnoreCase("avi")) {
image = R.mipmap.type_video;
} else if (suffix.equalsIgnoreCase("apk")) {
image = R.mipmap.type_apk;
}
}catch (Exception e){
e.printStackTrace();
}
}
return image;
}


如果是文件选择器的话,支持自由选择文件类型,只需要传入一个imietype,默认所有类型*/*
Intent intent = new Intent(MainActivity.this, FolderChooserActivity.class);
intent.putExtra("isFolderChooser", false);
intent.putExtra("mimeType", "image/*");
startActivityForResult(intent, REQUEST_FILE);


3.使用方法

选择文件夹的话,进入要选择的文件夹点击右上角保存图标即可选择,在文件选择器里除了可以直接点击文件选择外,同样可以点击右上角保存按钮选择文件夹。

本选择器使用线程池处理耗时查找文件的内容,查找时会转圈,不过一般SD卡文件也就那么些,文件多了也就1到2秒。

头部标题栏可以自定义,可以直接使用我写的,也可以用ActionBar,注意保存的按钮处理一下即可。

跳转到选择器时可传入三种intent extra,一个不传也没事,都有默认值
intent.putExtra("isFolderChooser", true);//是否是文件夹,默认false
//选择器初始路径,默认SD卡根目录
intent.putExtra("file_path", Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM");
intent.putExtra("mimeType", "image/*");//文件选择器类型,默认所有文件


最后在你的activity接收返回的文件地址
<span style="font-size:18px;">@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode){
case REQUEST_FOLDER:
File folder = (File) data.getSerializableExtra("file_path");
Toast.makeText(MainActivity.this, "已选择:" + folder.getAbsolutePath(), Toast.LENGTH_LONG).show();
break;
case REQUEST_FILE:
File file = (File) data.getSerializableExtra("file_path");
Toast.makeText(MainActivity.this, "已选择:" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}</span>


文件选择的列表使用了RecyclerView
 列表分割线使用了一个库com.yqritc:recyclerview-flexibledivider:1.2.8,你也可以不用它,自己在RecyclerView的item中定制你的分割线。

4.权限

别忘了加入权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

5.全部源码

最后贴上全部源码:下载:http://download.csdn.net/detail/sinat_25689603/9574166

package com.example.folderchooser;

import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.folderchooser.folderchooser.FolderChooserActivity;

import java.io.File;

public class MainActivity extends AppCompatActivity {

private Button choose_folder;
private Button choose_file;

private static final int REQUEST_FOLDER = 1;
private static final int REQUEST_FILE = 2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}

private void initView() {
choose_folder = (Button) findViewById(R.id.choose_folder);
choose_file = (Button) findViewById(R.id.choose_file);

choose_folder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, FolderChooserActivity.class);
intent.putExtra("isFolderChooser", true);
intent.putExtra("file_path", Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM");
startActivityForResult(intent, REQUEST_FOLDER);
}
});

choose_file.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, FolderChooserActivity.class); intent.putExtra("isFolderChooser", false); intent.putExtra("mimeType", "image/*"); startActivityForResult(intent, REQUEST_FILE);
}
});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode){
case REQUEST_FOLDER:
File folder = (File) data.getSerializableExtra("file_path");
Toast.makeText(MainActivity.this, "已选择:" + folder.getAbsolutePath(), Toast.LENGTH_LONG).show();
break;
case REQUEST_FILE:
File file = (File) data.getSerializableExtra("file_path");
Toast.makeText(MainActivity.this, "已选择:" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
}
package com.example.folderchooser.folderchooser;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.folderchooser.R;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* 文件和文件夹选择器
* 作者:yedongyang
* 我的博客:http://blog.csdn.net/sinat_25689603
* created by ydy on 2016/7/11 11:47
*/
public class FolderChooserActivity extends AppCompatActivity {

ImageView titleLeft; //标题栏左边按钮
TextView titleText; // 标题栏title
ImageView titleRight; //标题栏右边按钮
TextView savePath;
RecyclerView recyclerView;
LinearLayout loading_view;

//是否为文件夹选择器。true文件夹,false文件
private boolean isFolderChooser = false;
private String mimeType = "*/*";
private String mInitialPath = Environment.getExternalStorageDirectory().getAbsolutePath();

private FolderChooserAdapter mAdapter;
private List mData;

private File parentFolder;
private List parentContents;
private boolean canGoUp = true;

private ExecutorService singleThreadExecutor;

@SuppressLint("HandlerLeak")
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 0:
savePath.setText(parentFolder.getAbsolutePath());
mData.clear();
mData.addAll(getContentsArray());
mAdapter.notifyDataSetChanged();

loading_view.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
break;
}
}
};

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_folder_chooser);
isFolderChooser = getIntent().getBooleanExtra("isFolderChooser", false);
String mime_Type = getIntent().getStringExtra("mimeType");
String file_path = getIntent().getStringExtra("file_path");
mimeType = mime_Type == null ? mimeType : mime_Type;
singleThreadExecutor = Executors.newSingleThreadExecutor();

mInitialPath = file_path == null ? mInitialPath : file_path;
parentFolder = new File(mInitialPath);
initView();
setData();
}

private void setData(){
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
parentContents = isFolderChooser ? listFiles() : listFiles(mimeType);
handler.sendEmptyMessage(0);
}
});
}

private void initView() {
findViewById();
setTitleView();
setRecyclerView();
savePath.setText(parentFolder.getAbsolutePath());
}

//设置标题栏
private void setTitleView() {
titleText.setText("请选择目录");
titleLeft.setVisibility(View.VISIBLE);
titleRight.setVisibility(View.VISIBLE);
titleLeft.setImageResource(R.mipmap.ic_arrow_back_white_24dp);
titleRight.setImageResource(R.mipmap.ic_save_white_24dp);

titleLeft.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FolderChooserActivity.this.finish();
}
});
titleRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ChooserEnd();
}
});
}

private void setRecyclerView() {
mData = new ArrayList<>();
//设置布局管理器
LinearLayoutManager manager = new LinearLayoutManager(this);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(manager);

//分割线
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
.color(0xFFE9E7E8)
.size(1)
.build());

//设置适配器
mAdapter = new FolderChooserAdapter(this, mData, new ItemClickCallback() {
@Override
public void onClick(View view, int position, FolderChooserInfo info) {
onSelection(view, position, info);
}
});
recyclerView.setAdapter(mAdapter);
}

private List getContentsArray() {
List results = new ArrayList<>();
if (parentContents == null) {
if (canGoUp){
FolderChooserInfo info = new FolderChooserInfo();
info.setName("...");
info.setFile(null);
info.setImage(R.mipmap.back);
results.add(info);
}
return results;
}
if (canGoUp){
FolderChooserInfo info = new FolderChooserInfo();
info.setName("...");
info.setFile(null);
info.setImage(R.mipmap.back);
results.add(info);
}
results.addAll(parentContents);
return results;
}

public void onSelection( View view, int position, FolderChooserInfo info) {
if (canGoUp && position == 0) {
if (parentFolder.isFile()) {
parentFolder = parentFolder.getParentFile();
}
parentFolder = parentFolder.getParentFile();
if (parentFolder.getAbsolutePath().equals("/storage/emulated"))
parentFolder = parentFolder.getParentFile();
canGoUp = parentFolder.getParent() != null;
} else {
parentFolder = info.getFile();
canGoUp = true;
if (parentFolder.getAbsolutePath().equals("/storage/emulated"))
parentFolder = Environment.getExternalStorageDirectory();
}
if (parentFolder.isFile()) {
ChooserEnd();
}else{
loading_view.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
setData();
}
}

private List listFiles() {
File[] contents = parentFolder.listFiles();
List results = new ArrayList<>();
if (contents != null) {
for (File fi : contents) {
if (fi.isDirectory()){
FolderChooserInfo info = new FolderChooserInfo();
info.setName(fi.getName());
info.setFile(fi);
info.setImage(fileType(fi));
results.add(info);
}
}
Collections.sort(results, new FolderSorter());
return results;
}
return null;
}

private List listFiles(String mimeType) {
File[] contents = parentFolder.listFiles();
List results = new ArrayList<>();
if (contents != null) {
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
for (File fi : contents) {
if (fi.isDirectory()) {
FolderChooserInfo info = new FolderChooserInfo();
info.setName(fi.getName());
info.setFile(fi);
info.setImage(fileType(fi));
results.add(info);
} else {
if (fileIsMimeType(fi, mimeType, mimeTypeMap)) {
FolderChooserInfo info = new FolderChooserInfo();
info.setName(fi.getName());
info.setFile(fi);
info.setImage(fileType(fi));
results.add(info);
}
}
}
Collections.sort(results, new FileSorter());
return results;
}
return null;
}

boolean fileIsMimeType(File file, String mimeType, MimeTypeMap mimeTypeMap) {
if (mimeType == null || mimeType.equals("*/*")) {
return true;
} else {
// get the file mime type
String filename = file.toURI().toString();
int dotPos = filename.lastIndexOf('.');
if (dotPos == -1) {
return false;
}
String fileExtension = filename.substring(dotPos + 1);
String fileType = mimeTypeMap.getMimeTypeFromExtension(fileExtension);
if (fileType == null) {
return false;
}
// check the 'type/subtype' pattern
if (fileType.equals(mimeType)) {
return true;
}
// check the 'type/*' pattern
int mimeTypeDelimiter = mimeType.lastIndexOf('/');
if (mimeTypeDelimiter == -1) {
return false;
}
String mimeTypeMainType = mimeType.substring(0, mimeTypeDelimiter);
String mimeTypeSubtype = mimeType.substring(mimeTypeDelimiter + 1);
if (!mimeTypeSubtype.equals("*")) {
return false;
}
int fileTypeDelimiter = fileType.lastIndexOf('/');
if (fileTypeDelimiter == -1) {
return false;
}
String fileTypeMainType = fileType.substring(0, fileTypeDelimiter);
if (fileTypeMainType.equals(mimeTypeMainType)) {
return true;
}
}
return false;
}

private static class FileSorter implements Comparator {
@Override
public int compare(FolderChooserInfo lhs, FolderChooserInfo rhs) {
if (lhs.getFile().isDirectory() && !rhs.getFile().isDirectory()) {
return -1;
} else if (!lhs.getFile().isDirectory() && rhs.getFile().isDirectory()) {
return 1;
} else {
return lhs.getName().compareTo(rhs.getName());
}
}
}

private static class FolderSorter implements Comparator {
@Override
public int compare(FolderChooserInfo lhs, FolderChooserInfo rhs) {
return lhs.getName().compareTo(rhs.getName());
}
}

public interface ItemClickCallback{
void onClick(View view, int position, FolderChooserInfo info);
}

private void findViewById(){
titleLeft = (ImageView) findViewById(R.id.title_left);
titleRight = (ImageView) findViewById(R.id.title_right);
titleText = (TextView) findViewById(R.id.title_text);
savePath = (TextView) findViewById(R.id.save_path);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
loading_view = (LinearLayout) findViewById(R.id.loading_view);
}

private void ChooserEnd(){
File result = parentFolder;
Intent intent = new Intent();
intent.putExtra("file_path", result);
setResult(RESULT_OK, intent);
finish();
}

private int fileType(File file){ int image = R.mipmap.type_file; if(file.isDirectory()){ image = R.mipmap.type_folder; }else{ try { // 指定文件类型的图标 String[] token = file.getName().split("\\."); String suffix = token[token.length - 1]; if (suffix.equalsIgnoreCase("txt")) { image = R.mipmap.type_txt; } else if (suffix.equalsIgnoreCase("png") || suffix.equalsIgnoreCase("jpg") || suffix.equalsIgnoreCase("jpeg") || suffix.equalsIgnoreCase("gif")) { image = R.mipmap.type_image; } else if (suffix.equalsIgnoreCase("mp3")) { image = R.mipmap.type_mp3; } else if (suffix.equalsIgnoreCase("mp4") || suffix.equalsIgnoreCase("rmvb") || suffix.equalsIgnoreCase("avi")) { image = R.mipmap.type_video; } else if (suffix.equalsIgnoreCase("apk")) { image = R.mipmap.type_apk; } }catch (Exception e){ e.printStackTrace(); } } return image; }
}
package com.example.folderchooser.folderchooser;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.vi
9b66
ew.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.folderchooser.R;

import java.util.List;

public class FolderChooserAdapter extends RecyclerView.Adapter {

private Context mContext;
private LayoutInflater mInflater;
private List mData;
private FolderChooserActivity.ItemClickCallback callback;

public FolderChooserAdapter(Context mContext, List mData, FolderChooserActivity.ItemClickCallback callback) {
this.mContext = mContext;
this.mData = mData;
this.callback = callback;
mInflater = LayoutInflater.from(mContext);
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.folder_chooser_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final FolderChooserInfo info = mData.get(position);
holder.name.setText(info.getName() == null ? "" : info.getName());

holder.v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.onClick(v, position, info);
}
});
holder.image.setImageResource(info.getImage());
}

@Override
public int getItemCount() {
return mData.size();
}

static class ViewHolder extends RecyclerView.ViewHolder{
ImageView image;
TextView name;
LinearLayout v;

ViewHolder(View view) {
super(view);
image = (ImageView) view.findViewById(R.id.image);
name = (TextView) view.findViewById(R.id.name);
v = (LinearLayout) view.findViewById(R.id.view);
}
}
}
package com.example.folderchooser.folderchooser;

import java.io.File;

public class FolderChooserInfo {

private String name;
private File file;
private int image;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public File getFile() {
return file;
}

public void setFile(File file) {
this.file = file;
}

public int getImage() {
return image;
}

public void setImage(int image) {
this.image = image;
}
}


<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>

<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>


参考:https://github.com/afollestad/material-dialogs#selectors
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息