Android:增强目录选择器对话框

介绍:

每一次你需要在Android应用程序中选择一个SD卡目录,你都得加载一种目录选择器对话框,由它呈现图形界面以便你选择需要的目录。

不幸的是,正如开发人员所预料的,Android不提供任何内置的目录选择器对话框。因此开发人员必须自己写。本文将讲述以增强创建对话框的能力,为Android SD卡实现简单的目录选择器对话框。该流程包含在一个单独的文件中并且不用任何额外资源,除了预定义的Android资源。

android,移动设备开发

执行代码

目录选择器对话框是基于AlertDialog,由子目录的ListView所供给。当前目录路径是显示在AlertDialog标题上。通过点击子目录ListView中的项目完成导航向前到一个目录,然后通过按住“返回”键返回。清单中的子目录是按名称分类的。当通过按住OK键选中需要的目录,一个“注册回调”被唤起,它由已选择目录的完整路径所供给。

代码包含在一个单独的文件DirectoryChooserDialog.java中。它以当前目录的子目录的ListView 加载AlertDialog 并保持追踪导航目录。

执行DirectoryChooserDialog 类定义如下回调界面。

// Callback interface for selected directory
public interface ChosenDirectoryListener 
{    public void onChosenDir(String chosenDir);
}

一个回调可以被注册于DirectoryChooserDialog类构造函数中。

public DirectoryChooserDialog(Context context, ChosenDirectoryListener chosenDirectoryListener);

通过默认创建能力,新目录能够被运用(通过点击“新文件夹”按钮),它可以通过setNewFolderEnabled的方式关闭,当禁用新文件夹按钮隐藏时。

///////////////////////////////////////////////////////////////////////
// setNewFolderEnabled() - enable/disable new folder button
///////////////////////////////////////////////////////////////////////

public void setNewFolderEnabled(boolean isNewFolderEnabled)
{
    m_isNewFolderEnabled = isNewFolderEnabled;
}

public boolean getNewFolderEnabled()
{
    return m_isNewFolderEnabled;
}

DirectoryChooserDialog指定两个公共chooseDirectory 方式来加载目录选择器对话框。一个带有初始目录参数;另一个没有。默认初始目录是SD卡的根目录。

//////////////////////////////////////////////////////////////////////
// chooseDirectory() - load directory chooser dialog for initial
// default sdcard root directory
//////////////////////////////////////////////////////////////////////

public void chooseDirectory();

////////////////////////////////////////////////////////////////////////////////
// chooseDirectory(String dir) - load directory chooser dialog for initial
// input 'dir' directory
////////////////////////////////////////////////////////////////////////////////

public void chooseDirectory(String dir);

DirectoryChooserDialog 类全面执行如下:

// DirectoryChooserDialog.java

package com.example.directorychooser;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnKeyListener;
import android.os.Environment;
import android.text.Editable;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class DirectoryChooserDialog 
{
    private boolean m_isNewFolderEnabled = true;
    private String m_sdcardDirectory = "";
    private Context m_context;
    private TextView m_titleView;
  
    private String m_dir = "";
    private List<String> m_subdirs = null;
    private ChosenDirectoryListener m_chosenDirectoryListener = null;
    private ArrayAdapter<String> m_listAdapter = null;

    //////////////////////////////////////////////////////
    // Callback interface for selected directory
    //////////////////////////////////////////////////////
    public interface ChosenDirectoryListener 
    {
        public void onChosenDir(String chosenDir);
    }

    public DirectoryChooserDialog(Context context, ChosenDirectoryListener chosenDirectoryListener)
    {
        m_context = context;
        m_sdcardDirectory = Environment.getExternalStorageDirectory().getAbsolutePath();
        m_chosenDirectoryListener = chosenDirectoryListener;

        try
        {
            m_sdcardDirectory = new File(m_sdcardDirectory).getCanonicalPath();
        }
        catch (IOException ioe)
        {
        }
    }

    ///////////////////////////////////////////////////////////////////////
    // setNewFolderEnabled() - enable/disable new folder button
    ///////////////////////////////////////////////////////////////////////

    public void setNewFolderEnabled(boolean isNewFolderEnabled)
    {
        m_isNewFolderEnabled = isNewFolderEnabled;
    }

    public boolean getNewFolderEnabled()
    {
        return m_isNewFolderEnabled;
    }

    ///////////////////////////////////////////////////////////////////////
    // chooseDirectory() - load directory chooser dialog for initial
    // default sdcard directory
    ///////////////////////////////////////////////////////////////////////

    public void chooseDirectory()
    {
        // Initial directory is sdcard directory
        chooseDirectory(m_sdcardDirectory);
    }

    ////////////////////////////////////////////////////////////////////////////////
    // chooseDirectory(String dir) - load directory chooser dialog for initial 
    // input 'dir' directory
    ////////////////////////////////////////////////////////////////////////////////

    public void chooseDirectory(String dir)
    {
        File dirFile = new File(dir);
        if (! dirFile.exists() || ! dirFile.isDirectory())
        {
            dir = m_sdcardDirectory;
        }

        try
        {
            dir = new File(dir).getCanonicalPath();
        }
        catch (IOException ioe)
        {
            return;
        }

        m_dir = dir;
        m_subdirs = getDirectories(dir);

        class DirectoryOnClickListener implements DialogInterface.OnClickListener
        {
            public void onClick(DialogInterface dialog, int item) 
            {
                // Navigate into the sub-directory
                m_dir += "/" + ((AlertDialog) dialog).getListView().getAdapter().getItem(item);
                updateDirectory();
            }
        }

    AlertDialog.Builder dialogBuilder = 
    createDirectoryChooserDialog(dir, m_subdirs, new DirectoryOnClickListener());

    dialogBuilder.setPositiveButton("OK", new OnClickListener() 
    {
        @Override
        public void onClick(DialogInterface dialog, int which) 
        {
            // Current directory chosen
            if (m_chosenDirectoryListener != null)
            {
                // Call registered listener supplied with the chosen directory
                m_chosenDirectoryListener.onChosenDir(m_dir);
            }
        }
    }).setNegativeButton("Cancel", null);

    final AlertDialog dirsDialog = dialogBuilder.create();

    dirsDialog.setOnKeyListener(new OnKeyListener() 
    {
        @Override
        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) 
        {
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN)
            {
                // Back button pressed
                if ( m_dir.equals(m_sdcardDirectory) )
                {
                    // The very top level directory, do nothing
                    return false;
                }
                else
                {
                    // Navigate back to an upper directory
                    m_dir = new File(m_dir).getParent();
                    updateDirectory();
                }
    
                return true;
            }
            else
            {
                return false;
            }
        }
    });

    // Show directory chooser dialog
    dirsDialog.show();
}

private boolean createSubDir(String newDir)
{
    File newDirFile = new File(newDir);
    if (! newDirFile.exists() )
    {
        return newDirFile.mkdir();
    }

    return false;
}

private List<String> getDirectories(String dir)
{
    List<String> dirs = new ArrayList<String>();

    try
    {
        File dirFile = new File(dir);
        if (! dirFile.exists() || ! dirFile.isDirectory())
        {
            return dirs;
        }
 
        for (File file : dirFile.listFiles()) 
        {
            if ( file.isDirectory() )
            {
                dirs.add( file.getName() );
            }
        }
    }
    catch (Exception e)
    {
    }

    Collections.sort(dirs, new Comparator<String>()
    {
        public int compare(String o1, String o2) 
        {
            return o1.compareTo(o2);
        }
    });

    return dirs;
}

private AlertDialog.Builder createDirectoryChooserDialog(String title, List<String> listItems,
        DialogInterface.OnClickListener onClickListener)
{
    AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(m_context);

    // Create custom view for AlertDialog title containing 
    // current directory TextView and possible 'New folder' button.
    // Current directory TextView allows long directory path to be wrapped to multiple lines.
    LinearLayout titleLayout = new LinearLayout(m_context);
    titleLayout.setOrientation(LinearLayout.VERTICAL);

    m_titleView = new TextView(m_context);
    m_titleView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    m_titleView.setTextAppearance(m_context, android.R.style.TextAppearance_Large);
    m_titleView.setTextColor( m_context.getResources().getColor(android.R.color.white) );
    m_titleView.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
    m_titleView.setText(title);

    Button newDirButton = new Button(m_context);
    newDirButton.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    newDirButton.setText("New folder");
    newDirButton.setOnClickListener(new View.OnClickListener() 
    {
        @Override
        public void onClick(View v) 
        {
            final EditText input = new EditText(m_context);

            // Show new folder name input dialog
            new AlertDialog.Builder(m_context).
            setTitle("New folder name").
            setView(input).setPositiveButton("OK", new DialogInterface.OnClickListener() 
            {
                public void onClick(DialogInterface dialog, int whichButton) 
                {
                    Editable newDir = input.getText();
                    String newDirName = newDir.toString();
                    // Create new directory
                    if ( createSubDir(m_dir + "/" + newDirName) )
                    {
                        // Navigate into the new directory
                        m_dir += "/" + newDirName;
                        updateDirectory();
                    }
                    else
                    {
                        Toast.makeText(
                        m_context, "Failed to create '" + newDirName + 
                          "' folder", Toast.LENGTH_SHORT).show();
                    }
                }
            }).setNegativeButton("Cancel", null).show(); 
        }
    });

    if (! m_isNewFolderEnabled)
    {
        newDirButton.setVisibility(View.GONE);
    }

    titleLayout.addView(m_titleView);
    titleLayout.addView(newDirButton);

    dialogBuilder.setCustomTitle(titleLayout);

    m_listAdapter = createListAdapter(listItems);

    dialogBuilder.setSingleChoiceItems(m_listAdapter, -1, onClickListener);
    dialogBuilder.setCancelable(false);

    return dialogBuilder;
}

private void updateDirectory()
{
    m_subdirs.clear();
    m_subdirs.addAll( getDirectories(m_dir) );
    m_titleView.setText(m_dir);

    m_listAdapter.notifyDataSetChanged();
}

private ArrayAdapter<String> createListAdapter(List<String> items)
{
    return new ArrayAdapter<String>(m_context, 
      android.R.layout.select_dialog_item, android.R.id.text1, items)
    {
        @Override
        public View getView(int position, View convertView,
        ViewGroup parent) 
        {
            View v = super.getView(position, convertView, parent);

            if (v instanceof TextView)
            {
                // Enable list item (directory) text wrapping
                TextView tv = (TextView) v;
                tv.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
                tv.setEllipsize(null);
            }
            return v;
        }
    };
}
}

用途实例

如下实例表现如何通过点击按钮加载目录选择器对话框。先前选中的目录变为调用下一个对话框的初始目录。

Android,移动设备开发

Android,移动设备开发

Android,移动设备开发

结论:

本文陈述了以创建新的目录来增强目录选择器对话框。

原文地址:https://www.cnblogs.com/elegant-dancer/p/3367703.html