这里是一个使用 Kotlin 编写的对话框,可以列出/sdcard中的所有非隐藏文件到一个列表,并提供刷新和退出按钮。长按列表项会弹出上下文菜单,菜单包括删除、重命名和修改时间的功能。

import android.app.AlertDialog
import android.content.Context
import android.os.Environment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import java.io.File
import java.text.SimpleDateFormat
import java.util.*

class FileDialog(context: Context) {

    private val fileDialogView: View = LayoutInflater.from(context).inflate(R.layout.dialog_file, null)
    private val fileList: ListView = fileDialogView.findViewById(R.id.file_list)
    private val refreshButton: Button = fileDialogView.findViewById(R.id.refresh_button)
    private val exitButton: Button = fileDialogView.findViewById(R.id.exit_button)

    private val fileAdapter: FileAdapter = FileAdapter(context)
    private var currentDirectory: File = Environment.getExternalStorageDirectory()

    private var onFileSelectedListener: ((File) -> Unit)? = null

    init {
        fileList.adapter = fileAdapter

        refreshButton.setOnClickListener {
            refreshFileList()
        }

        exitButton.setOnClickListener {
            dismiss()
        }

        fileList.setOnItemLongClickListener { _, view, position, _ ->
            showContextMenu(view, position)
            true
        }

        refreshFileList()
    }

    fun setOnFileSelectedListener(listener: (File) -> Unit) {
        onFileSelectedListener = listener
    }

    fun show() {
        AlertDialog.Builder(fileDialogView.context)
            .setView(fileDialogView)
            .show()
    }

    fun dismiss() {
        fileList.adapter = null
        onFileSelectedListener = null
        currentDirectory = Environment.getExternalStorageDirectory()
        fileDialogView.findViewById<TextView>(R.id.path_text).text = currentDirectory.path
        (fileDialogView.context as? AlertDialog)?.dismiss()
    }

    private fun refreshFileList() {
        val files = currentDirectory.listFiles()?.filter { !it.isHidden }?.sortedBy { it.name } ?: emptyList()
        fileAdapter.setFiles(files)
        fileAdapter.notifyDataSetChanged()
        fileDialogView.findViewById<TextView>(R.id.path_text).text = currentDirectory.path
    }

    private fun showContextMenu(view: View, position: Int) {
        val file = fileAdapter.getItem(position)

        val menu = PopupMenu(view.context, view)
        menu.inflate(R.menu.file_context_menu)
        menu.setOnMenuItemClickListener { menuItem ->
            when (menuItem.itemId) {
                R.id.delete_menu_item -> {
                    file.delete()
                    refreshFileList()
                    true
                }
                R.id.rename_menu_item -> {
                    showRenameDialog(file)
                    true
                }
                R.id.modify_time_menu_item -> {
                    showModifyTimeDialog(file)
                    true
                }
                else -> false
            }
        }
        menu.show()
    }

    private fun showRenameDialog(file: File) {
        val editText = EditText(fileDialogView.context)
        editText.setText(file.name)

        AlertDialog.Builder(fileDialogView.context)
            .setTitle(R.string.rename_dialog_title)
            .setView(editText)
            .setPositiveButton(R.string.ok_button_text) { _, _ ->
                val newName = editText.text.toString()
                val newFile = File(file.parent, newName)
                file.renameTo(newFile)
                refreshFileList()
            }
            .setNegativeButton(R.string.cancel_button_text, null)
            .show()
    }

    private fun showModifyTimeDialog(file: File) {
        val editText = EditText(fileDialogView.context)
        editText.setText(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date(file.lastModified())))

        AlertDialog.Builder(fileDialogView.context)
            .setTitle(R.string.modify_time_dialog_title)
            .setView(editText)
            .setPositiveButton(R.string.ok_button_text) { _, _ ->
                val newTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(editText.text.toString())?.time ?: return@setPositiveButton
                file.setLastModified(newTime)
                refreshFileList()
            }
            .setNegativeButton(R.string.cancel_button_text, null)
            .show()
    }

    private inner class FileAdapter(private val context: Context) : BaseAdapter() {

        private var files: List<File> = emptyList()

        fun setFiles(files: List<File>) {
            this.files = files
        }

        override fun getCount(): Int {
            return files.size
        }

        override fun getItem(position: Int): File {
            return files[position]
        }

        override fun getItemId(position: Int): Long {
            return position.toLong()
        }

        override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
            val view = convertView ?: LayoutInflater.from(context).inflate(R.layout.list_item_file, parent, false)

            val file = getItem(position)

            view.findViewById<TextView>(R.id.filename_text).text = file.name
            view.findViewById<TextView>(R.id.filesize_text).text = if (file.isDirectory) "" else formatFileSize(file.length())
            view.findViewById<TextView>(R.id.filedate_text).text = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date(file.lastModified()))

            view.setOnClickListener {
                if (file.isDirectory) {
                    currentDirectory = file
                    refreshFileList()
                } else {
                    onFileSelectedListener?.invoke(file)
                    dismiss()
                }
            }

            return view
        }

        private fun formatFileSize(size: Long): String {
            val units = arrayOf("B", "KB", "MB", "GB", "TB")
            var fileSize = size.toDouble()
            var unitIndex = 0
            while (fileSize >= 1024 && unitIndex < units.size - 1) {
                fileSize /= 1024
                unitIndex++
            }
            return String.format(Locale.getDefault(), "%.2f %s", fileSize, units[unitIndex])
        }
    }
}

布局文件dialog_file.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="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/path_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:textAppearance="?android:textAppearanceMedium" />

    <ListView
        android:id="@+id/file_list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:divider="@null"
        android:dividerHeight="0dp" />

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

        <Button
            android:id="@+id/refresh_button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/refresh_button_text" />

        <Button
            android:id="@+id/exit_button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/exit_button_text" />

    </LinearLayout>

</LinearLayout>

菜单文件file_context_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/delete_menu_item"
        android:title="@string/delete_menu_item_text" />
    <item
        android:id="@+id/rename_menu_item"
        android:title="@string/rename_menu_item_text" />
    <item
        android:id="@+id/modify_time_menu_item"
        android:title="@string/modify_time_menu_item_text" />
</menu>
Kotlin 实现 SD卡文件浏览对话框,支持刷新、退出、长按菜单功能

原文地址: https://www.cveoy.top/t/topic/lfgi 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录