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


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.view.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; } } 
                  
                 
                
               
              
             
            
           
         
        
        
       
       
      
      
     
     

      
      

      
      

    
       
       

    
       
       

        
        
        

        
        
        
    
       
       

    
       
       

    
       
       
        
        
        
    
       
       

      
      
      
      

      
      

    
       
       
    
       
       

      
      

      
      

      
      

    
       
       

    
       
       


      
      
      
      

      
      

    
       
       

    
       
       

    
       
       


      
      
      
      

      
      

    
       
       

    
       
       
        
        
        
            
         
         
                
          
          

                
          
          
            
         
         
        
        
        
        
        
        
    
       
       


      
      


参考:https://github.com/afollestad/material-dialogs#selectors

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值