[소스 1] package app.main;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FileList _FileList = new FileList(this);
_FileList.setOnPathChangedListener(_OnPathChanged);
_FileList.setOnFileSelected(_OnFileSelected);
LinearLayout layout = (LinearLayout) findViewById(R.id.LinearLayout01);
layout.addView(_FileList);
_FileList.setPath("/");
_FileList.setFocusable(true);
_FileList.setFocusableInTouchMode(true);
}
private OnPathChangedListener _OnPathChanged = new OnPathChangedListener() {
@Override
public void onChanged(String path) {
((TextView) findViewById(R.id.TextView01)).setText(path);
}
};
private OnFileSelectedListener _OnFileSelected = new OnFileSelectedListener() {
@Override
public void onSelected(String path, String fileName) {
// TODO
}
};
}
15: FileList 클래스는 ListView를 상속받아서 확장하였습니다. layout.xml을 통해서 사용 할 수도 있지만, 쉽게 코드를 읽을 수 있도록 동적 생성하였습니다.
FileList는 두 종류의 이벤트를 지원하고 있습니다.
OnPathChangedListener는 표시하고 있는 폴더가 변경되면 해당 폴더의 전체 Path를 알려줍니다. 28-33: 라인은 OnPathChangedListener 인터페이스의 멤버 메소드를 구현 한 것 입니다.
OnFileSelected는 파일을 선택 했을 경우, 선택된 파일과 파일이 속해있는 폴더의 전체 Path를 알려줍니다. 35-40: 라인은 OnFileSelected 인터페이스의 멤버 메소드를 구현 한 것 입니다.
22: FileList의 setPath(String path) 메소드는 지정된 경로(path) 안에 있는 폴더와 파일 목록을 표시 합니다.
32: TextView를 통해서 경로(path)명이 변경 될 때마다 표시하고 있습니다.
38: 라인에는 파일이 선택되었을 경우 실행하고자 하는 코드를 작성하시면 됩니다.
아래의 FileList 클래스의 소스는 [소스 2]와 같습니다.
[소스 2]
package app.main;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class FileList extends ListView {
public FileList(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public FileList(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public FileList(Context context) {
super(context);
init(context);
}
private void init(Context context) {
_Context = context;
setOnItemClickListener(_OnItemClick);
}
private Context _Context = null;
private ArrayList<String> _List = new ArrayList<String>();
private ArrayList<String> _FolderList = new ArrayList<String>();
private ArrayList<String> _FileList = new ArrayList<String>();
private ArrayAdapter<String> _Adapter = null;
// Property
private String _Path = "";
// Event
private OnPathChangedListener _OnPathChangedListener = null;
private OnFileSelectedListener _OnFileSelectedListener = null;
private boolean openPath(String path) {
_FolderList.clear();
_FileList.clear();
File file = new File(path);
File[] files = file.listFiles();
if (files == null) return false;
for (int i=0; i<files.length; i++) {
if (files[i].isDirectory()) {
_FolderList.add("<" + files[i].getName() + ">");
} else {
_FileList.add(files[i].getName());
}
}
Collections.sort(_FolderList);
Collections.sort(_FileList);
_FolderList.add(0, "<..>");
return true;
}
private void updateAdapter() {
_List.clear();
_List.addAll(_FolderList);
_List.addAll(_FileList);
_Adapter = new ArrayAdapter<String>(_Context, android.R.layout.simple_list_item_1, _List);
setAdapter(_Adapter);
}
public void setPath(String value) {
if (value.length() == 0) {
value = "/";
} else {
String lastChar = value.substring(value.length()-1, value.length());
if (lastChar.matches("/") == false) value = value + "/";
}
if (openPath(value)) {
_Path = value;
updateAdapter();
if (_OnPathChangedListener != null) _OnPathChangedListener.onChanged(value);
}
}
public String getPath() {
return _Path;
}
public void setOnPathChangedListener(OnPathChangedListener value) {
_OnPathChangedListener = value;
}
public OnPathChangedListener getOnPathChangedListener() {
return _OnPathChangedListener;
}
public void setOnFileSelected(OnFileSelectedListener value) {
_OnFileSelectedListener = value;
}
public OnFileSelectedListener getOnFileSelected() {
return _OnFileSelectedListener;
}
public String DelteRight(String value, String border) {
String list[] = value.split(border);
String result = "";
for (int i=0; i<list.length; i++) {
result = result + list[i] + border;
}
return result;
}
private String delteLastFolder(String value) {
String list[] = value.split("/");
String result = "";
for (int i=0; i<list.length-1; i++) {
result = result + list[i] + "/";
}
return result;
}
private String getRealPathName(String newPath) {
String path = newPath.substring(1, newPath.length()-1);
if (path.matches("..")) {
return delteLastFolder(_Path);
} else {
return _Path + path + "/";
}
}
private AdapterView.OnItemClickListener _OnItemClick = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long id) {
String fileName = getItemAtPosition(position).toString();
if (fileName.matches("<.*>")) {
setPath(getRealPathName(fileName));
} else {
if (_OnFileSelectedListener != null) _OnFileSelectedListener.onSelected(_Path, fileName);
}
}
};
}
제가 지금 작성하는 어플리케이션의 경우에는 파일을 선택하는 것은 중요한 요소는 아니기 때문에 위에 있는 정도면 충분하여 우선은 여기까지만 작성 해 봅니다. 추후, 다른 용도가 생기면 개선하여 다시 올리도록 하겠습니다.
마지막으로 위의 예제에서 사용된 layout/main.xml은 아래와 같습니다.
[소스 3]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/LinearLayout01"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:text="@+id/TextView01"
android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</TextView>
</LinearLayout>
첨부파일에 전체 소스가 있습니다. 위에서 설명하지 않은 인터페이스의 경우에는 첨부파일을 참고하시기 바랍니다.