废话没有,先看效果
第一步:创建MainActivity
import android.app.Activity;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import com.rdsa.singleselectedfileorfolder.R;import java.util.ArrayList;public class MainActivity extends AppCompatActivity { public Context mContext; private Button selectFile, selectFolder, mSelectFile, mSelectFolder; private TextView result; private Activity activity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.mContext = this; this.activity = this; setContentView(R.layout.activity_main); initView(); initData(); initEvent(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == ChooseFileOrDirActivity.RequestCode && resultCode == ChooseFileOrDirActivity.ResultCode) { ArrayList<String> resPath = data.getStringArrayListExtra(ChooseFileOrDirActivity.ResultData); StringBuffer sb = new StringBuffer(); for(String item : resPath) { sb.append(item).append("rn"); } result.setText(sb.toString()); } } private void initView() { this.result = super.findViewById(R.id.result); this.selectFile = super.findViewById(R.id.selectFile); this.selectFolder = super.findViewById(R.id.selectFolder); this.mSelectFile = super.findViewById(R.id.mSelectFile); this.mSelectFolder = super.findViewById(R.id.mSelectFolder); } private void initData() { } private void initEvent() { selectFile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(activity, ChooseFileOrDirActivity.class); intent.putExtra(ChooseFileOrDirActivity.EnterVar, ChooseFileOrDirActivity.SingleFile); activity.startActivityForResult(intent, ChooseFileOrDirActivity.RequestCode); } }); selectFolder.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(activity, ChooseFileOrDirActivity.class); intent.putExtra(ChooseFileOrDirActivity.EnterVar, ChooseFileOrDirActivity.SingleFolder); activity.startActivityForResult(intent, ChooseFileOrDirActivity.RequestCode); } }); mSelectFile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(activity, ChooseFileOrDirActivity.class); intent.putExtra(ChooseFileOrDirActivity.EnterVar, ChooseFileOrDirActivity.MultiFile); activity.startActivityForResult(intent, ChooseFileOrDirActivity.RequestCode); } }); mSelectFolder.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(activity, ChooseFileOrDirActivity.class); intent.putExtra(ChooseFileOrDirActivity.EnterVar, ChooseFileOrDirActivity.MultiFolder); activity.startActivityForResult(intent, ChooseFileOrDirActivity.RequestCode); } }); }}
第二步:创建MainActivity布局文件activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.rdsa.selectedfileorfolder.MainActivity"> <Button android:id="@+id/selectFolder" android:text="文件夹选择(单选)" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/selectFile" android:text="文件选择(单选)" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/mSelectFolder" android:text="文件夹选择(多选)" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/mSelectFile" android:text="文件选择(多选)" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/result" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Wait for Result" /></LinearLayout>
第三步:创建目录数据存储类FileOrDirBeans
public class FileOrDirBeans { String isFile, name, isCheckVisible, isChecked, absolutePath ; public FileOrDirBeans(String... params) { this.isFile = params[0]; this.name = params[1]; this.isCheckVisible = params[2]; this.isChecked = params[3]; this.absolutePath = params[4]; } public String getIsFile() { return isFile; } public void setIsFile(String isFile) { this.isFile = isFile; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIsCheckVisible() { return isCheckVisible; } public void setIsCheckVisible(String isCheckVisible) { this.isCheckVisible = isCheckVisible; } public String getIsChecked() { return isChecked; } public void setIsChecked(String isChecked) { this.isChecked = isChecked; } public String getAbsolutePath() { return absolutePath; } public void setAbsolutePath(String absolutePath) { this.absolutePath = absolutePath; }}
第四步:创建文件浏览ChooseFileOrDirActivity
import android.Manifest;import android.app.Activity;import android.content.Intent;import android.content.pm.PackageManager;import android.os.Build;import android.os.Bundle;import android.os.Environment;import android.view.KeyEvent;import android.view.View;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;import com.rdsa.singleselectedfileorfolder.R;import java.io.File;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;public class ChooseFileOrDirActivity extends Activity { public static final String EnterVar = "EnterVar"; public static final String ResultData = "SELECTED"; public static final int RequestCode = 888; public static final int ResultCode = 999; public static final int SingleFile = 1000; public static final int SingleFolder = 2000; public static final int MultiFile = 3000; public static final int MultiFolder = 2001; private String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath(); private static final int REQUESCODE = 5; private static final String NEED_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE; private ListView listView4File; private TextView noDataTip; private Button btChose; private List<String> data; private ArrayList<FileOrDirBeans> fileOrDirList; private FileAdapter fileAdapter; private int enterVar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ly_choose_file_or_folder); this.enterVar = this.getIntent().getIntExtra(EnterVar, SingleFile); this.initView(); this.initData(); this.initEvent(); } private void initData() { this.listView4File.setEmptyView(noDataTip); this.data = new ArrayList<>(); this.fileOrDirList = new ArrayList<>(); this.fileAdapter = new FileAdapter(this, fileOrDirList, enterVar); this.listView4File.setAdapter(fileAdapter); if (Build.VERSION.SDK_INT >= 23) { // 判断系统版本是否大于6.0 if (checkSelfPermission(NEED_PERMISSION) == PackageManager.PERMISSION_GRANTED) { //检查是否有读写权限 loadDataFromPath(rootPath, enterVar);//从路径中加载数据 } else { requestPermissions(new String[]{NEED_PERMISSION}, REQUESCODE); // 申请权限 } } else { loadDataFromPath(rootPath, enterVar);//系统版本小于6.0直接加载数据 } } private void loadDataFromPath(final String mPath, final int type) { this.data.clear(); // data为 ListView 中要显示的数据 this.fileOrDirList.clear(); new Thread() { public void run() { super.run(); data = orderByName(mPath, type == SingleFolder || type == MultiFolder); fileOrDirList = getBeans(data, type); runOnUiThread(new Runnable() {@Overridepublic void run() { fileAdapter.setData(data, fileOrDirList);//将数据载入适配器当中} }); } }.start(); } private ArrayList<FileOrDirBeans> getBeans(List<String> fileList, final int type) { ArrayList<FileOrDirBeans> resultList = new ArrayList<>(); for(String fileItem : fileList) { File file = new File(fileItem); String isFile = String.valueOf(file.isFile()); String isCheckVisible = (file.isFile() || type == SingleFolder || type == MultiFolder) ? "true" : "false";; FileOrDirBeans bean = new FileOrDirBeans(isFile, file.getName(), isCheckVisible, "false", fileItem); resultList.add(bean); } return resultList; } private void initView() { listView4File = findViewById(R.id.rvFileView); noDataTip = findViewById(R.id.noDataTip); } private void initEvent() { fileAdapter.setEvent(new FileAdapter.Event() { @Override public void enterNextDir(String path) { rootPath = path; loadDataFromPath(rootPath, enterVar); } }); findViewById(R.id.btChose).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(); intent.putStringArrayListExtra(ResultData, fileAdapter.getSelectData()); setResult(ResultCode, intent); finish(); } }); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUESCODE && permissions[0].equals(NEED_PERMISSION)) { loadDataFromPath(rootPath, enterVar); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {//点击的是返回键 if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {//按键的按下事件 if (rootPath.trim().equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {return super.onKeyDown(keyCode, event); } else {File file = new File(rootPath);if (!file.exists()) { return super.onKeyDown(keyCode, event);}rootPath = file.getParent();loadDataFromPath(rootPath, enterVar);return false; } } } return super.onKeyDown(keyCode, event); } public static ArrayList<String> orderByName(String filePath, boolean excludeFile) { ArrayList<String> FileNameList = new ArrayList<String>(); File file = new File(filePath); File[] files = file.listFiles(); List fileList = Arrays.asList(files); Collections.sort(fileList, new Comparator<File>() { @Override public int compare(File o1, File o2) { if (o1.isDirectory() && o2.isFile())return -1; if (o1.isFile() && o2.isDirectory())return 1; return o1.getName().compareTo(o2.getName()); } }); for (File itemFile : files) { if(itemFile.getName().startsWith(".")) { continue; } else { if(itemFile.isFile() && excludeFile) {continue; } FileNameList.add(itemFile.getAbsolutePath()); //往集合中添加符合条件的数据 } } return FileNameList; }}
第五步:创建ChooseFileOrDirActivity布局文件ly_choose_file_or_folder.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:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#F9F9FA"> <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> <Button android:id="@+id/btChose" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="5dp" android:background="@drawable/bg_button" android:text="确定" android:textColor="#458B74" /> </RelativeLayout> <ListView android:id="@+id/rvFileView" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/noDataTip" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical|center_horizontal" android:text="没有数据可用,返回上一层" /></LinearLayout>
第六步:创建ListView的数据容器类FileAdapter
import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.CheckBox;import android.widget.CompoundButton;import android.widget.ImageView;import android.widget.TextView;import com.rdsa.singleselectedfileorfolder.R;import java.util.ArrayList;import java.util.List;public class FileAdapter extends BaseAdapter { private Context context; private Event event; private ArrayList<String> selectData; private ArrayList<FileOrDirBeans> fileOrDirList; private LayoutInflater mLayoutInflater; // 将 Item 的 XML 转换成 View private final int enterVar; public FileAdapter(Context context, final ArrayList<FileOrDirBeans> fileOrDirList, int enterVar) { this.context = context; this.selectData = new ArrayList<>(); this.mLayoutInflater = LayoutInflater.from(context); // context 必须是界面所在的 context this.enterVar = enterVar; this.fileOrDirList = fileOrDirList; } @Override public int getCount() { return this.fileOrDirList.size(); } @Override // 数据项 public Object getItem(int position) { return fileOrDirList.get(position); } @Override public long getItemId(int position) { return position; } @Override // 显示的内容 public View getView(final int position, View convertView, ViewGroup viewGroup) { ViewHolder viewHolder; if(convertView == null) { convertView = mLayoutInflater.inflate(R.layout.filechoose_layout_fileitme, null); viewHolder = new ViewHolder(); viewHolder.icon = convertView.findViewById(R.id.icon); viewHolder.fileName = convertView.findViewById(R.id.fileName); viewHolder.checkBox = convertView.findViewById(R.id.checkBox); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder)convertView.getTag(); } final FileOrDirBeans bean = fileOrDirList.get(position); final String absPath = bean.getAbsolutePath(); bean.setIsChecked("false"); // 初始化一个boolean值 来判断是否被选中 for (String s : selectData) { // 遍历选中的集合 if (s.trim().equals(absPath)) { // 如果集合中的子元素与适配其中的路径相同 bean.setIsChecked("true"); // 判断已被选中 break; //终止循环 } } viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {//设置checkBox的点击事件 if (isChecked) {//选中状态if (selectData.contains(absPath)) {//如果集合中包含了该元素则直接返回 if (enterVar == ChooseFileOrDirActivity.SingleFile || enterVar == ChooseFileOrDirActivity.SingleFolder) { selectData.clear(); selectData.add(absPath); }} else {//否则添加 if(enterVar == ChooseFileOrDirActivity.SingleFile || enterVar == ChooseFileOrDirActivity.SingleFolder) { selectData.clear(); } selectData.add(absPath);} } else {//未选中状态if (selectData.contains(absPath)) {//如果集合中包含了该元素则移除 selectData.remove(absPath);} else {//否则 返回 return;} } notifyDataSetChanged(); } }); viewHolder.icon.setImageDrawable(Boolean.parseBoolean(bean.getIsFile()) ? context.getResources().getDrawable(R.drawable._16_file) : context.getResources().getDrawable(R.drawable._16_folder)); viewHolder.fileName.setText(bean.getName()); viewHolder.checkBox.setVisibility((Boolean.parseBoolean(bean.isCheckVisible))? View.VISIBLE : View.GONE); viewHolder.checkBox.setChecked(Boolean.parseBoolean(bean.getIsChecked())); viewHolder.fileName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(!Boolean.parseBoolean(bean.getIsFile())) {event.enterNextDir(fileOrDirList.get(position).getAbsolutePath()); } } }); return convertView; } static class ViewHolder { private ImageView icon; private TextView fileName; private CheckBox checkBox; } public interface Event { void enterNextDir(String path);//进入下一个文件夹 } public void setData(List<String> data, ArrayList<FileOrDirBeans> fileOrDirList) { this.fileOrDirList.clear(); this.fileOrDirList.addAll(fileOrDirList); notifyDataSetChanged(); } public void setEvent(Event event) { this.event = event; } public ArrayList<String> getSelectData() { return selectData; }}
第七步:创建FileAdapter每一项的布局文件filechoose_layout_fileitme.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="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:layout_alignParentStart="true" android:layout_centerVertical="true" android:src="@drawable/file" /> <TextView android:id="@+id/fileName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:paddingRight="50dp" android:layout_toRightOf="@+id/icon" android:layout_centerVertical="true" android:text="TextView" /> <CheckBox android:id="@+id/checkBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:layout_marginEnd="8dp" /></RelativeLayout>
第八步:AndroidManifest 增加对文件操作的授权
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
第九步:用到的图片资源_16_file.jpg"和_16_folder.jpg"