2014-09-05 2 views
0

Я пишу DialogFragment для просмотра файловой системы, которая работает очень хорошо. У меня только одна проблема.Как воссоздать ListView в DialogFragment

Файлы отображаются в ListView, и когда пользователь выбирает файл, это событие отправляется в Activity, который вызвал фрагмент поверх интерфейса OnFileSelectedListener. Это нормально для файлов, но неправильно посылать имена каталогов для активности, а затем уничтожать и воссоздавать фрагмент, когда все, что должно произойти, состоит в том, что фрагмент должен показывать новый каталог. Это также приводит к исчезновению целого Fragement, а затем к повторению, что не очень приятно и гладко.

Кроме того, каждая деятельность, использующая Фрагмент, должна использовать логику воссоздания Фрагмента, которая далека от «не повторяйте себя».

Итак, вкратце, есть ли способ сделать изменение списка в фрагменте? Вызов AlertDialog.Builder не раз печально не работает.

Heres my DialogFragment. Я надеюсь, что это нормально, чтобы получить возможность отправлять все это:

package de.fusionsystems.firmenlaufmonitor; 

import java.io.File; 
import java.util.ArrayList; 
import java.util.Arrays; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.app.Dialog; 
import android.app.DialogFragment; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.DialogInterface.OnClickListener; 
import android.content.SharedPreferences; 
import android.content.SharedPreferences.Editor; 
import android.graphics.drawable.Drawable; 
import android.os.Bundle; 
import android.preference.PreferenceManager; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.TextView; 

public class FileChooserFragment extends DialogFragment { 
    private OnFileSelectedListener mCallback; 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     return createDialog(); 
    } 

    private AlertDialog createDialog(){ 
     // Create the AlertDialog object and return it 
     SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity()); 
     ArrayList<File> files = getFilesInDir(options.getString("BaseDir", "")); 
     ArrayList<ListEntry> fileEntries = new ArrayList<ListEntry>(); 

     if (!isBaseDir(options.getString("BaseDir", ""))){ 
      fileEntries.add(new ListEntry("..", getResources().getDrawable(R.drawable.ic_folder))); 
     } 

     for (File file : files){    
      if (file.isDirectory()){ 
       fileEntries.add(new ListEntry(file.getName(),getResources().getDrawable(R.drawable.ic_folder))); 
      }else{ 
       if (file.getName().endsWith(".kml")){ 
        fileEntries.add(new ListEntry(file.getName(),getResources().getDrawable(R.drawable.ic_file))); 
       } 
      } 
     } 

     final FileAdapter adapter = new FileAdapter(getActivity(), fileEntries); 
     OnClickListener clickListener = new OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       String path; 
       SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity()); 
       if (adapter.getItem(which).name.equals("..")){ 
        //navigate back 
        path = options.getString("BaseDir", "/"); 
        path=path.substring(0, path.length()); 
        path=path.substring(0,path.lastIndexOf("/")); 
        path = !path.equals("")?path:("/"); 
       }else { 
        path = options.getString("BaseDir", ""); 
        path += ((path.equals("/"))?(""):("/"))+adapter.getItem(which).name; 
       } 
       Log.d("Path", path); 
       Editor editor = options.edit(); 
       File dirTest = new File(path); 
       if (dirTest.isDirectory()){ 
        editor.putString("BaseDir", path); 
        editor.commit(); 
        //mCallback.onFileSelected(""); 
        //createDialog(); 
        //*******************DO THE RIGHT THING HERE*********************** 
       }else{ 
        mCallback.onFileSelected(path); 
       } 
      } 
     }; 
     // Use the Builder class for convenient dialog construction 
     AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
     builder.setAdapter(adapter, clickListener) 
       .setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int id) { 
         dismiss(); 
        } 
       }); 
     builder.setTitle("Datei wählen"); 
     return builder.create(); 
     } 

    private ArrayList<File> getFilesInDir(String dir) { 
     File folder = new File(dir); 
     if (!folder.exists()){ 
      folder = new File("/"); 
      if (!folder.exists()){ 
       Log.e("FileBrowser","Something's really fishy"); 
      } 
     } 
     ArrayList<File> fileList = new ArrayList<File>(Arrays.asList(folder.listFiles())); 
     return fileList; 
    } 

    private boolean isBaseDir(String dir) { 
     File folder = new File(dir); 
      if (!folder.exists()){ 
       folder = new File("/"); 
       if (!folder.exists()){ 
        Log.e("FileBrowser","Something's really fishy"); 
       } 
      } 
     File baseDir = new File("/"); 
     if (folder.equals(baseDir)){ 
      return true; 
     }else{ 
      return false; 
     } 
    } 

    // Container Activity must implement this interface 
    public interface OnFileSelectedListener { 
     public void onFileSelected(String file); 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     // This makes sure that the container activity has implemented 
     // the callback interface. If not, it throws an exception 
     try { 
      mCallback = (OnFileSelectedListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + " must implement OnHeadlineSelectedListener"); 
     } 
    } 

    class ListEntry { 
     public String name; 
     public Drawable item ; 

     public ListEntry(String name, Drawable item) { 
      this.name = name; 
      this.item = item; 
     } 
    } 

    class FileAdapter extends ArrayAdapter<ListEntry>{ 

     public FileAdapter(Context context, ArrayList<ListEntry> fileEntry) { 
      super(context, R.layout.filechooser_list_item,fileEntry); 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent){ 
       ListEntry entry = getItem(position);  
       // Check if an existing view is being reused, otherwise inflate the view 
       if (convertView == null) { 
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.filechooser_list_item, parent, false); 
       } 
       // Lookup view for data population 
       TextView filechooserEntry = (TextView) convertView.findViewById(R.id.filechooser_entry); 
       // Populate the data into the template view using the data object 
       filechooserEntry.setText(entry.name); 
       filechooserEntry.setCompoundDrawablesWithIntrinsicBounds(entry.item, null, null, null); 
       // Return the completed view to render on screen 
       return convertView; 
     } 
    } 
} 
+0

может быть это будет работать для вас .. '((BaseAdapter) ListVIEW.getAdapter()) notifyDataSetChanged() ; ' – bGorle

+0

Не могли бы вы иметь еще один фрагмент, возможно, ListFragment, с ListView в xml ListFragment, который можно использовать для отображения списка? Скрыть фрагмент диалога в обработчике событий OnFileSelectedListener и заполнить список ListFragment, а затем показать его? Или, возможно, просто используйте ListView на DialogFragment, но лучше использовать фрагменты так, как они предназначены, путем модуляции, каждый фрагмент используется для одной вещи, другой фрагмент, используемый для другой вещи, который сохраняет код простым и ремонтопригодны. – Bryan

+0

Оказалось, что есть методы для добавления(), remove() и очистки() адаптера. Благодаря Бру, кто комментирует, я правильно подхожу. Его работы сейчас. Реальная сложная часть заключалась в том, чтобы предотвратить фрагментацию Фрагмента при нажатии на Список. –

ответ

4

Вот мое решение для FileBrowser как DialogFragment. Оказывается, есть способы добавить() remove() и clean() элементы к адаптеру, поэтому ответ на начальный вопрос был прост. Сложная часть заключалась в том, чтобы запретить закрытие диалогового окна после выбора элемента «Список». Этот ответ очень помог: https://stackoverflow.com/a/15619098/3960095. Вот мой рабочий код для будущих посетителей:

package de.yourCompany.yourProject; 

import java.io.File; 
import java.util.ArrayList; 
import java.util.Arrays; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.app.Dialog; 
import android.app.DialogFragment; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.DialogInterface.OnClickListener; 
import android.content.SharedPreferences; 
import android.content.SharedPreferences.Editor; 
import android.graphics.drawable.Drawable; 
import android.os.Bundle; 
import android.preference.PreferenceManager; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.TextView; 

public class FileChooserFragment extends DialogFragment{ 
    private OnFileSelectedListener mCallback; 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     // Create the AlertDialog object and return it 
     final FileAdapter adapter = new FileAdapter(getActivity(), new ArrayList<ListEntry>());    
     adapter.getFiles();  
     OnClickListener clickListener = new OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
      //do nothing here to prevent dismiss after click  
      } 
     }; 
     // Use the Builder class for convenient dialog construction 
     AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
     builder.setAdapter(adapter, clickListener) 
       .setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int id) { 
        } 
       }); 
     builder.setTitle("Datei wählen"); 
     final AlertDialog theDialog = builder.show(); 
     theDialog.getListView().setOnItemClickListener(new OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
       String path; 
       SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity()); 
       if (adapter.getItem(position).name.equals("..")){ 
        //navigate back 
        path = options.getString("BaseDir", "/"); 
        path=path.substring(0, path.length()); 
        path=path.substring(0,path.lastIndexOf("/")); 
        path = !path.equals("")?path:("/"); 
       }else { 
        //get the Slashes right and navigate forward 
        path = options.getString("BaseDir", ""); 
        path += ((path.equals("/"))?(""):("/"))+adapter.getItem(position).name; 
       } 
       Editor editor = options.edit(); 
       File dirTest = new File(path); 
       if (dirTest.isDirectory()){ 
        editor.putString("BaseDir", path); 
        editor.commit(); 
        adapter.clear(); 
        adapter.getFiles(); 
       }else{ 
        mCallback.onFileSelected(path); 
        theDialog.dismiss(); 
       } 

      } 
     }); 
     return theDialog; 
    } 

    private boolean isBaseDir(String dir) { 
     File folder = new File(dir); 
      if (!folder.exists()){ 
       folder = new File("/"); 
       if (!folder.exists()){ 
        Log.wtf("FileBrowser","Something's really fishy"); 
       } 
      } 
     File baseDir = new File("/"); 
     if (folder.equals(baseDir)){ 
      return true; 
     }else{ 
      return false; 
     } 
    } 

    // Container Activity must implement this interface 
    public interface OnFileSelectedListener { 
     public void onFileSelected(String file); 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     // This makes sure that the container activity has implemented 
     // the callback interface. If not, it throws an exception 
     try { 
      mCallback = (OnFileSelectedListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + " must implement OnHeadlineSelectedListener"); 
     } 
    } 

    class ListEntry { 
     public String name; 
     public Drawable item ; 

     public ListEntry(String name, Drawable item) { 
      this.name = name; 
      this.item = item; 
     } 
    } 

    class FileAdapter extends ArrayAdapter<ListEntry>{ 

     //show only files with the suffix FILE_SUFFIX, use "*" to show all files; 
     private static final String FILE_SUFFIX = ".kml"; 

     public FileAdapter(Context context, ArrayList<ListEntry> fileEntry) { 
      super(context, R.layout.filechooser_list_item,fileEntry); 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent){ 
       ListEntry entry = getItem(position);  
       // Check if an existing view is being reused, otherwise inflate the view 
       if (convertView == null) { 
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.filechooser_list_item, parent, false); 
       } 
       // Lookup view for data population 
       TextView filechooserEntry = (TextView) convertView.findViewById(R.id.filechooser_entry); 
       // Populate the data into the template view using the data object 
       filechooserEntry.setText(entry.name); 
       filechooserEntry.setCompoundDrawablesWithIntrinsicBounds(entry.item, null, null, null); 
       // Return the completed view to render on screen 
       return convertView; 
     } 

     private FileAdapter getFiles() { 
      SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity()); 
      ArrayList<File> files = getFilesInDir(options.getString("BaseDir", "")); 

      if (!isBaseDir(options.getString("BaseDir", ""))){ 
       this.add(new ListEntry("..", getResources().getDrawable(R.drawable.ic_folder))); 
      } 

      for (File file : files){    
       if (file.isDirectory()){ 
        this.add(new ListEntry(file.getName(),getResources().getDrawable(R.drawable.ic_folder))); 
       }else{ 
        if (file.getName().endsWith(FILE_SUFFIX)||FILE_SUFFIX.equals("*")){ 
         this.add(new ListEntry(file.getName(),getResources().getDrawable(R.drawable.ic_file))); 
        } 
       } 
      } 
     return this; 
     } 

     private ArrayList<File> getFilesInDir(String dir) { 
      File folder = new File(dir); 
      if (!folder.exists()){ 
       folder = new File("/"); 
       if (!folder.exists()){ 
        Log.wtf("FileBrowser","Something's really fishy"); 
       } 
      } 
      ArrayList<File> fileList; 
      if (folder.listFiles()!=null){ 
       fileList = new ArrayList<File>(Arrays.asList(folder.listFiles())); 
      }else{ 
       fileList = new ArrayList<File>(); 
      } 
      return fileList; 
     } 
    } 
} 

и в вашей деятельности:.

public class YourActivity extends Activity implements FileChooserFragment.OnFileSelectedListener{ 

@Override 
public void onFileSelected(String file) { 
//Do whatever you want to do with the files 
} 

// And whereever you want to start the Fragment: 
FileChooserFragment fileFragment = new FileChooserFragment(); 
fileFragment.show(getFragmentManager(), "fileChooser"); 
Смежные вопросы