Android文件管理器:如何实现SD卡文件夹跳转查看功能?
Hey there! Let's get your file manager's folder navigation working properly. I'll break down exactly what you need to do step by step, using standard Android practices that fit with your existing code.
First, we need to make your list items respond to taps. Assuming you're using a ListView (adjust if you're using RecyclerView), add an item click listener in your MainActivity's onCreate method:
// Initialize your list and adapter first (you probably already have this) ListView folderListView = findViewById(R.id.your_list_view_id); ArrayAdapter<String> folderAdapter = new ArrayAdapter<>(this, R.layout.list_item, R.id.folder_text_id, new ArrayList<>()); folderListView.setAdapter(folderAdapter); // Add the click listener folderListView.setOnItemClickListener((parent, view, position, id) -> { // Get the full path of the clicked folder (make sure your adapter stores paths, not just names!) String selectedFolderPath = folderAdapter.getItem(position); // Load and display subfolders for this path loadFolderContents(selectedFolderPath); });
If you were only storing folder names in your adapter, switch to storing full absolute paths—this is critical for navigating to subfolders.
Replace your root-only folder loading code with a flexible method that can load any directory's contents. This will handle both the initial root directory and any subfolder you tap:
// Keep a class-level variable to track your current directory path private String currentDirectoryPath; private ArrayAdapter<String> folderAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Initialize variables and load root directory on start folderAdapter = new ArrayAdapter<>(this, R.layout.list_item, R.id.folder_text_id, new ArrayList<>()); currentDirectoryPath = Environment.getExternalStorageDirectory().getAbsolutePath(); loadFolderContents(currentDirectoryPath); } private void loadFolderContents(String targetPath) { List<String> subfolders = new ArrayList<>(); File targetDirectory = new File(targetPath); // Validate the directory exists and is accessible if (targetDirectory.exists() && targetDirectory.isDirectory()) { // Filter to only include folders (exclude files) File[] folderFiles = targetDirectory.listFiles(file -> file.isDirectory()); if (folderFiles != null) { for (File folder : folderFiles) { subfolders.add(folder.getAbsolutePath()); // Store full path for navigation } } } // Update the adapter with new data folderAdapter.clear(); folderAdapter.addAll(subfolders); folderAdapter.notifyDataSetChanged(); // Optional: Update the app bar to show current folder name getSupportActionBar().setTitle(targetDirectory.getName()); }
Let users navigate back to the parent folder by enabling the up button in the action bar:
First, enable the up button in onCreate:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Then handle the up button click:
@Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { File currentDir = new File(currentDirectoryPath); File parentDir = currentDir.getParentFile(); if (parentDir != null) { // Move up to parent directory currentDirectoryPath = parentDir.getAbsolutePath(); loadFolderContents(currentDirectoryPath); } else { // We're already at root—no action needed, or reload root if you want loadFolderContents(Environment.getExternalStorageDirectory().getAbsolutePath()); } return true; } return super.onOptionsItemSelected(item); }
Don't forget to handle storage permissions—this is a common pitfall!
Add these permissions to your AndroidManifest.xml:
<!-- For Android 12 and below --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- For Android 13+ (media folders) --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- For full file access (Android 11+; requires Google Play review) --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
Request permissions at runtime in MainActivity:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 101); return; } } // Initialize adapter and load root directory if permissions are granted folderAdapter = new ArrayAdapter<>(this, R.layout.list_item, R.id.folder_text_id, new ArrayList<>()); currentDirectoryPath = Environment.getExternalStorageDirectory().getAbsolutePath(); loadFolderContents(currentDirectoryPath); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 101) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permissions granted—load root directory currentDirectoryPath = Environment.getExternalStorageDirectory().getAbsolutePath(); loadFolderContents(currentDirectoryPath); } else { Toast.makeText(this, "Storage permission is required to access folders", Toast.LENGTH_SHORT).show(); } } }
- If taps don't register: Check that your
list_item.xmldoesn't have views withandroid:clickable="true"orandroid:focusable="true"—these will block the list item's click event. - If subfolders don't show up: Verify the
FileFilteris correctly checkingfile.isDirectory(), and that the target path is valid (useLog.dto print the path if needed). - Scoped Storage issues: For Android 10+, if you need access to non-media folders, consider using the Storage Access Framework (SAF) instead of
MANAGE_EXTERNAL_STORAGEif possible, as the latter requires special Play Store review.
内容的提问来源于stack exchange,提问作者Dagget

