2014-09-05 3 views
0

J'écris un DialogFragment pour la navigation sur le système de fichiers, ce qui fonctionne vraiment bien maintenant. J'ai juste un problème.Comment recréer un ListView dans DialogFragment

Les fichiers sont affichés dans un ListView, et lorsque l'utilisateur sélectionne un fichier, cet événement est envoyé à l'activité qui a appelé le fragment sur une interface OnFileSelectedListener. C'est très bien pour les fichiers, mais il est mauvais d'envoyer les noms de répertoire à l'activité, puis de détruire et de recréer le fragment, quand tout ce qui devrait arriver est que le fragment devrait montrer un nouveau répertoire. Cela fait aussi disparaître l'ensemble du Fragement et ensuite le redistribuer, ce qui n'est pas vraiment beau et lisse.

Par ailleurs, tout en utilisant l'activité du fragment doit utiliser la logique pour recréer le fragment, ce qui est loin d'être « ne vous répétez pas. »

Donc, en bref, est-il un moyen de faire un changeout de ListView dans le Fragment? Appeler le AlertDialog.Builder plus d'une fois malheureusement ne fonctionne pas.

Heres mon DialogFragment. J'espère qu'il est autorisé à poster le tout:

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

peut être cela fonctionnera pour vous .. '((BaseAdapter) ListVIEW.getAdapter()) notifyDataSetChanged() ; ' – bGorle

+0

Pourriez-vous à la place avoir un autre fragment, peut-être un ListFragment, avec un ListView dans le xml de ListFragment, qui peut être utilisé pour afficher la liste? Masquer le fragment de dialogue dans le gestionnaire d'événements OnFileSelectedListener et remplir la liste ListFragment, puis l'afficher? Ou peut-être même simplement utiliser un ListView sur le DialogFragment, mais il est préférable d'utiliser les fragments comme ils le devraient, en étant modularisé, chaque fragment étant utilisé pour une chose, un autre fragment pour une autre chose, qui garde le code simple et maintenable. – Bryan

+0

Il s'avère qu'il existe des méthodes pour ajouter(), supprimer() et effacer() l'adaptateur. Merci à Bhr, dont le commentaire me guide dans la bonne direction. Cela fonctionne maintenant. Le vrai problème était d'empêcher le fragment de se dissiper en cliquant sur la liste. –

Répondre

4

Voici ma solution pour une Filebrowser comme DialogFragment. Il s'avère qu'il existe des méthodes pour ajouter() remove() et clean() des éléments à l'adaptateur, de sorte que la réponse à la question initiale était très simple. La partie délicate consistait à empêcher la fermeture du dialogue après la sélection d'un élément de liste. Cette réponse a beaucoup aidé: https://stackoverflow.com/a/15619098/3960095. Voici mon code de travail pour les futurs visiteurs:

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; 
     } 
    } 
} 

et dans votre activité.

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"); 
Questions connexes