Build your own File Selector Screen on Android

Build your own File Selector Screen on Android

Hello everyone, in this article we are going to talk about a custom File Selector. We will build a custom file selector. We are going to use a dialog and get file and folder list and show. After that we allow the user to select files. We will make an example about this. We are going to use java and android studio in this example.

Now, Let's get started.

Now first I want to share my dialog XML file. Below code block you can see it:

dialog_selectmusic.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="100" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="96"
        >

        <ListView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/lstMusicFiles"
            android:choiceMode="multipleChoice"
            />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:orientation="horizontal"
        android:weightSum="4"
        android:layout_weight="4"
        android:baselineAligned="false"
        >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            >

            <ImageButton
                android:id="@+id/btnGoBackFolder"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/vector_back"
                />
        </LinearLayout>
        
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            >
            <ImageButton
                android:id="@+id/btnCheckAllMusic"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:src="@drawable/vector_checkall" />
        </LinearLayout>
        
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
            <ImageButton
                android:id="@+id/btnAddToPlaylist"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:src="@drawable/vector_add_to_playlist" />
        </LinearLayout>

    </LinearLayout>

</LinearLayout>
It will be seen like below. Android File Selector dialog image
And my listview design XML file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:weightSum="1"
    android:layout_marginTop="1dp"
    android:background="@drawable/list_item_highlight"  >

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:weightSum="1"
        android:layout_marginTop="5dp">
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="75dp"
            android:layout_height="fill_parent">
            
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/imgFileType"
                android:src="@drawable/vector_music"/>
        </LinearLayout>

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="Text"
                android:id="@+id/lblFileName"
                android:layout_marginEnd="10dp"
                android:singleLine="true"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="Text"
                android:id="@+id/lblFileSize"
                android:layout_marginEnd="10dp"
                android:singleLine="true"/>
        </LinearLayout>
    </LinearLayout>
    
    <View
        android:layout_marginTop="2dp"
        android:id="@+id/separator"
        android:background="@color/GumusRengi"
        android:layout_width = "fill_parent"
        android:layout_height="5.0dip"
        />

</LinearLayout>
And it will shown like below: Android File Selector dialog listview item

Our design files are ready now, now let's write some code.

I will keep the datas of the files and folder as fileModels. Create a class named fileModel.java and inside variables what we need. I need below files, you can write what values do you need .You can see the file model below:

fileModel.java

public class fileModel {
    final public String type; //folder or file
    final public String name;
    final public String path;
    final public long size;
    public Boolean isChecked;
    
    public fileModel(String _type, String _name ,String _path, long _size, Boolean _isChecked)
    {
        this.type = _type;
        this.name = _name;
        this.path = _path;
        this.size = _size;
        this.isChecked = _isChecked;
    }
}

And below code block will read the files and folders on device drive.


    private ArrayList<fileModel> fnc_readFolderContent(String _path) {
        ArrayList<fileModel> arrFileList = new ArrayList<>();

        //String path = _path;
        File directory = new File(_path);
        File[] files = directory.listFiles();

        //Order files by Names
        if (files != null && files.length > 1) {
            Arrays.sort(files, new Comparator<File>() {
                @Override
                public int compare(File object1, File object2) {
                    return object1.getName().compareTo(object2.getName());
                }
            });
        }

        //Read all files information
        for (int i = 0; i < files.length; i++) {
            String fileType = files[i].isDirectory() ? "folder" : "file";
            String fileName = files[i].getName();
            String filePath = files[i].getPath();
            long fileSize = files[i].length();
            String fileExtention = filePath.contains(".")  ? filePath.substring(filePath.lastIndexOf(".")) : "";

            //create the file model and initialize them
            fileModel file = new fileModel(fileType, fileName, filePath, fileSize, false);

            //check file is a folder or mp3 file
            //this is optional, I want to show only mp3 files in this application
            if( (fileType.equals("file") && fileExtention.equals(".mp3") ) || fileType.equals("folder") )
                arrFileList.add(file); // add the file models to the Arraylist to retun for the outer function
        }

        return arrFileList;
    } 

And my file Array Adapter. You can see the code block below:


    private class FileListCustomAdapter extends ArrayAdapter<fileModel> {

        final private ArrayList<fileModel> lstFileList;

        public FileListCustomAdapter(Context context, int textViewResourceId, ArrayList<fileModel> xmlList) {
            super(context, textViewResourceId, xmlList);
            this.lstFileList = xmlList;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View row = convertView;
            if (row == null) {
                LayoutInflater inflater = getActivity().getLayoutInflater();
                //My custom list item design is here
                row = inflater.inflate(R.layout.list_item_music_select_file_list, parent, false);
            }
            TextView lblFileName =  row.findViewById(R.id.lblFileName);
            TextView lblFileSize =  row.findViewById(R.id.lblFileSize);
            ImageView imgFileType =  row.findViewById(R.id.imgFileType);

            lblFileName.setText(this.lstFileList.get(position).name);
            lblFileSize.setText( TheFunctions.readableFileSize(this.lstFileList.get(position).size) );
            //set the image type if folder or music file
            imgFileType.setImageDrawable(this.lstFileList.get(position).type.equals("folder") ? getResources().getDrawable(R.drawable.vector_folder) : getResources().getDrawable(R.drawable.vector_unchecked));
            if(lstFileList.get(position).isChecked )
            {
                imgFileType.setImageDrawable(getResources().getDrawable(R.drawable.vector_checked));
            }

            return row;
        }

        //To prevent data resetting when scroolled
        @Override
        public int getCount() {
            return lstFileList.size();
        }

        @Override
        public fileModel getItem(int position) {
            return lstFileList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }
    }

I have written the required methods for these operation below code block will show the dialog which list the all files and folders. Now write some code on that part

First I will create a Dialog component and I will initialize this component at onCreate. Then I will make some configuration for related dialogs. And then we will show it. After that we will show the dialog and manage the button clicks.

Also when we clicked the listview listitem first we have to know it is folder or file. If it is folder we should list the files in clicked folder. And we have to list again. You can see the codes inside below code block. And also if the clicked item is file we want to check the file and add it in arraylist.


public class FragmentCurrentPlaylist extends Fragment implements View.OnClickListener {
    View view;
    String currentMusicFolderPath = "";
    final String baseFolder = Environment.getExternalStorageDirectory().toString();

    Dialog dialog_select_music;

    public FragmentCurrentPlaylist() {
        // Required empty public constructor of fragment
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //Initialize the dialog component
        dialog_select_music = new Dialog(getActivity());
        //Dialog configuration
        dialog_select_music.setTitle("Please Select Music");
         //I shared this XML file above for content of dialog
        dialog_select_music.setContentView(R.layout.dialog_selectmusic); 
        //I want it full screen
        dialog_select_music.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); 
        // disable the cancelling when touch outside of dialog
        dialog_select_music.setCanceledOnTouchOutside(false); 


        //My components in dialog and I will use these components 
        final ListView lstFiles =  dialog_select_music.findViewById(R.id.lstMusicFiles);
        final ImageButton btnAddMusicToPlaylist = dialog_select_music.findViewById(R.id.btnAddToPlaylist);
        final ImageButton btnGoBackFolder = dialog_select_music.findViewById(R.id.btnGoBackFolder);
        final ImageButton btnCheckAllMusic = dialog_select_music.findViewById(R.id.btnCheckAllMusic);

        // I will show this function below, this fnunction will return all file and folders as fileModel
        final ArrayList<fileModel> lstFileList = fnc_readFolderContent(currentMusicFolderPath); 

        // this adapter will load file and folder list with defined below arrayadapter model
        final FileListCustomAdapter adapter = new FileListCustomAdapter(getActivity(), R.layout.list_item_music_select_file_list, lstFileList);
        lstFiles.setAdapter(adapter);

        //Selected files list with arraylist with fileModel class
        final ArrayList<fileModel> lstSelectedFileList = new ArrayList<>();

        //When we click an item of listFiles
        lstFiles.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ImageView imgIsFileChecked = view.findViewById(R.id.imgFileType);

                //when we clicked the item first we have to know it is folder or file
                if (lstFileList.get(position).type.equals("folder")) {
                    //if folder we have to list inside the selected folder
                    currentMusicFolderPath = lstFileList.get(position).path;

                    ArrayList<fileModel> temp_lstFileList = fnc_readFolderContent(currentMusicFolderPath);
                    lstFileList.clear();
                    lstFileList.addAll(fnc_readFolderContent(currentMusicFolderPath));
                    adapter.clear();
                    for (int i = 0; i < temp_lstFileList.size(); i++) {
                        adapter.add(temp_lstFileList.get(i));
                    }
                    adapter.notifyDataSetChanged();
                    ((BaseAdapter) lstFiles.getAdapter()).notifyDataSetChanged();

                } else if (lstFileList.get(position).type.equals("file")) {
                     //if file we check it as checked and add it selected file arraylist
                    if (lstSelectedFileList.indexOf(lstFileList.get(position)) < 0) {
                        lstFileList.get(position).isChecked = true;
                        lstSelectedFileList.add(lstFileList.get(position));
                        imgIsFileChecked.setImageDrawable(getResources().getDrawable(R.drawable.vector_checked));
                        Log.d("event_add", lstFileList.get(position).path);
                    } else {
                        lstFileList.get(position).isChecked = false;
                        lstSelectedFileList.remove(lstFileList.get(position));
                        imgIsFileChecked.setImageDrawable(getResources().getDrawable(R.drawable.vector_unchecked));
                        Log.d("event_remove", lstFileList.get(position).path);
                    }
                }
            }
        });

        btnAddMusicToPlaylist.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog_select_music.dismiss();
                //do whatever you want with selected files
            }
        });

        btnGoBackFolder.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //when goBack, list the folders at upper folder and show them
                if (currentMusicFolderPath.length() > baseFolder.length()) {
                    currentMusicFolderPath = currentMusicFolderPath.substring(0, currentMusicFolderPath.lastIndexOf('/'));
                    Log.d("upper_folder", currentMusicFolderPath);
                    ArrayList<fileModel> temp_lstFileList = fnc_readFolderContent(currentMusicFolderPath);
                    lstFileList.clear();
                    lstFileList.addAll(fnc_readFolderContent(currentMusicFolderPath));
                    adapter.clear();
                    for (int i = 0; i < temp_lstFileList.size(); i++) {
                        adapter.add(temp_lstFileList.get(i));
                    }
                    adapter.notifyDataSetChanged();
                    ((BaseAdapter) lstFiles.getAdapter()).notifyDataSetChanged();
                } else {
                    //When you try to go system files location
                    Toast.makeText(getActivity(), "You can not go back more..."), Toast.LENGTH_SHORT).show();
                }

            }
        });
    }
}

That is all in this article.

Have a good file selecting...

Burak Hamdi TUFAN


Tags


Share this Post

Send with Whatsapp

Post a Comment

Success! Your comment sent to post. It will be showed after confirmation.
Error! There was an error sending your comment.

Comments

  • There is no comment. Be the owner of first comment...