1 // DirectoryChooserDialog.java 2 3 package com.beloko.idtech; 4 5 import java.io.File; 6 import java.io.IOException; 7 import java.util.ArrayList; 8 import java.util.Collections; 9 import java.util.Comparator; 10 import java.util.List; 11 12 import android.app.AlertDialog; 13 import android.content.Context; 14 import android.content.DialogInterface; 15 import android.content.DialogInterface.OnClickListener; 16 import android.content.DialogInterface.OnKeyListener; 17 import android.os.Environment; 18 import android.text.Editable; 19 import android.util.Log; 20 import android.view.Gravity; 21 import android.view.KeyEvent; 22 import android.view.View; 23 import android.view.ViewGroup; 24 import android.view.ViewGroup.LayoutParams; 25 import android.widget.ArrayAdapter; 26 import android.widget.Button; 27 import android.widget.EditText; 28 import android.widget.LinearLayout; 29 import android.widget.TextView; 30 import android.widget.Toast; 31 32 public class DirectoryChooserDialog 33 { 34 private boolean m_isNewFolderEnabled = true; 35 private String m_sdcardDirectory = ""; 36 private Context m_context; 37 private TextView m_titleView; 38 39 private String m_dir = ""; 40 private List<String> m_subdirs = null; 41 private ChosenDirectoryListener m_chosenDirectoryListener = null; 42 private ArrayAdapter<String> m_listAdapter = null; 43 44 ////////////////////////////////////////////////////// 45 // Callback interface for selected directory 46 ////////////////////////////////////////////////////// 47 public interface ChosenDirectoryListener 48 { onChosenDir(String chosenDir)49 public void onChosenDir(String chosenDir); 50 } 51 DirectoryChooserDialog(Context context, ChosenDirectoryListener chosenDirectoryListener)52 public DirectoryChooserDialog(Context context, ChosenDirectoryListener chosenDirectoryListener) 53 { 54 m_context = context; 55 m_sdcardDirectory = Environment.getExternalStorageDirectory().getAbsolutePath(); 56 m_chosenDirectoryListener = chosenDirectoryListener; 57 58 try 59 { 60 m_sdcardDirectory = new File(m_sdcardDirectory).getCanonicalPath(); 61 } 62 catch (IOException ioe) 63 { 64 } 65 } 66 67 /////////////////////////////////////////////////////////////////////// 68 // setNewFolderEnabled() - enable/disable new folder button 69 /////////////////////////////////////////////////////////////////////// 70 setNewFolderEnabled(boolean isNewFolderEnabled)71 public void setNewFolderEnabled(boolean isNewFolderEnabled) 72 { 73 m_isNewFolderEnabled = isNewFolderEnabled; 74 } 75 getNewFolderEnabled()76 public boolean getNewFolderEnabled() 77 { 78 return m_isNewFolderEnabled; 79 } 80 81 /////////////////////////////////////////////////////////////////////// 82 // chooseDirectory() - load directory chooser dialog for initial 83 // default sdcard directory 84 /////////////////////////////////////////////////////////////////////// 85 chooseDirectory()86 public void chooseDirectory() 87 { 88 // Initial directory is sdcard directory 89 chooseDirectory(m_sdcardDirectory); 90 } 91 92 //////////////////////////////////////////////////////////////////////////////// 93 // chooseDirectory(String dir) - load directory chooser dialog for initial 94 // input 'dir' directory 95 //////////////////////////////////////////////////////////////////////////////// 96 chooseDirectory(String dir)97 public void chooseDirectory(String dir) 98 { 99 File dirFile = new File(dir);; 100 101 Log.d("dir","dir = " + dir); 102 103 if (! dirFile.exists() || ! dirFile.isDirectory()) 104 { 105 dir = m_sdcardDirectory; 106 } 107 108 try 109 { 110 dir = new File(dir).getCanonicalPath(); 111 } 112 catch (IOException ioe) 113 { 114 return; 115 } 116 117 m_dir = dir; 118 119 m_subdirs = getDirectories(dir); 120 121 class DirectoryOnClickListener implements DialogInterface.OnClickListener 122 { 123 public void onClick(DialogInterface dialog, int item) 124 { 125 // Navigate into the sub-directory 126 m_dir += "/" + ((AlertDialog) dialog).getListView().getAdapter().getItem(item); 127 128 try { 129 m_dir = new File(m_dir).getCanonicalPath(); 130 } catch (IOException e) { 131 // TODO Auto-generated catch block 132 e.printStackTrace(); 133 } 134 135 updateDirectory(); 136 } 137 } 138 139 AlertDialog.Builder dialogBuilder = 140 createDirectoryChooserDialog(dir, m_subdirs, new DirectoryOnClickListener()); 141 142 dialogBuilder.setPositiveButton("OK", new OnClickListener() 143 { 144 @Override 145 public void onClick(DialogInterface dialog, int which) 146 { 147 // Current directory chosen 148 if (m_chosenDirectoryListener != null) 149 { 150 // Call registered listener supplied with the chosen directory 151 m_chosenDirectoryListener.onChosenDir(m_dir); 152 } 153 } 154 }).setNegativeButton("Cancel", null); 155 156 final AlertDialog dirsDialog = dialogBuilder.create(); 157 158 dirsDialog.setOnKeyListener(new OnKeyListener() 159 { 160 @Override 161 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) 162 { 163 if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) 164 { 165 // Back button pressed 166 if ( m_dir.equals("/") ) 167 { 168 // The very top level directory, do nothing 169 return false; 170 } 171 else 172 { 173 // Navigate back to an upper directory 174 m_dir = new File(m_dir).getParent(); 175 updateDirectory(); 176 } 177 178 return true; 179 } 180 else 181 { 182 return false; 183 } 184 } 185 }); 186 187 // Show directory chooser dialog 188 dirsDialog.show(); 189 } 190 createSubDir(String newDir)191 private boolean createSubDir(String newDir) 192 { 193 File newDirFile = new File(newDir); 194 if (! newDirFile.exists() ) 195 { 196 return newDirFile.mkdir(); 197 } 198 199 return false; 200 } 201 getDirectories(String dir)202 private List<String> getDirectories(String dir) 203 { 204 List<String> dirs = new ArrayList<String>(); 205 206 dirs.add(".."); 207 208 try 209 { 210 File dirFile = new File(dir); 211 if (! dirFile.exists() || ! dirFile.isDirectory()) 212 { 213 return dirs; 214 } 215 216 for (File file : dirFile.listFiles()) 217 { 218 if ( file.isDirectory() ) 219 { 220 dirs.add( file.getName() ); 221 } 222 } 223 } 224 catch (Exception e) 225 { 226 } 227 228 Collections.sort(dirs, new Comparator<String>() 229 { 230 public int compare(String o1, String o2) 231 { 232 return o1.compareTo(o2); 233 } 234 }); 235 236 return dirs; 237 } 238 createDirectoryChooserDialog(String title, List<String> listItems, DialogInterface.OnClickListener onClickListener)239 private AlertDialog.Builder createDirectoryChooserDialog(String title, List<String> listItems, 240 DialogInterface.OnClickListener onClickListener) 241 { 242 AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(m_context); 243 244 // Create custom view for AlertDialog title containing 245 // current directory TextView and possible 'New folder' button. 246 // Current directory TextView allows long directory path to be wrapped to multiple lines. 247 LinearLayout titleLayout = new LinearLayout(m_context); 248 titleLayout.setOrientation(LinearLayout.VERTICAL); 249 250 m_titleView = new TextView(m_context); 251 m_titleView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); 252 m_titleView.setTextAppearance(m_context, android.R.style.TextAppearance_Large); 253 m_titleView.setTextColor( m_context.getResources().getColor(android.R.color.white) ); 254 m_titleView.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL); 255 m_titleView.setText(title); 256 257 Button newDirButton = new Button(m_context); 258 newDirButton.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); 259 newDirButton.setText("New folder"); 260 newDirButton.setOnClickListener(new View.OnClickListener() 261 { 262 @Override 263 public void onClick(View v) 264 { 265 final EditText input = new EditText(m_context); 266 267 // Show new folder name input dialog 268 new AlertDialog.Builder(m_context). 269 setTitle("New folder name"). 270 setView(input).setPositiveButton("OK", new DialogInterface.OnClickListener() 271 { 272 public void onClick(DialogInterface dialog, int whichButton) 273 { 274 Editable newDir = input.getText(); 275 String newDirName = newDir.toString(); 276 // Create new directory 277 if ( createSubDir(m_dir + "/" + newDirName) ) 278 { 279 // Navigate into the new directory 280 m_dir += "/" + newDirName; 281 updateDirectory(); 282 } 283 else 284 { 285 Toast.makeText( 286 m_context, "Failed to create '" + newDirName + 287 "' folder", Toast.LENGTH_SHORT).show(); 288 } 289 } 290 }).setNegativeButton("Cancel", null).show(); 291 } 292 }); 293 294 if (! m_isNewFolderEnabled) 295 { 296 newDirButton.setVisibility(View.GONE); 297 } 298 299 titleLayout.addView(m_titleView); 300 titleLayout.addView(newDirButton); 301 302 dialogBuilder.setCustomTitle(titleLayout); 303 304 m_listAdapter = createListAdapter(listItems); 305 306 dialogBuilder.setSingleChoiceItems(m_listAdapter, -1, onClickListener); 307 dialogBuilder.setCancelable(false); 308 309 return dialogBuilder; 310 } 311 updateDirectory()312 private void updateDirectory() 313 { 314 m_subdirs.clear(); 315 m_subdirs.addAll( getDirectories(m_dir) ); 316 m_titleView.setText(m_dir); 317 318 m_listAdapter.notifyDataSetChanged(); 319 } 320 createListAdapter(List<String> items)321 private ArrayAdapter<String> createListAdapter(List<String> items) 322 { 323 return new ArrayAdapter<String>(m_context, 324 android.R.layout.select_dialog_item, android.R.id.text1, items) 325 { 326 @Override 327 public View getView(int position, View convertView, 328 ViewGroup parent) 329 { 330 View v = super.getView(position, convertView, parent); 331 332 if (v instanceof TextView) 333 { 334 // Enable list item (directory) text wrapping 335 TextView tv = (TextView) v; 336 tv.getLayoutParams().height = LayoutParams.WRAP_CONTENT; 337 tv.setEllipsize(null); 338 } 339 return v; 340 } 341 }; 342 } 343 }