1. 程式人生 > >Android 自定義檔案路徑選擇器

Android 自定義檔案路徑選擇器

文中涉及到檔名稱排序,固定根目錄以及返回上一層在上面,方便選擇等。根據檔案字尾,篩選檔案還沒做。先看效果。

1、效果圖

2、核心程式碼如下

是通過繼承BaseAdapter 完成的,裡面有自定義layout介面。進行管理返回跟目錄以及上一層,方便管理。

package com.filebrowser;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MyAdapter extends BaseAdapter implements View.OnClickListener, AdapterView.OnItemClickListener {
    private String rootPath;
    private LayoutInflater mInflater;
    private Bitmap mIcon3;
    private Bitmap mIcon4;
    private List<File> fileList;
    private View header;
    private View layoutReturnRoot;
    private View layoutReturnPre;
    private TextView curPathTextView;
    private String suffix = "";
    private String currentDirPath;
    private FileSelectListener listener;

    public MyAdapter(View fileSelectListView, String rootPath, String defaultPath) {
        this.rootPath = rootPath;
        Context context = fileSelectListView.getContext();
        mInflater = LayoutInflater.from(context);
        mIcon3 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_fodler);
        mIcon4 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_file);

        curPathTextView = (TextView) fileSelectListView.findViewById(R.id.curPath);
        header = fileSelectListView.findViewById(R.id.layoutFileListHeader);
        layoutReturnRoot = fileSelectListView.findViewById(R.id.layoutReturnRoot);
        layoutReturnPre = fileSelectListView.findViewById(R.id.layoutReturnPre);
        layoutReturnRoot.setOnClickListener(this);
        layoutReturnPre.setOnClickListener(this);
        if (defaultPath != null && !defaultPath.isEmpty()) {
            getFileDir(defaultPath);
        } else {
            getFileDir(rootPath);
        }
        ListView listView = (ListView) fileSelectListView.findViewById(R.id.list);
        listView.setAdapter(this);
        listView.setOnItemClickListener(this);
    }

    private class ViewHolder {
        TextView text;
        ImageView icon;
    }

    public interface FileSelectListener {
        void onFileSelect(File selectedFile);

        void onDirSelect(File selectedDir);
    }

    public void setOnFileSelectListener(FileSelectListener listener) {
        this.listener = listener;
    }

    /**
     * 獲取所選檔案路徑下的所有檔案,並且更新到listview中
     */
    private void getFileDir(String filePath) {
        File file = new File(filePath);
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.isFile()&&!suffix.isEmpty()){
                    return pathname.getName().endsWith(suffix);
                }
                return true;
            }
        });
        fileList = Arrays.asList(files);
        //按名稱排序
        Collections.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                if (o1.isFile() && o2.isDirectory())
                    return 1;
                if (o1.isDirectory() && o2.isFile())
                    return -1;
                return o1.getName().compareTo(o2.getName());
            }
        });

        if (header != null) {
            header.setVisibility(filePath.equals(rootPath) ? View.GONE : View.VISIBLE);
        }

        notifyDataSetChanged();

        if (curPathTextView != null) {
            curPathTextView.setText(filePath);
        }
        currentDirPath = filePath;

        if (listener!=null){
            listener.onDirSelect(file);
        }
    }


    public int getCount() {
        return fileList.size();
    }

    public Object getItem(int position) {
        return fileList.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.file_item, null);
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        File file = fileList.get(position);
        holder.text.setText(file.getName());
        if (file.isDirectory()) {
            holder.icon.setImageBitmap(mIcon3);
        } else {
            holder.icon.setImageBitmap(mIcon4);
        }
        return convertView;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        File file = fileList.get(position);
        if (file.isDirectory()) {
            getFileDir(file.getPath());
        } else {
            if (listener!=null){
                listener.onFileSelect(file);
            }
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.layoutReturnRoot) {
            getFileDir(rootPath);
        } else if (v.getId() == R.id.layoutReturnPre) {
            getFileDir(new File(currentDirPath).getParent());
        }
    }
}

使用的佈局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="@color/white"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/layoutFileSelectList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        android:showDividers="middle|end">

        <TextView
            android:id="@+id/curPath"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="6dp"
            android:paddingLeft="10dp"
            android:textSize="16sp" />

        <LinearLayout
            android:id="@+id/layoutFileListHeader"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:divider="@drawable/shape_divider_line"
            android:showDividers="beginning|middle|end"
            android:orientation="vertical">

            <LinearLayout
                android:id="@+id/layoutReturnRoot"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:paddingLeft="10dp"
                android:gravity="center"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/iv_return_root"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:background="@drawable/icon_back">

                </ImageView>

                <TextView
                    android:id="@+id/tv_return_root"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:gravity="center_vertical"
                    android:paddingLeft="10dp"
                    android:text="@string/ReturnRootDir"
                    android:textSize="16sp">

                </TextView>

            </LinearLayout>

            <LinearLayout
                android:id="@+id/layoutReturnPre"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:paddingLeft="10dp"
                android:gravity="center"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/iv_return_pre"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:background="@drawable/icon_back02">

                </ImageView>

                <TextView
                    android:id="@+id/tv_return_pre"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:gravity="center_vertical"
                    android:paddingLeft="10dp"
                    android:text="@string/ReturnPreDir"
                    android:textSize="16sp">

                </TextView>

            </LinearLayout>

        </LinearLayout>


        <ListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </ListView>

    </LinearLayout>

</LinearLayout>

呼叫方式

package com.filebrowser;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.io.File;

public class FileBrowserActivity extends Activity implements
        View.OnClickListener, MyAdapter.FileSelectListener {
    private TextView curPathTextView;
    private String rootPath = "";
    private MyAdapter listAdapter;
    //初始化進入的目錄,預設目錄
    private String filePath = "";

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_file_browser_acitivity);
        initView();

        //跟目錄
        rootPath = getIntent().getStringExtra("rootPath");
        //指定資料夾
        filePath = getIntent().getStringExtra("path");

        curPathTextView.setText(filePath);
        filePath = filePath.isEmpty() ? rootPath : filePath;
        View layoutFileSelectList = findViewById(R.id.layoutFileSelectList);
        listAdapter = new MyAdapter(layoutFileSelectList, rootPath, filePath);
        listAdapter.setOnFileSelectListener(this);

        findViewById(R.id.btnSure).setOnClickListener(this);
        findViewById(R.id.btnCancel).setOnClickListener(this);
    }

    @Override
    public void finish() {
        Intent intent = new Intent();
        intent.putExtra("file", filePath);
        setResult(RESULT_OK, intent);
        super.finish();
    }

    private void initView() {
        curPathTextView = (TextView) findViewById(R.id.curPath);
    }


    @Override
    public void onFileSelect(File selectedFile) {
        filePath = selectedFile.getPath();
    }

    @Override
    public void onDirSelect(File selectedDir) {
        filePath = selectedDir.getPath();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btnSure:
                finish();
                break;
            case R.id.btnCancel:
                filePath ="";
                finish();
                break;

            default:
                break;

        }
    }

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layoutProgramManagerMainView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:orientation="vertical">

    <include
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        layout="@layout/layout_file_select_list"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_gravity="bottom"
        android:layout_weight="0"
        android:orientation="vertical"
        android:showDividers="beginning">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="horizontal">


            <Button
                android:id="@+id/btnCancel"
                android:layout_width="0dp"
                android:layout_height="40dp"
                android:layout_weight="1"
                android:text="@string/cancel"
                android:textSize="16sp" />
            <Button
                android:id="@+id/btnSure"
                android:layout_width="0dp"
                android:layout_height="40dp"
                android:layout_weight="1"
                android:text="@string/sure"
                android:textSize="16sp" />

        </LinearLayout>
    </LinearLayout>

</LinearLayout>

返回選擇的目錄

package com.filebrowser;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Locale;

public class MainActivity extends Activity {
    public static final int FILE_RESULT_CODE = 1;
    private Button btn_open;
    private TextView changePath;
    private String rootPath;

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

    private void initView() {
        btn_open = (Button) findViewById(R.id.btn_open);
        changePath = (TextView) findViewById(R.id.changePath);
    }

    private void initListener() {
        btn_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openBrowser();
            }
        });

        findViewById(R.id.btn_open1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openBrowser1();
            }
        });
    }

    private void openBrowser() {
        rootPath = System.getenv("SECONDARY_STORAGE");
        if (rootPath == null) {
            rootPath = Environment.getExternalStorageDirectory().toString();
        }
        if ((rootPath.equals(Environment.getExternalStorageDirectory().toString()))) {
            String filePath = rootPath + "/Android";
            Intent intent = new Intent(MainActivity.this, FileBrowserActivity.class);
            //根目錄
            intent.putExtra("rootPath", rootPath);
            //進去指定資料夾
            intent.putExtra("path", filePath);
            startActivityForResult(intent, FILE_RESULT_CODE);
        }
    }

    private void openBrowser1() {
        rootPath = getSdcardPath();
        if (rootPath == null || rootPath.isEmpty()) {
            rootPath = Environment.getExternalStorageDirectory().toString();
        }
        Intent intent = new Intent(MainActivity.this, FileBrowserActivity.class);
        intent.putExtra("rootPath", rootPath);
        intent.putExtra("path", rootPath);
        startActivityForResult(intent, FILE_RESULT_CODE);
    }

    public String getSdcardPath() {
        String sdcardPath = "";
        String[] pathArr = null;
        StorageManager storageManager = (StorageManager) getSystemService(STORAGE_SERVICE);
        try {
            Method getVolumePaths = storageManager.getClass().getMethod("getVolumePaths");
            pathArr = (String[]) getVolumePaths.invoke(storageManager);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if (pathArr != null && pathArr.length >= 3) {
            sdcardPath = pathArr[1];
        }
        return sdcardPath;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (FILE_RESULT_CODE == requestCode) {
            Bundle bundle = null;
            if (data != null && (bundle = data.getExtras()) != null) {
                String path = bundle.getString("file","");
                if(!path.isEmpty()){
                    changePath.setText("選擇路徑為 : " + path);
                }
            }
        }
    }
}

3、最後肯定是許可權

    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

其實後面可以封裝成一個自定義的view 進行繼承LinearLayout進行封裝即可。